blob: 8c900c2d9abb6b82d89e0b3b2be2a3a12e7151a3 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003 * Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#ifdef CONFIG_CTRL_IFACE
12
13#ifdef CONFIG_CTRL_IFACE_UNIX
14#include <dirent.h>
15#endif /* CONFIG_CTRL_IFACE_UNIX */
16
17#include "common/wpa_ctrl.h"
18#include "utils/common.h"
19#include "utils/eloop.h"
20#include "utils/edit.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "utils/list.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "common/version.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070023#include "common/ieee802_11_defs.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070024#ifdef ANDROID
25#include <cutils/properties.h>
26#endif /* ANDROID */
27
28
29static const char *wpa_cli_version =
30"wpa_cli v" VERSION_STR "\n"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080031"Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032
33
34static const char *wpa_cli_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080035"This software may be distributed under the terms of the BSD license.\n"
36"See README for more details.\n";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037
38static const char *wpa_cli_full_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080039"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040"\n"
41"Redistribution and use in source and binary forms, with or without\n"
42"modification, are permitted provided that the following conditions are\n"
43"met:\n"
44"\n"
45"1. Redistributions of source code must retain the above copyright\n"
46" notice, this list of conditions and the following disclaimer.\n"
47"\n"
48"2. Redistributions in binary form must reproduce the above copyright\n"
49" notice, this list of conditions and the following disclaimer in the\n"
50" documentation and/or other materials provided with the distribution.\n"
51"\n"
52"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53" names of its contributors may be used to endorse or promote products\n"
54" derived from this software without specific prior written permission.\n"
55"\n"
56"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67"\n";
68
69static struct wpa_ctrl *ctrl_conn;
70static struct wpa_ctrl *mon_conn;
71static int wpa_cli_quit = 0;
72static int wpa_cli_attached = 0;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070073static int wpa_cli_connected = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074static int wpa_cli_last_id = 0;
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
82static int ping_interval = 5;
83static int interactive = 0;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070084static char *ifname_prefix = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070085
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080086struct cli_txt_entry {
87 struct dl_list list;
88 char *txt;
89};
90
91static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
92static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
93static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070094static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070097static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070098static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070099static void wpa_cli_close_connection(void);
100static char * wpa_cli_get_default_ifname(void);
101static char ** wpa_list_cmd_list(void);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700102
103
104static void usage(void)
105{
106 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107 "[-a<action file>] \\\n"
108 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
109 "[command..]\n"
110 " -h = help (show this usage text)\n"
111 " -v = shown version information\n"
112 " -a = run in daemon mode executing the action file based on "
113 "events from\n"
114 " wpa_supplicant\n"
115 " -B = run a daemon in the background\n"
116 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
117 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700118 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700119}
120
121
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800122static void cli_txt_list_free(struct cli_txt_entry *e)
123{
124 dl_list_del(&e->list);
125 os_free(e->txt);
126 os_free(e);
127}
128
129
130static void cli_txt_list_flush(struct dl_list *list)
131{
132 struct cli_txt_entry *e;
133 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
134 cli_txt_list_free(e);
135}
136
137
138static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
139 const char *txt)
140{
141 struct cli_txt_entry *e;
142 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
143 if (os_strcmp(e->txt, txt) == 0)
144 return e;
145 }
146 return NULL;
147}
148
149
150static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
151{
152 struct cli_txt_entry *e;
153 e = cli_txt_list_get(txt_list, txt);
154 if (e)
155 cli_txt_list_free(e);
156}
157
158
159static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
160{
161 u8 addr[ETH_ALEN];
162 char buf[18];
163 if (hwaddr_aton(txt, addr) < 0)
164 return;
165 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
166 cli_txt_list_del(txt_list, buf);
167}
168
169
170#ifdef CONFIG_P2P
171static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
172{
173 const char *end;
174 char *buf;
175 end = os_strchr(txt, ' ');
176 if (end == NULL)
177 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700178 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800179 if (buf == NULL)
180 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800181 cli_txt_list_del(txt_list, buf);
182 os_free(buf);
183}
184#endif /* CONFIG_P2P */
185
186
187static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
188{
189 struct cli_txt_entry *e;
190 e = cli_txt_list_get(txt_list, txt);
191 if (e)
192 return 0;
193 e = os_zalloc(sizeof(*e));
194 if (e == NULL)
195 return -1;
196 e->txt = os_strdup(txt);
197 if (e->txt == NULL) {
198 os_free(e);
199 return -1;
200 }
201 dl_list_add(txt_list, &e->list);
202 return 0;
203}
204
205
206#ifdef CONFIG_P2P
207static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
208{
209 u8 addr[ETH_ALEN];
210 char buf[18];
211 if (hwaddr_aton(txt, addr) < 0)
212 return -1;
213 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
214 return cli_txt_list_add(txt_list, buf);
215}
216
217
218static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
219{
220 const char *end;
221 char *buf;
222 int ret;
223 end = os_strchr(txt, ' ');
224 if (end == NULL)
225 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700226 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800227 if (buf == NULL)
228 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800229 ret = cli_txt_list_add(txt_list, buf);
230 os_free(buf);
231 return ret;
232}
233#endif /* CONFIG_P2P */
234
235
236static char ** cli_txt_list_array(struct dl_list *txt_list)
237{
238 unsigned int i, count = dl_list_len(txt_list);
239 char **res;
240 struct cli_txt_entry *e;
241
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700242 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800243 if (res == NULL)
244 return NULL;
245
246 i = 0;
247 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
248 res[i] = os_strdup(e->txt);
249 if (res[i] == NULL)
250 break;
251 i++;
252 }
253
254 return res;
255}
256
257
258static int get_cmd_arg_num(const char *str, int pos)
259{
260 int arg = 0, i;
261
262 for (i = 0; i <= pos; i++) {
263 if (str[i] != ' ') {
264 arg++;
265 while (i <= pos && str[i] != ' ')
266 i++;
267 }
268 }
269
270 if (arg > 0)
271 arg--;
272 return arg;
273}
274
275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276static int str_starts(const char *src, const char *match)
277{
278 return os_strncmp(src, match, os_strlen(match)) == 0;
279}
280
281
282static int wpa_cli_show_event(const char *event)
283{
284 const char *start;
285
286 start = os_strchr(event, '>');
287 if (start == NULL)
288 return 1;
289
290 start++;
291 /*
292 * Skip BSS added/removed events since they can be relatively frequent
293 * and are likely of not much use for an interactive user.
294 */
295 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
296 str_starts(start, WPA_EVENT_BSS_REMOVED))
297 return 0;
298
299 return 1;
300}
301
302
303static int wpa_cli_open_connection(const char *ifname, int attach)
304{
305#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
306 ctrl_conn = wpa_ctrl_open(ifname);
307 if (ctrl_conn == NULL)
308 return -1;
309
310 if (attach && interactive)
311 mon_conn = wpa_ctrl_open(ifname);
312 else
313 mon_conn = NULL;
314#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
315 char *cfile = NULL;
316 int flen, res;
317
318 if (ifname == NULL)
319 return -1;
320
321#ifdef ANDROID
322 if (access(ctrl_iface_dir, F_OK) < 0) {
323 cfile = os_strdup(ifname);
324 if (cfile == NULL)
325 return -1;
326 }
327#endif /* ANDROID */
328
329 if (cfile == NULL) {
330 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
331 cfile = os_malloc(flen);
332 if (cfile == NULL)
333 return -1;
334 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
335 ifname);
336 if (res < 0 || res >= flen) {
337 os_free(cfile);
338 return -1;
339 }
340 }
341
342 ctrl_conn = wpa_ctrl_open(cfile);
343 if (ctrl_conn == NULL) {
344 os_free(cfile);
345 return -1;
346 }
347
348 if (attach && interactive)
349 mon_conn = wpa_ctrl_open(cfile);
350 else
351 mon_conn = NULL;
352 os_free(cfile);
353#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
354
355 if (mon_conn) {
356 if (wpa_ctrl_attach(mon_conn) == 0) {
357 wpa_cli_attached = 1;
358 if (interactive)
359 eloop_register_read_sock(
360 wpa_ctrl_get_fd(mon_conn),
361 wpa_cli_mon_receive, NULL, NULL);
362 } else {
363 printf("Warning: Failed to attach to "
364 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700365 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700366 return -1;
367 }
368 }
369
370 return 0;
371}
372
373
374static void wpa_cli_close_connection(void)
375{
376 if (ctrl_conn == NULL)
377 return;
378
379 if (wpa_cli_attached) {
380 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
381 wpa_cli_attached = 0;
382 }
383 wpa_ctrl_close(ctrl_conn);
384 ctrl_conn = NULL;
385 if (mon_conn) {
386 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
387 wpa_ctrl_close(mon_conn);
388 mon_conn = NULL;
389 }
390}
391
392
393static void wpa_cli_msg_cb(char *msg, size_t len)
394{
395 printf("%s\n", msg);
396}
397
398
399static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
400{
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700401 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700402 size_t len;
403 int ret;
404
405 if (ctrl_conn == NULL) {
406 printf("Not connected to wpa_supplicant - command dropped.\n");
407 return -1;
408 }
Dmitry Shmidtd3e385e2013-06-05 11:06:13 -0700409 if (ifname_prefix) {
410 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
411 ifname_prefix, cmd);
412 buf[sizeof(buf) - 1] = '\0';
413 cmd = buf;
414 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415 len = sizeof(buf) - 1;
416 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
417 wpa_cli_msg_cb);
418 if (ret == -2) {
419 printf("'%s' command timed out.\n", cmd);
420 return -2;
421 } else if (ret < 0) {
422 printf("'%s' command failed.\n", cmd);
423 return -1;
424 }
425 if (print) {
426 buf[len] = '\0';
427 printf("%s", buf);
428 if (interactive && len > 0 && buf[len - 1] != '\n')
429 printf("\n");
430 }
431 return 0;
432}
433
434
435static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
436{
437 return _wpa_ctrl_command(ctrl, cmd, 1);
438}
439
440
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700441static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
442 char *argv[])
443{
444 int i, res;
445 char *pos, *end;
446
447 pos = buf;
448 end = buf + buflen;
449
450 res = os_snprintf(pos, end - pos, "%s", cmd);
451 if (res < 0 || res >= end - pos)
452 goto fail;
453 pos += res;
454
455 for (i = 0; i < argc; i++) {
456 res = os_snprintf(pos, end - pos, " %s", argv[i]);
457 if (res < 0 || res >= end - pos)
458 goto fail;
459 pos += res;
460 }
461
462 buf[buflen - 1] = '\0';
463 return 0;
464
465fail:
466 printf("Too long command\n");
467 return -1;
468}
469
470
471static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
472 int argc, char *argv[])
473{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700474 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700475 if (argc < min_args) {
476 printf("Invalid %s command - at least %d argument%s "
477 "required.\n", cmd, min_args,
478 min_args > 1 ? "s are" : " is");
479 return -1;
480 }
481 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
482 return -1;
483 return wpa_ctrl_command(ctrl, buf);
484}
485
486
487static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
488{
489 return wpa_ctrl_command(ctrl, "IFNAME");
490}
491
492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700493static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
494{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800495 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
496 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
497 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
498 return wpa_ctrl_command(ctrl, "STATUS-WPS");
Dmitry Shmidt56052862013-10-04 10:23:25 -0700499 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
500 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800501 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502}
503
504
505static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
506{
507 return wpa_ctrl_command(ctrl, "PING");
508}
509
510
511static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
513 return wpa_ctrl_command(ctrl, "RELOG");
514}
515
516
517static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
518{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700519 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700520}
521
522
523static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
524{
525 return wpa_ctrl_command(ctrl, "MIB");
526}
527
528
529static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
530{
531 return wpa_ctrl_command(ctrl, "PMKSA");
532}
533
534
535static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
536{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700537 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700538 return 0;
539}
540
541
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700542static char ** wpa_cli_complete_help(const char *str, int pos)
543{
544 int arg = get_cmd_arg_num(str, pos);
545 char **res = NULL;
546
547 switch (arg) {
548 case 1:
549 res = wpa_list_cmd_list();
550 break;
551 }
552
553 return res;
554}
555
556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700557static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
558{
559 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
560 return 0;
561}
562
563
564static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
565{
566 wpa_cli_quit = 1;
567 if (interactive)
568 eloop_terminate();
569 return 0;
570}
571
572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
574{
575 char cmd[256];
576 int res;
577
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700578 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800579 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700580 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
581 printf("Too long SET command.\n");
582 return -1;
583 }
584 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700585 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700586
587 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
588}
589
590
591static char ** wpa_cli_complete_set(const char *str, int pos)
592{
593 int arg = get_cmd_arg_num(str, pos);
594 const char *fields[] = {
595 /* runtime values */
596 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
597 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
598 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
599 "wps_fragment_size", "wps_version_number", "ampdu",
600 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
601 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
602 "no_keep_alive",
603 /* global configuration parameters */
604 "eapol_version", "ap_scan", "disable_scan_offload",
605 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
606 "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
607 "driver_param", "dot11RSNAConfigPMKLifetime",
608 "dot11RSNAConfigPMKReauthThreshold",
609 "dot11RSNAConfigSATimeout",
610 "update_config", "load_dynamic_eap", "uuid", "device_name",
611 "manufacturer", "model_name", "model_number", "serial_number",
612 "device_type", "os_version", "config_methods",
613 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
614 "p2p_listen_reg_class", "p2p_listen_channel",
615 "p2p_oper_reg_class", "p2p_oper_channel",
616 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
617 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
618 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
619 "p2p_ignore_shared_freq", "country", "bss_max_count",
620 "bss_expiration_age", "bss_expiration_scan_count",
621 "filter_ssids", "filter_rssi", "max_num_sta",
622 "disassoc_low_ack", "hs20", "interworking", "hessid",
623 "access_network_type", "pbc_in_m1", "autoscan",
624 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
625 "wps_nfc_dev_pw", "ext_password_backend",
626 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
627 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
Dmitry Shmidt051af732013-10-22 13:52:46 -0700628 "ignore_old_scan_res", "freq_list", "external_sim"
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700629 };
630 int i, num_fields = sizeof(fields) / sizeof(fields[0]);
631
632 if (arg == 1) {
633 char **res = os_calloc(num_fields + 1, sizeof(char *));
634 if (res == NULL)
635 return NULL;
636 for (i = 0; i < num_fields; i++) {
637 res[i] = os_strdup(fields[i]);
638 if (res[i] == NULL)
639 return res;
640 }
641 return res;
642 }
643
644 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
645 return cli_txt_list_array(&bsses);
646
647 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700648}
649
650
651static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
652{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700653 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700654}
655
656
657static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
658{
659 return wpa_ctrl_command(ctrl, "LOGOFF");
660}
661
662
663static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
664{
665 return wpa_ctrl_command(ctrl, "LOGON");
666}
667
668
669static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
670 char *argv[])
671{
672 return wpa_ctrl_command(ctrl, "REASSOCIATE");
673}
674
675
676static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
677 char *argv[])
678{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700679 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700680}
681
682
683static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
684{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700685 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700686}
687
688
689static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
690 char *argv[])
691{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700692 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700693}
694
695
696static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
697 char *argv[])
698{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700699 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700700}
701
702
703static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
704 char *argv[])
705{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700706 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707}
708
709
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700710static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
711{
712 char cmd[256];
713 int res;
714
715 if (argc < 1)
716 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
717 else
718 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
719 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
720 printf("Too long BSS_FLUSH command.\n");
721 return -1;
722 }
723 return wpa_ctrl_command(ctrl, cmd);
724}
725
726
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700727static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
728 char *argv[])
729{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700730 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700731}
732
733
734static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
735{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700736 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700737}
738
739
740static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
741{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700742 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743}
744
745
746static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
747{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700748 if (argc == 0) {
749 printf("Invalid WPS_PIN command: need one or two arguments:\n"
750 "- BSSID: use 'any' to select any\n"
751 "- PIN: optional, used only with devices that have no "
752 "display\n");
753 return -1;
754 }
755
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700756 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700757}
758
759
760static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
761 char *argv[])
762{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700763 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700764}
765
766
767static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
768 char *argv[])
769{
770 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
771}
772
773
Dmitry Shmidt04949592012-07-19 12:16:46 -0700774#ifdef CONFIG_WPS_NFC
775
776static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
777{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700778 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700779}
780
781
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800782static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
783 char *argv[])
784{
785 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
786}
787
788
Dmitry Shmidt04949592012-07-19 12:16:46 -0700789static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
790 char *argv[])
791{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700792 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700793}
794
795
796static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
797 char *argv[])
798{
799 int ret;
800 char *buf;
801 size_t buflen;
802
803 if (argc != 1) {
804 printf("Invalid 'wps_nfc_tag_read' command - one argument "
805 "is required.\n");
806 return -1;
807 }
808
809 buflen = 18 + os_strlen(argv[0]);
810 buf = os_malloc(buflen);
811 if (buf == NULL)
812 return -1;
813 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
814
815 ret = wpa_ctrl_command(ctrl, buf);
816 os_free(buf);
817
818 return ret;
819}
820
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800821
822static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
823 char *argv[])
824{
825 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
826}
827
828
829static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
830 char *argv[])
831{
832 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
833}
834
835
836static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
837 char *argv[])
838{
839 int ret;
840 char *buf;
841 size_t buflen;
842
843 if (argc != 1) {
844 printf("Invalid 'nfc_rx_handover_req' command - one argument "
845 "is required.\n");
846 return -1;
847 }
848
849 buflen = 21 + os_strlen(argv[0]);
850 buf = os_malloc(buflen);
851 if (buf == NULL)
852 return -1;
853 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
854
855 ret = wpa_ctrl_command(ctrl, buf);
856 os_free(buf);
857
858 return ret;
859}
860
861
862static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
863 char *argv[])
864{
865 int ret;
866 char *buf;
867 size_t buflen;
868
869 if (argc != 1) {
870 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
871 "is required.\n");
872 return -1;
873 }
874
875 buflen = 21 + os_strlen(argv[0]);
876 buf = os_malloc(buflen);
877 if (buf == NULL)
878 return -1;
879 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
880
881 ret = wpa_ctrl_command(ctrl, buf);
882 os_free(buf);
883
884 return ret;
885}
886
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800887
888static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
889 char *argv[])
890{
891 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
892}
893
Dmitry Shmidt04949592012-07-19 12:16:46 -0700894#endif /* CONFIG_WPS_NFC */
895
896
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700897static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
898{
899 char cmd[256];
900 int res;
901
902 if (argc == 2)
903 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
904 argv[0], argv[1]);
905 else if (argc == 5 || argc == 6) {
906 char ssid_hex[2 * 32 + 1];
907 char key_hex[2 * 64 + 1];
908 int i;
909
910 ssid_hex[0] = '\0';
911 for (i = 0; i < 32; i++) {
912 if (argv[2][i] == '\0')
913 break;
914 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
915 }
916
917 key_hex[0] = '\0';
918 if (argc == 6) {
919 for (i = 0; i < 64; i++) {
920 if (argv[5][i] == '\0')
921 break;
922 os_snprintf(&key_hex[i * 2], 3, "%02x",
923 argv[5][i]);
924 }
925 }
926
927 res = os_snprintf(cmd, sizeof(cmd),
928 "WPS_REG %s %s %s %s %s %s",
929 argv[0], argv[1], ssid_hex, argv[3], argv[4],
930 key_hex);
931 } else {
932 printf("Invalid WPS_REG command: need two arguments:\n"
933 "- BSSID of the target AP\n"
934 "- AP PIN\n");
935 printf("Alternatively, six arguments can be used to "
936 "reconfigure the AP:\n"
937 "- BSSID of the target AP\n"
938 "- AP PIN\n"
939 "- new SSID\n"
940 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
941 "- new encr (NONE, WEP, TKIP, CCMP)\n"
942 "- new key\n");
943 return -1;
944 }
945
946 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
947 printf("Too long WPS_REG command.\n");
948 return -1;
949 }
950 return wpa_ctrl_command(ctrl, cmd);
951}
952
953
954static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
955 char *argv[])
956{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700957 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700958}
959
960
961static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
962 char *argv[])
963{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700964 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700965}
966
967
968static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
969 char *argv[])
970{
971 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
972
973}
974
975
976static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
977 char *argv[])
978{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979 if (argc < 2) {
980 printf("Invalid WPS_ER_PIN command: need at least two "
981 "arguments:\n"
982 "- UUID: use 'any' to select any\n"
983 "- PIN: Enrollee PIN\n"
984 "optional: - Enrollee MAC address\n");
985 return -1;
986 }
987
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700988 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989}
990
991
992static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
993 char *argv[])
994{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700995 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700996}
997
998
999static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
1000 char *argv[])
1001{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002 if (argc != 2) {
1003 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1004 "- UUID: specify which AP to use\n"
1005 "- PIN: AP PIN\n");
1006 return -1;
1007 }
1008
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001009 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001010}
1011
1012
1013static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1014 char *argv[])
1015{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 if (argc != 2) {
1017 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1018 "arguments:\n"
1019 "- UUID: specify which AP to use\n"
1020 "- Network configuration id\n");
1021 return -1;
1022 }
1023
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001024 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025}
1026
1027
1028static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1029 char *argv[])
1030{
1031 char cmd[256];
1032 int res;
1033
1034 if (argc == 5 || argc == 6) {
1035 char ssid_hex[2 * 32 + 1];
1036 char key_hex[2 * 64 + 1];
1037 int i;
1038
1039 ssid_hex[0] = '\0';
1040 for (i = 0; i < 32; i++) {
1041 if (argv[2][i] == '\0')
1042 break;
1043 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1044 }
1045
1046 key_hex[0] = '\0';
1047 if (argc == 6) {
1048 for (i = 0; i < 64; i++) {
1049 if (argv[5][i] == '\0')
1050 break;
1051 os_snprintf(&key_hex[i * 2], 3, "%02x",
1052 argv[5][i]);
1053 }
1054 }
1055
1056 res = os_snprintf(cmd, sizeof(cmd),
1057 "WPS_ER_CONFIG %s %s %s %s %s %s",
1058 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1059 key_hex);
1060 } else {
1061 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1062 "- AP UUID\n"
1063 "- AP PIN\n"
1064 "- new SSID\n"
1065 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1066 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1067 "- new key\n");
1068 return -1;
1069 }
1070
1071 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1072 printf("Too long WPS_ER_CONFIG command.\n");
1073 return -1;
1074 }
1075 return wpa_ctrl_command(ctrl, cmd);
1076}
1077
1078
Dmitry Shmidt04949592012-07-19 12:16:46 -07001079#ifdef CONFIG_WPS_NFC
1080static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1081 char *argv[])
1082{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001083 if (argc != 2) {
1084 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1085 "arguments:\n"
1086 "- WPS/NDEF: token format\n"
1087 "- UUID: specify which AP to use\n");
1088 return -1;
1089 }
1090
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001091 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001092}
1093#endif /* CONFIG_WPS_NFC */
1094
1095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001096static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1097{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001098 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001099}
1100
1101
1102static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1103{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001104 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001105}
1106
1107
1108static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1109{
1110 char cmd[256], *pos, *end;
1111 int i, ret;
1112
1113 if (argc < 2) {
1114 printf("Invalid IDENTITY command: needs two arguments "
1115 "(network id and identity)\n");
1116 return -1;
1117 }
1118
1119 end = cmd + sizeof(cmd);
1120 pos = cmd;
1121 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1122 argv[0], argv[1]);
1123 if (ret < 0 || ret >= end - pos) {
1124 printf("Too long IDENTITY command.\n");
1125 return -1;
1126 }
1127 pos += ret;
1128 for (i = 2; i < argc; i++) {
1129 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1130 if (ret < 0 || ret >= end - pos) {
1131 printf("Too long IDENTITY command.\n");
1132 return -1;
1133 }
1134 pos += ret;
1135 }
1136
1137 return wpa_ctrl_command(ctrl, cmd);
1138}
1139
1140
1141static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1142{
1143 char cmd[256], *pos, *end;
1144 int i, ret;
1145
1146 if (argc < 2) {
1147 printf("Invalid PASSWORD command: needs two arguments "
1148 "(network id and password)\n");
1149 return -1;
1150 }
1151
1152 end = cmd + sizeof(cmd);
1153 pos = cmd;
1154 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1155 argv[0], argv[1]);
1156 if (ret < 0 || ret >= end - pos) {
1157 printf("Too long PASSWORD command.\n");
1158 return -1;
1159 }
1160 pos += ret;
1161 for (i = 2; i < argc; i++) {
1162 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1163 if (ret < 0 || ret >= end - pos) {
1164 printf("Too long PASSWORD command.\n");
1165 return -1;
1166 }
1167 pos += ret;
1168 }
1169
1170 return wpa_ctrl_command(ctrl, cmd);
1171}
1172
1173
1174static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1175 char *argv[])
1176{
1177 char cmd[256], *pos, *end;
1178 int i, ret;
1179
1180 if (argc < 2) {
1181 printf("Invalid NEW_PASSWORD command: needs two arguments "
1182 "(network id and password)\n");
1183 return -1;
1184 }
1185
1186 end = cmd + sizeof(cmd);
1187 pos = cmd;
1188 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1189 argv[0], argv[1]);
1190 if (ret < 0 || ret >= end - pos) {
1191 printf("Too long NEW_PASSWORD command.\n");
1192 return -1;
1193 }
1194 pos += ret;
1195 for (i = 2; i < argc; i++) {
1196 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1197 if (ret < 0 || ret >= end - pos) {
1198 printf("Too long NEW_PASSWORD command.\n");
1199 return -1;
1200 }
1201 pos += ret;
1202 }
1203
1204 return wpa_ctrl_command(ctrl, cmd);
1205}
1206
1207
1208static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1209{
1210 char cmd[256], *pos, *end;
1211 int i, ret;
1212
1213 if (argc < 2) {
1214 printf("Invalid PIN command: needs two arguments "
1215 "(network id and pin)\n");
1216 return -1;
1217 }
1218
1219 end = cmd + sizeof(cmd);
1220 pos = cmd;
1221 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1222 argv[0], argv[1]);
1223 if (ret < 0 || ret >= end - pos) {
1224 printf("Too long PIN command.\n");
1225 return -1;
1226 }
1227 pos += ret;
1228 for (i = 2; i < argc; i++) {
1229 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1230 if (ret < 0 || ret >= end - pos) {
1231 printf("Too long PIN command.\n");
1232 return -1;
1233 }
1234 pos += ret;
1235 }
1236 return wpa_ctrl_command(ctrl, cmd);
1237}
1238
1239
1240static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1241{
1242 char cmd[256], *pos, *end;
1243 int i, ret;
1244
1245 if (argc < 2) {
1246 printf("Invalid OTP command: needs two arguments (network "
1247 "id and password)\n");
1248 return -1;
1249 }
1250
1251 end = cmd + sizeof(cmd);
1252 pos = cmd;
1253 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1254 argv[0], argv[1]);
1255 if (ret < 0 || ret >= end - pos) {
1256 printf("Too long OTP command.\n");
1257 return -1;
1258 }
1259 pos += ret;
1260 for (i = 2; i < argc; i++) {
1261 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1262 if (ret < 0 || ret >= end - pos) {
1263 printf("Too long OTP command.\n");
1264 return -1;
1265 }
1266 pos += ret;
1267 }
1268
1269 return wpa_ctrl_command(ctrl, cmd);
1270}
1271
1272
Dmitry Shmidt051af732013-10-22 13:52:46 -07001273static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1274{
1275 char cmd[256], *pos, *end;
1276 int i, ret;
1277
1278 if (argc < 2) {
1279 printf("Invalid SIM command: needs two arguments "
1280 "(network id and SIM operation response)\n");
1281 return -1;
1282 }
1283
1284 end = cmd + sizeof(cmd);
1285 pos = cmd;
1286 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1287 argv[0], argv[1]);
1288 if (ret < 0 || ret >= end - pos) {
1289 printf("Too long SIM command.\n");
1290 return -1;
1291 }
1292 pos += ret;
1293 for (i = 2; i < argc; i++) {
1294 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1295 if (ret < 0 || ret >= end - pos) {
1296 printf("Too long SIM command.\n");
1297 return -1;
1298 }
1299 pos += ret;
1300 }
1301 return wpa_ctrl_command(ctrl, cmd);
1302}
1303
1304
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001305static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1306 char *argv[])
1307{
1308 char cmd[256], *pos, *end;
1309 int i, ret;
1310
1311 if (argc < 2) {
1312 printf("Invalid PASSPHRASE command: needs two arguments "
1313 "(network id and passphrase)\n");
1314 return -1;
1315 }
1316
1317 end = cmd + sizeof(cmd);
1318 pos = cmd;
1319 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1320 argv[0], argv[1]);
1321 if (ret < 0 || ret >= end - pos) {
1322 printf("Too long PASSPHRASE command.\n");
1323 return -1;
1324 }
1325 pos += ret;
1326 for (i = 2; i < argc; i++) {
1327 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1328 if (ret < 0 || ret >= end - pos) {
1329 printf("Too long PASSPHRASE command.\n");
1330 return -1;
1331 }
1332 pos += ret;
1333 }
1334
1335 return wpa_ctrl_command(ctrl, cmd);
1336}
1337
1338
1339static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1340{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001341 if (argc < 2) {
1342 printf("Invalid BSSID command: needs two arguments (network "
1343 "id and BSSID)\n");
1344 return -1;
1345 }
1346
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001347 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001348}
1349
1350
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001351static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1352{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001353 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001354}
1355
1356
1357static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1358{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001359 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001360}
1361
1362
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001363static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1364 char *argv[])
1365{
1366 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1367}
1368
1369
1370static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1371 char *argv[])
1372{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001373 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001374}
1375
1376
1377static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1378 char *argv[])
1379{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001380 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001381}
1382
1383
1384static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1385 char *argv[])
1386{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001387 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001388}
1389
1390
1391static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1392 char *argv[])
1393{
1394 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1395}
1396
1397
1398static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1399 char *argv[])
1400{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001401 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001402}
1403
1404
1405static void wpa_cli_show_network_variables(void)
1406{
1407 printf("set_network variables:\n"
1408 " ssid (network name, SSID)\n"
1409 " psk (WPA passphrase or pre-shared key)\n"
1410 " key_mgmt (key management protocol)\n"
1411 " identity (EAP identity)\n"
1412 " password (EAP password)\n"
1413 " ...\n"
1414 "\n"
1415 "Note: Values are entered in the same format as the "
1416 "configuration file is using,\n"
1417 "i.e., strings values need to be inside double quotation "
1418 "marks.\n"
1419 "For example: set_network 1 ssid \"network name\"\n"
1420 "\n"
1421 "Please see wpa_supplicant.conf documentation for full list "
1422 "of\navailable variables.\n");
1423}
1424
1425
1426static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1427 char *argv[])
1428{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001429 if (argc == 0) {
1430 wpa_cli_show_network_variables();
1431 return 0;
1432 }
1433
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001434 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001435 printf("Invalid SET_NETWORK command: needs three arguments\n"
1436 "(network id, variable name, and value)\n");
1437 return -1;
1438 }
1439
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001440 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001441}
1442
1443
1444static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1445 char *argv[])
1446{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001447 if (argc == 0) {
1448 wpa_cli_show_network_variables();
1449 return 0;
1450 }
1451
1452 if (argc != 2) {
1453 printf("Invalid GET_NETWORK command: needs two arguments\n"
1454 "(network id and variable name)\n");
1455 return -1;
1456 }
1457
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001458 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001459}
1460
1461
Dmitry Shmidt04949592012-07-19 12:16:46 -07001462static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1463 char *argv[])
1464{
1465 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1466}
1467
1468
1469static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1470{
1471 return wpa_ctrl_command(ctrl, "ADD_CRED");
1472}
1473
1474
1475static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1476 char *argv[])
1477{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001478 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001479}
1480
1481
1482static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1483{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001484 if (argc != 3) {
1485 printf("Invalid SET_CRED command: needs three arguments\n"
1486 "(cred id, variable name, and value)\n");
1487 return -1;
1488 }
1489
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001490 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001491}
1492
1493
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001494static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1495 char *argv[])
1496{
1497 return wpa_ctrl_command(ctrl, "DISCONNECT");
1498}
1499
1500
1501static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1502 char *argv[])
1503{
1504 return wpa_ctrl_command(ctrl, "RECONNECT");
1505}
1506
1507
1508static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1509 char *argv[])
1510{
1511 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1512}
1513
1514
1515static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1516{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001517 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001518}
1519
1520
1521static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1522 char *argv[])
1523{
1524 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1525}
1526
1527
1528static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1529{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001530 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001531}
1532
1533
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001534static char ** wpa_cli_complete_bss(const char *str, int pos)
1535{
1536 int arg = get_cmd_arg_num(str, pos);
1537 char **res = NULL;
1538
1539 switch (arg) {
1540 case 1:
1541 res = cli_txt_list_array(&bsses);
1542 break;
1543 }
1544
1545 return res;
1546}
1547
1548
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001549static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1550 char *argv[])
1551{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001552 if (argc < 1 || argc > 2) {
1553 printf("Invalid GET_CAPABILITY command: need either one or "
1554 "two arguments\n");
1555 return -1;
1556 }
1557
1558 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1559 printf("Invalid GET_CAPABILITY command: second argument, "
1560 "if any, must be 'strict'\n");
1561 return -1;
1562 }
1563
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001564 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001565}
1566
1567
1568static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1569{
1570 printf("Available interfaces:\n");
1571 return wpa_ctrl_command(ctrl, "INTERFACES");
1572}
1573
1574
1575static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1576{
1577 if (argc < 1) {
1578 wpa_cli_list_interfaces(ctrl);
1579 return 0;
1580 }
1581
1582 wpa_cli_close_connection();
1583 os_free(ctrl_ifname);
1584 ctrl_ifname = os_strdup(argv[0]);
1585
1586 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1587 printf("Connected to interface '%s.\n", ctrl_ifname);
1588 } else {
1589 printf("Could not connect to interface '%s' - re-trying\n",
1590 ctrl_ifname);
1591 }
1592 return 0;
1593}
1594
1595
1596static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1597 char *argv[])
1598{
1599 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1600}
1601
1602
1603static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1604 char *argv[])
1605{
1606 return wpa_ctrl_command(ctrl, "TERMINATE");
1607}
1608
1609
1610static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1611 char *argv[])
1612{
1613 char cmd[256];
1614 int res;
1615
1616 if (argc < 1) {
1617 printf("Invalid INTERFACE_ADD command: needs at least one "
1618 "argument (interface name)\n"
1619 "All arguments: ifname confname driver ctrl_interface "
1620 "driver_param bridge_name\n");
1621 return -1;
1622 }
1623
1624 /*
1625 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1626 * <driver_param>TAB<bridge_name>
1627 */
1628 res = os_snprintf(cmd, sizeof(cmd),
1629 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1630 argv[0],
1631 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1632 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1633 argc > 5 ? argv[5] : "");
1634 if (res < 0 || (size_t) res >= sizeof(cmd))
1635 return -1;
1636 cmd[sizeof(cmd) - 1] = '\0';
1637 return wpa_ctrl_command(ctrl, cmd);
1638}
1639
1640
1641static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1642 char *argv[])
1643{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001644 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001645}
1646
1647
1648static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1649 char *argv[])
1650{
1651 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1652}
1653
1654
1655#ifdef CONFIG_AP
1656static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1657{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001658 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001659}
1660
1661
1662static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1663 char *addr, size_t addr_len)
1664{
1665 char buf[4096], *pos;
1666 size_t len;
1667 int ret;
1668
1669 if (ctrl_conn == NULL) {
1670 printf("Not connected to hostapd - command dropped.\n");
1671 return -1;
1672 }
1673 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001674 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001675 wpa_cli_msg_cb);
1676 if (ret == -2) {
1677 printf("'%s' command timed out.\n", cmd);
1678 return -2;
1679 } else if (ret < 0) {
1680 printf("'%s' command failed.\n", cmd);
1681 return -1;
1682 }
1683
1684 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001685 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001686 return -1;
1687 printf("%s", buf);
1688
1689 pos = buf;
1690 while (*pos != '\0' && *pos != '\n')
1691 pos++;
1692 *pos = '\0';
1693 os_strlcpy(addr, buf, addr_len);
1694 return 0;
1695}
1696
1697
1698static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1699{
1700 char addr[32], cmd[64];
1701
1702 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1703 return 0;
1704 do {
1705 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1706 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1707
1708 return -1;
1709}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001710
1711
1712static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1713 char *argv[])
1714{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001715 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001716}
1717
1718
1719static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1720 char *argv[])
1721{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001722 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001723}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001724#endif /* CONFIG_AP */
1725
1726
1727static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1728{
1729 return wpa_ctrl_command(ctrl, "SUSPEND");
1730}
1731
1732
1733static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1734{
1735 return wpa_ctrl_command(ctrl, "RESUME");
1736}
1737
1738
1739static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1740{
1741 return wpa_ctrl_command(ctrl, "DROP_SA");
1742}
1743
1744
1745static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1746{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001747 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001748}
1749
1750
1751#ifdef CONFIG_P2P
1752
1753static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1754{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001755 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1756}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001757
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001758
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001759static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1760{
1761 char **res = NULL;
1762 int arg = get_cmd_arg_num(str, pos);
1763
1764 res = os_calloc(6, sizeof(char *));
1765 if (res == NULL)
1766 return NULL;
1767 res[0] = os_strdup("type=social");
1768 if (res[0] == NULL) {
1769 os_free(res);
1770 return NULL;
1771 }
1772 res[1] = os_strdup("type=progressive");
1773 if (res[1] == NULL)
1774 return res;
1775 res[2] = os_strdup("delay=");
1776 if (res[2] == NULL)
1777 return res;
1778 res[3] = os_strdup("dev_id=");
1779 if (res[3] == NULL)
1780 return res;
1781 if (arg == 1)
1782 res[4] = os_strdup("[timeout]");
1783
1784 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001785}
1786
1787
1788static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1789 char *argv[])
1790{
1791 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1792}
1793
1794
1795static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1796 char *argv[])
1797{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001798 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001799}
1800
1801
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001802static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1803{
1804 int arg = get_cmd_arg_num(str, pos);
1805 char **res = NULL;
1806
1807 switch (arg) {
1808 case 1:
1809 res = cli_txt_list_array(&p2p_peers);
1810 break;
1811 }
1812
1813 return res;
1814}
1815
1816
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001817static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1818 char *argv[])
1819{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001820 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001821}
1822
1823
1824static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1825 char *argv[])
1826{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001827 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001828}
1829
1830
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001831static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1832{
1833 int arg = get_cmd_arg_num(str, pos);
1834 char **res = NULL;
1835
1836 switch (arg) {
1837 case 1:
1838 res = cli_txt_list_array(&p2p_groups);
1839 break;
1840 }
1841
1842 return res;
1843}
1844
1845
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001846static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1847 char *argv[])
1848{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001849 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001850}
1851
1852
1853static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1854 char *argv[])
1855{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001856 if (argc != 2 && argc != 3) {
1857 printf("Invalid P2P_PROV_DISC command: needs at least "
1858 "two arguments, address and config method\n"
1859 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001860 return -1;
1861 }
1862
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001863 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001864}
1865
1866
1867static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1868 char *argv[])
1869{
1870 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1871}
1872
1873
1874static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1875 char *argv[])
1876{
1877 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001878
1879 if (argc != 2 && argc != 4) {
1880 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1881 "arguments (address and TLVs) or four arguments "
1882 "(address, \"upnp\", version, search target "
1883 "(SSDP ST:)\n");
1884 return -1;
1885 }
1886
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001887 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001888 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001889 return wpa_ctrl_command(ctrl, cmd);
1890}
1891
1892
1893static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1894 int argc, char *argv[])
1895{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001896 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001897}
1898
1899
1900static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1901 char *argv[])
1902{
1903 char cmd[4096];
1904 int res;
1905
1906 if (argc != 4) {
1907 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1908 "arguments (freq, address, dialog token, and TLVs)\n");
1909 return -1;
1910 }
1911
1912 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1913 argv[0], argv[1], argv[2], argv[3]);
1914 if (res < 0 || (size_t) res >= sizeof(cmd))
1915 return -1;
1916 cmd[sizeof(cmd) - 1] = '\0';
1917 return wpa_ctrl_command(ctrl, cmd);
1918}
1919
1920
1921static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1922 char *argv[])
1923{
1924 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1925}
1926
1927
1928static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1929 int argc, char *argv[])
1930{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001931 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001932}
1933
1934
1935static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1936 char *argv[])
1937{
1938 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1939}
1940
1941
1942static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1943 char *argv[])
1944{
1945 char cmd[4096];
1946 int res;
1947
1948 if (argc != 3 && argc != 4) {
1949 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1950 "arguments\n");
1951 return -1;
1952 }
1953
1954 if (argc == 4)
1955 res = os_snprintf(cmd, sizeof(cmd),
1956 "P2P_SERVICE_ADD %s %s %s %s",
1957 argv[0], argv[1], argv[2], argv[3]);
1958 else
1959 res = os_snprintf(cmd, sizeof(cmd),
1960 "P2P_SERVICE_ADD %s %s %s",
1961 argv[0], argv[1], argv[2]);
1962 if (res < 0 || (size_t) res >= sizeof(cmd))
1963 return -1;
1964 cmd[sizeof(cmd) - 1] = '\0';
1965 return wpa_ctrl_command(ctrl, cmd);
1966}
1967
1968
1969static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1970 char *argv[])
1971{
1972 char cmd[4096];
1973 int res;
1974
1975 if (argc != 2 && argc != 3) {
1976 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1977 "arguments\n");
1978 return -1;
1979 }
1980
1981 if (argc == 3)
1982 res = os_snprintf(cmd, sizeof(cmd),
1983 "P2P_SERVICE_DEL %s %s %s",
1984 argv[0], argv[1], argv[2]);
1985 else
1986 res = os_snprintf(cmd, sizeof(cmd),
1987 "P2P_SERVICE_DEL %s %s",
1988 argv[0], argv[1]);
1989 if (res < 0 || (size_t) res >= sizeof(cmd))
1990 return -1;
1991 cmd[sizeof(cmd) - 1] = '\0';
1992 return wpa_ctrl_command(ctrl, cmd);
1993}
1994
1995
1996static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1997 int argc, char *argv[])
1998{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001999 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002000}
2001
2002
2003static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2004 int argc, char *argv[])
2005{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002006 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002007}
2008
2009
2010static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2011{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002012 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002013}
2014
2015
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002016static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2017{
2018 int arg = get_cmd_arg_num(str, pos);
2019 char **res = NULL;
2020
2021 switch (arg) {
2022 case 1:
2023 res = cli_txt_list_array(&p2p_peers);
2024 break;
2025 }
2026
2027 return res;
2028}
2029
2030
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002031static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2032 char *addr, size_t addr_len,
2033 int discovered)
2034{
2035 char buf[4096], *pos;
2036 size_t len;
2037 int ret;
2038
2039 if (ctrl_conn == NULL)
2040 return -1;
2041 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002042 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002043 wpa_cli_msg_cb);
2044 if (ret == -2) {
2045 printf("'%s' command timed out.\n", cmd);
2046 return -2;
2047 } else if (ret < 0) {
2048 printf("'%s' command failed.\n", cmd);
2049 return -1;
2050 }
2051
2052 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002053 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054 return -1;
2055
2056 pos = buf;
2057 while (*pos != '\0' && *pos != '\n')
2058 pos++;
2059 *pos++ = '\0';
2060 os_strlcpy(addr, buf, addr_len);
2061 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2062 printf("%s\n", addr);
2063 return 0;
2064}
2065
2066
2067static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2068{
2069 char addr[32], cmd[64];
2070 int discovered;
2071
2072 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2073
2074 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2075 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002076 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002077 do {
2078 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2079 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2080 discovered) == 0);
2081
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002082 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002083}
2084
2085
2086static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2087{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002088 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002089}
2090
2091
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002092static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2093{
2094 int arg = get_cmd_arg_num(str, pos);
2095 const char *fields[] = {
2096 "discoverability",
2097 "managed",
2098 "listen_channel",
2099 "ssid_postfix",
2100 "noa",
2101 "ps",
2102 "oppps",
2103 "ctwindow",
2104 "disabled",
2105 "conc_pref",
2106 "force_long_sd",
2107 "peer_filter",
2108 "cross_connect",
2109 "go_apsd",
2110 "client_apsd",
2111 "disallow_freq",
2112 "disc_int",
2113 "per_sta_psk",
2114 };
2115 int i, num_fields = sizeof(fields) / sizeof(fields[0]);
2116
2117 if (arg == 1) {
2118 char **res = os_calloc(num_fields + 1, sizeof(char *));
2119 if (res == NULL)
2120 return NULL;
2121 for (i = 0; i < num_fields; i++) {
2122 res[i] = os_strdup(fields[i]);
2123 if (res[i] == NULL)
2124 return res;
2125 }
2126 return res;
2127 }
2128
2129 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2130 return cli_txt_list_array(&p2p_peers);
2131
2132 return NULL;
2133}
2134
2135
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002136static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2137{
2138 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2139}
2140
2141
2142static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2143 char *argv[])
2144{
2145 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2146}
2147
2148
2149static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2150 char *argv[])
2151{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002152 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002153}
2154
2155
2156static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2157 char *argv[])
2158{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002159 if (argc != 0 && argc != 2 && argc != 4) {
2160 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2161 "(preferred duration, interval; in microsecods).\n"
2162 "Optional second pair can be used to provide "
2163 "acceptable values.\n");
2164 return -1;
2165 }
2166
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002167 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002168}
2169
2170
2171static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2172 char *argv[])
2173{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002174 if (argc != 0 && argc != 2) {
2175 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2176 "(availability period, availability interval; in "
2177 "millisecods).\n"
2178 "Extended Listen Timing can be cancelled with this "
2179 "command when used without parameters.\n");
2180 return -1;
2181 }
2182
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002183 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2184}
2185
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002186
2187static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2188 char *argv[])
2189{
2190 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2191}
2192
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002193#endif /* CONFIG_P2P */
2194
2195#ifdef CONFIG_WIFI_DISPLAY
2196
2197static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2198 char *argv[])
2199{
2200 char cmd[100];
2201 int res;
2202
2203 if (argc != 1 && argc != 2) {
2204 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2205 "arguments (subelem, hexdump)\n");
2206 return -1;
2207 }
2208
2209 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2210 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002211 if (res < 0 || (size_t) res >= sizeof(cmd))
2212 return -1;
2213 cmd[sizeof(cmd) - 1] = '\0';
2214 return wpa_ctrl_command(ctrl, cmd);
2215}
2216
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002217
2218static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2219 char *argv[])
2220{
2221 char cmd[100];
2222 int res;
2223
2224 if (argc != 1) {
2225 printf("Invalid WFD_SUBELEM_GET command: needs one "
2226 "argument (subelem)\n");
2227 return -1;
2228 }
2229
2230 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2231 argv[0]);
2232 if (res < 0 || (size_t) res >= sizeof(cmd))
2233 return -1;
2234 cmd[sizeof(cmd) - 1] = '\0';
2235 return wpa_ctrl_command(ctrl, cmd);
2236}
2237#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002238
2239
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002240#ifdef CONFIG_INTERWORKING
2241static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2242 char *argv[])
2243{
2244 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2245}
2246
2247
2248static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2249 char *argv[])
2250{
2251 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2252}
2253
2254
2255static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2256 char *argv[])
2257{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002258 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002259}
2260
2261
2262static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2263 char *argv[])
2264{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002265 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002266}
2267
2268
2269static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2270{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002271 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2272}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002273
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002274
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002275static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2276 char *argv[])
2277{
2278 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2279}
2280
2281
2282static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2283 char *argv[])
2284{
2285 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002286}
2287#endif /* CONFIG_INTERWORKING */
2288
2289
Dmitry Shmidt04949592012-07-19 12:16:46 -07002290#ifdef CONFIG_HS20
2291
2292static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2293 char *argv[])
2294{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002295 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002296}
2297
2298
2299static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2300 char *argv[])
2301{
2302 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002303
2304 if (argc == 0) {
2305 printf("Command needs one or two arguments (dst mac addr and "
2306 "optional home realm)\n");
2307 return -1;
2308 }
2309
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002310 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2311 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002312 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002313
2314 return wpa_ctrl_command(ctrl, cmd);
2315}
2316
2317#endif /* CONFIG_HS20 */
2318
2319
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002320static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2321 char *argv[])
2322{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002323 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002324}
2325
2326
2327static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2328 char *argv[])
2329{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002330 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002331}
2332
2333
2334static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2335 char *argv[])
2336{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002337 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002338}
2339
2340
2341static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2342 char *argv[])
2343{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002344 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002345}
2346
2347
2348static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2349 char *argv[])
2350{
2351 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2352}
2353
2354
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002355static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2356 char *argv[])
2357{
2358 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2359}
2360
2361
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002362static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2363 char *argv[])
2364{
2365 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2366}
2367
Dmitry Shmidt04949592012-07-19 12:16:46 -07002368
2369#ifdef CONFIG_AUTOSCAN
2370
2371static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2372{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002373 if (argc == 0)
2374 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2375
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002376 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002377}
2378
2379#endif /* CONFIG_AUTOSCAN */
2380
2381
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002382#ifdef CONFIG_WNM
2383
2384static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2385{
2386 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2387}
2388
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002389
2390static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2391{
2392 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2393}
2394
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002395#endif /* CONFIG_WNM */
2396
2397
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002398static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2399{
2400 if (argc == 0)
2401 return -1;
2402 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2403}
2404
2405
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002406#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002407static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2408{
2409 char cmd[256];
2410 int i;
2411 int len;
2412
2413 if (argc < 1) {
2414 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2415 return -1;
2416 }
2417
2418 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2419 for (i=1; i < argc; i++)
2420 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2421 cmd[sizeof(cmd) - 1] = '\0';
2422 printf("%s: %s\n", __func__, cmd);
2423 return wpa_ctrl_command(ctrl, cmd);
2424}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002425#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002426
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002427
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002428static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2429{
2430 return wpa_ctrl_command(ctrl, "FLUSH");
2431}
2432
2433
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002434enum wpa_cli_cmd_flags {
2435 cli_cmd_flag_none = 0x00,
2436 cli_cmd_flag_sensitive = 0x01
2437};
2438
2439struct wpa_cli_cmd {
2440 const char *cmd;
2441 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002442 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002443 enum wpa_cli_cmd_flags flags;
2444 const char *usage;
2445};
2446
2447static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002448 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002449 cli_cmd_flag_none,
2450 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002451 { "ifname", wpa_cli_cmd_ifname, NULL,
2452 cli_cmd_flag_none,
2453 "= get current interface name" },
2454 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002455 cli_cmd_flag_none,
2456 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002457 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002458 cli_cmd_flag_none,
2459 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002460 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002461 cli_cmd_flag_none,
2462 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002463 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002464 cli_cmd_flag_none,
2465 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002466 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002467 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002468 "[command] = show usage help" },
2469 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002470 cli_cmd_flag_none,
2471 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002472 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002473 cli_cmd_flag_none,
2474 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002475 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 cli_cmd_flag_none,
2477 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002478 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002479 cli_cmd_flag_none,
2480 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002481 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002482 cli_cmd_flag_none,
2483 "= set variables (shows list of variables when run without "
2484 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002485 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002486 cli_cmd_flag_none,
2487 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002488 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489 cli_cmd_flag_none,
2490 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002491 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 cli_cmd_flag_none,
2493 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002494 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002495 cli_cmd_flag_none,
2496 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002497 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002498 cli_cmd_flag_none,
2499 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002500 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002501 cli_cmd_flag_none,
2502 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002503 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002504 cli_cmd_flag_none,
2505 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002506 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507 cli_cmd_flag_sensitive,
2508 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002509 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002510 cli_cmd_flag_sensitive,
2511 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002512 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 cli_cmd_flag_sensitive,
2514 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002515 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002516 cli_cmd_flag_sensitive,
2517 "<network id> <password> = configure one-time-password for an SSID"
2518 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002519 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 cli_cmd_flag_sensitive,
2521 "<network id> <passphrase> = configure private key passphrase\n"
2522 " for an SSID" },
Dmitry Shmidt051af732013-10-22 13:52:46 -07002523 { "sim", wpa_cli_cmd_sim, NULL,
2524 cli_cmd_flag_sensitive,
2525 "<network id> <pin> = report SIM operation result" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002526 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002527 cli_cmd_flag_none,
2528 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002529 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002530 cli_cmd_flag_none,
2531 "<BSSID> = add a BSSID to the blacklist\n"
2532 "blacklist clear = clear the blacklist\n"
2533 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002534 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002535 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002536 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002537 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002538 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002539 cli_cmd_flag_none,
2540 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002541 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542 cli_cmd_flag_none,
2543 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002544 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002545 cli_cmd_flag_none,
2546 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002547 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002548 cli_cmd_flag_none,
2549 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002550 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002551 cli_cmd_flag_none,
2552 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002553 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002554 cli_cmd_flag_none,
2555 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002556 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002557 cli_cmd_flag_sensitive,
2558 "<network id> <variable> <value> = set network variables (shows\n"
2559 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002560 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561 cli_cmd_flag_none,
2562 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002563 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002564 cli_cmd_flag_none,
2565 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002566 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002567 cli_cmd_flag_none,
2568 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002569 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002570 cli_cmd_flag_none,
2571 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002572 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002573 cli_cmd_flag_sensitive,
2574 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002575 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002576 cli_cmd_flag_none,
2577 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002578 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002579 cli_cmd_flag_none,
2580 "= disconnect and wait for reassociate/reconnect command before\n"
2581 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002582 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002583 cli_cmd_flag_none,
2584 "= like reassociate, but only takes effect if already disconnected"
2585 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002586 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587 cli_cmd_flag_none,
2588 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002589 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002590 cli_cmd_flag_none,
2591 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002592 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002593 cli_cmd_flag_none,
2594 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002595 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002596 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002597 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002598 "= get capabilies" },
2599 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002600 cli_cmd_flag_none,
2601 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002602 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603 cli_cmd_flag_none,
2604 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002605 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002606 cli_cmd_flag_none,
2607 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2608 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2609 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002610 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611 cli_cmd_flag_none,
2612 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002613 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002614 cli_cmd_flag_none,
2615 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002616 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002617 cli_cmd_flag_none,
2618 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002619 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620 cli_cmd_flag_none,
2621 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002622 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002623 cli_cmd_flag_none,
2624 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002625 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002626 cli_cmd_flag_none,
2627 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002628 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002629 cli_cmd_flag_none,
2630 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002631 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002632 cli_cmd_flag_none,
2633 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002634 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002635 cli_cmd_flag_none,
2636 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002637 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638 cli_cmd_flag_none,
2639 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002640 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002641 cli_cmd_flag_sensitive,
2642 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2643 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002644 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 cli_cmd_flag_sensitive,
2646 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002647 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002649#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002650 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002651 cli_cmd_flag_none,
2652 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002653 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2654 cli_cmd_flag_none,
2655 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002656 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002657 cli_cmd_flag_none,
2658 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002659 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002660 cli_cmd_flag_sensitive,
2661 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002662 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2663 cli_cmd_flag_none,
2664 "<NDEF> <WPS> = create NFC handover request" },
2665 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2666 cli_cmd_flag_none,
2667 "<NDEF> <WPS> = create NFC handover select" },
2668 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2669 cli_cmd_flag_none,
2670 "<hexdump of payload> = report received NFC handover request" },
2671 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2672 cli_cmd_flag_none,
2673 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002674 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2675 cli_cmd_flag_none,
2676 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2677 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002678#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002679 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002680 cli_cmd_flag_sensitive,
2681 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002682 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002683 cli_cmd_flag_sensitive,
2684 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002685 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002686 cli_cmd_flag_none,
2687 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002688 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002689 cli_cmd_flag_none,
2690 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002691 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002692 cli_cmd_flag_sensitive,
2693 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002694 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002695 cli_cmd_flag_none,
2696 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002697 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698 cli_cmd_flag_sensitive,
2699 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002700 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002701 cli_cmd_flag_none,
2702 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002703 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002704 cli_cmd_flag_sensitive,
2705 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002706#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002707 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002708 cli_cmd_flag_none,
2709 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2710#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002711 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002712 cli_cmd_flag_none,
2713 "<addr> = request RSN authentication with <addr> in IBSS" },
2714#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002715 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002716 cli_cmd_flag_none,
2717 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002718 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002719 cli_cmd_flag_none,
2720 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002721 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002722 cli_cmd_flag_none,
2723 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002724 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002725 cli_cmd_flag_none,
2726 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002727#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002728 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002729 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002730 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002731 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002732 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002733 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002734 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002735 cli_cmd_flag_none,
2736 "<addr> = roam to the specified BSS" },
2737#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002738 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2739 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002740 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002741 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002742 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002743 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2744 cli_cmd_flag_none,
2745 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2746 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002747 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002748 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2749 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002750 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002751 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2752 "[ht40] = add a new P2P group (local end as GO)" },
2753 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2754 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002755 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002756 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002757 cli_cmd_flag_none,
2758 "= get the passphrase for a group (GO only)" },
2759 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002760 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002761 "<addr> <TLVs> = schedule service discovery request" },
2762 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002763 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002764 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002765 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002766 cli_cmd_flag_none,
2767 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002768 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002769 cli_cmd_flag_none,
2770 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002771 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002772 cli_cmd_flag_none,
2773 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002774 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002775 cli_cmd_flag_none,
2776 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002777 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 cli_cmd_flag_none,
2779 "<bonjour|upnp> <query|version> <response|service> = add a local "
2780 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002781 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002782 cli_cmd_flag_none,
2783 "<bonjour|upnp> <query|version> [|service] = remove a local "
2784 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002785 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002786 cli_cmd_flag_none,
2787 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002788 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002789 cli_cmd_flag_none,
2790 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002791 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002792 "[discovered] = list known (optionally, only fully discovered) P2P "
2793 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002794 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2795 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002796 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002797 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2798 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002799 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002800 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002801 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002802 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002803 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002804 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2805 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002806 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002807 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2808 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002809 "[<duration> <interval>] [<duration> <interval>] = request GO "
2810 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002811 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2812 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002813 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002814 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2815 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2816 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002817#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002818#ifdef CONFIG_WIFI_DISPLAY
2819 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2820 cli_cmd_flag_none,
2821 "<subelem> [contents] = set Wi-Fi Display subelement" },
2822 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2823 cli_cmd_flag_none,
2824 "<subelem> = get Wi-Fi Display subelement" },
2825#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002826#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002827 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002828 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002829 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2830 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002831 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002832 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002833 cli_cmd_flag_none,
2834 "[auto] = perform Interworking network selection" },
2835 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002836 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002837 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002838 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2839 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002840 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002841 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2842 cli_cmd_flag_none,
2843 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2844 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2845 wpa_cli_complete_bss, cli_cmd_flag_none,
2846 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002847#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002848#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002849 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2850 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002851 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2852 },
2853 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002854 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002855 "<addr> <home realm> = get HS20 nai home realm list" },
2856#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002857 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2858 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002859 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002860 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002861 cli_cmd_flag_none,
2862 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002863 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002864 cli_cmd_flag_none,
2865 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002866 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002867 cli_cmd_flag_none,
2868 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002869 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002870 cli_cmd_flag_none,
2871 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002872 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002873 cli_cmd_flag_none,
2874 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002875 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2876 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002877 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002878#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002879 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002880 "[params] = Set or unset (if none) autoscan parameters" },
2881#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002882#ifdef CONFIG_WNM
2883 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2884 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002885 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2886 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002887#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002888 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2889 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002890 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2891 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002892#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002893 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002894 cli_cmd_flag_none,
2895 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002896#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002897 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002898};
2899
2900
2901/*
2902 * Prints command usage, lines are padded with the specified string.
2903 */
2904static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2905{
2906 char c;
2907 size_t n;
2908
2909 printf("%s%s ", pad, cmd->cmd);
2910 for (n = 0; (c = cmd->usage[n]); n++) {
2911 printf("%c", c);
2912 if (c == '\n')
2913 printf("%s", pad);
2914 }
2915 printf("\n");
2916}
2917
2918
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002919static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002920{
2921 int n;
2922 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002923 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2924 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2925 print_cmd_help(&wpa_cli_commands[n], " ");
2926 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002927}
2928
2929
2930static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2931{
2932 const char *c, *delim;
2933 int n;
2934 size_t len;
2935
2936 delim = os_strchr(cmd, ' ');
2937 if (delim)
2938 len = delim - cmd;
2939 else
2940 len = os_strlen(cmd);
2941
2942 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2943 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2944 return (wpa_cli_commands[n].flags &
2945 cli_cmd_flag_sensitive);
2946 }
2947 return 0;
2948}
2949
2950
2951static char ** wpa_list_cmd_list(void)
2952{
2953 char **res;
2954 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002955 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002956
2957 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002958 count += dl_list_len(&p2p_groups);
2959 count += dl_list_len(&ifnames);
2960 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002961 if (res == NULL)
2962 return NULL;
2963
2964 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2965 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2966 if (res[i] == NULL)
2967 break;
2968 }
2969
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002970 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
2971 size_t len = 8 + os_strlen(e->txt);
2972 res[i] = os_malloc(len);
2973 if (res[i] == NULL)
2974 break;
2975 os_snprintf(res[i], len, "ifname=%s", e->txt);
2976 i++;
2977 }
2978
2979 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
2980 res[i] = os_strdup(e->txt);
2981 if (res[i] == NULL)
2982 break;
2983 i++;
2984 }
2985
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002986 return res;
2987}
2988
2989
2990static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2991 int pos)
2992{
2993 int i;
2994
2995 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2996 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002997 if (wpa_cli_commands[i].completion)
2998 return wpa_cli_commands[i].completion(str,
2999 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003000 edit_clear_line();
3001 printf("\r%s\n", wpa_cli_commands[i].usage);
3002 edit_redraw();
3003 break;
3004 }
3005 }
3006
3007 return NULL;
3008}
3009
3010
3011static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3012{
3013 char **res;
3014 const char *end;
3015 char *cmd;
3016
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003017 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3018 end = os_strchr(str, ' ');
3019 if (end && pos > end - str) {
3020 pos -= end - str + 1;
3021 str = end + 1;
3022 }
3023 }
3024
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003025 end = os_strchr(str, ' ');
3026 if (end == NULL || str + pos < end)
3027 return wpa_list_cmd_list();
3028
3029 cmd = os_malloc(pos + 1);
3030 if (cmd == NULL)
3031 return NULL;
3032 os_memcpy(cmd, str, pos);
3033 cmd[end - str] = '\0';
3034 res = wpa_cli_cmd_completion(cmd, str, pos);
3035 os_free(cmd);
3036 return res;
3037}
3038
3039
3040static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3041{
3042 struct wpa_cli_cmd *cmd, *match = NULL;
3043 int count;
3044 int ret = 0;
3045
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003046 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3047 ifname_prefix = argv[0] + 7;
3048 argv = &argv[1];
3049 argc--;
3050 } else
3051 ifname_prefix = NULL;
3052
3053 if (argc == 0)
3054 return -1;
3055
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003056 count = 0;
3057 cmd = wpa_cli_commands;
3058 while (cmd->cmd) {
3059 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3060 {
3061 match = cmd;
3062 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3063 /* we have an exact match */
3064 count = 1;
3065 break;
3066 }
3067 count++;
3068 }
3069 cmd++;
3070 }
3071
3072 if (count > 1) {
3073 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3074 cmd = wpa_cli_commands;
3075 while (cmd->cmd) {
3076 if (os_strncasecmp(cmd->cmd, argv[0],
3077 os_strlen(argv[0])) == 0) {
3078 printf(" %s", cmd->cmd);
3079 }
3080 cmd++;
3081 }
3082 printf("\n");
3083 ret = 1;
3084 } else if (count == 0) {
3085 printf("Unknown command '%s'\n", argv[0]);
3086 ret = 1;
3087 } else {
3088 ret = match->handler(ctrl, argc - 1, &argv[1]);
3089 }
3090
3091 return ret;
3092}
3093
3094
3095static int str_match(const char *a, const char *b)
3096{
3097 return os_strncmp(a, b, os_strlen(b)) == 0;
3098}
3099
3100
3101static int wpa_cli_exec(const char *program, const char *arg1,
3102 const char *arg2)
3103{
3104 char *cmd;
3105 size_t len;
3106 int res;
3107 int ret = 0;
3108
3109 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3110 cmd = os_malloc(len);
3111 if (cmd == NULL)
3112 return -1;
3113 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3114 if (res < 0 || (size_t) res >= len) {
3115 os_free(cmd);
3116 return -1;
3117 }
3118 cmd[len - 1] = '\0';
3119#ifndef _WIN32_WCE
3120 if (system(cmd) < 0)
3121 ret = -1;
3122#endif /* _WIN32_WCE */
3123 os_free(cmd);
3124
3125 return ret;
3126}
3127
3128
3129static void wpa_cli_action_process(const char *msg)
3130{
3131 const char *pos;
3132 char *copy = NULL, *id, *pos2;
3133
3134 pos = msg;
3135 if (*pos == '<') {
3136 /* skip priority */
3137 pos = os_strchr(pos, '>');
3138 if (pos)
3139 pos++;
3140 else
3141 pos = msg;
3142 }
3143
3144 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3145 int new_id = -1;
3146 os_unsetenv("WPA_ID");
3147 os_unsetenv("WPA_ID_STR");
3148 os_unsetenv("WPA_CTRL_DIR");
3149
3150 pos = os_strstr(pos, "[id=");
3151 if (pos)
3152 copy = os_strdup(pos + 4);
3153
3154 if (copy) {
3155 pos2 = id = copy;
3156 while (*pos2 && *pos2 != ' ')
3157 pos2++;
3158 *pos2++ = '\0';
3159 new_id = atoi(id);
3160 os_setenv("WPA_ID", id, 1);
3161 while (*pos2 && *pos2 != '=')
3162 pos2++;
3163 if (*pos2 == '=')
3164 pos2++;
3165 id = pos2;
3166 while (*pos2 && *pos2 != ']')
3167 pos2++;
3168 *pos2 = '\0';
3169 os_setenv("WPA_ID_STR", id, 1);
3170 os_free(copy);
3171 }
3172
3173 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3174
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003175 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003176 wpa_cli_connected = 1;
3177 wpa_cli_last_id = new_id;
3178 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3179 }
3180 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3181 if (wpa_cli_connected) {
3182 wpa_cli_connected = 0;
3183 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3184 }
3185 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3186 wpa_cli_exec(action_file, ctrl_ifname, pos);
3187 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3188 wpa_cli_exec(action_file, ctrl_ifname, pos);
3189 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3190 wpa_cli_exec(action_file, ctrl_ifname, pos);
3191 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3192 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003193 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3194 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003195 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3196 wpa_cli_exec(action_file, ctrl_ifname, pos);
3197 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3198 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003199 } else if (str_match(pos, AP_STA_CONNECTED)) {
3200 wpa_cli_exec(action_file, ctrl_ifname, pos);
3201 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3202 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003203 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3204 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003205 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3206 printf("wpa_supplicant is terminating - stop monitoring\n");
3207 wpa_cli_quit = 1;
3208 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003209}
3210
3211
3212#ifndef CONFIG_ANSI_C_EXTRA
3213static void wpa_cli_action_cb(char *msg, size_t len)
3214{
3215 wpa_cli_action_process(msg);
3216}
3217#endif /* CONFIG_ANSI_C_EXTRA */
3218
3219
3220static void wpa_cli_reconnect(void)
3221{
3222 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003223 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3224 return;
3225
3226 if (interactive) {
3227 edit_clear_line();
3228 printf("\rConnection to wpa_supplicant re-established\n");
3229 edit_redraw();
3230 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003231}
3232
3233
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003234static void cli_event(const char *str)
3235{
3236 const char *start, *s;
3237
3238 start = os_strchr(str, '>');
3239 if (start == NULL)
3240 return;
3241
3242 start++;
3243
3244 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3245 s = os_strchr(start, ' ');
3246 if (s == NULL)
3247 return;
3248 s = os_strchr(s + 1, ' ');
3249 if (s == NULL)
3250 return;
3251 cli_txt_list_add(&bsses, s + 1);
3252 return;
3253 }
3254
3255 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3256 s = os_strchr(start, ' ');
3257 if (s == NULL)
3258 return;
3259 s = os_strchr(s + 1, ' ');
3260 if (s == NULL)
3261 return;
3262 cli_txt_list_del_addr(&bsses, s + 1);
3263 return;
3264 }
3265
3266#ifdef CONFIG_P2P
3267 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3268 s = os_strstr(start, " p2p_dev_addr=");
3269 if (s == NULL)
3270 return;
3271 cli_txt_list_add_addr(&p2p_peers, s + 14);
3272 return;
3273 }
3274
3275 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3276 s = os_strstr(start, " p2p_dev_addr=");
3277 if (s == NULL)
3278 return;
3279 cli_txt_list_del_addr(&p2p_peers, s + 14);
3280 return;
3281 }
3282
3283 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3284 s = os_strchr(start, ' ');
3285 if (s == NULL)
3286 return;
3287 cli_txt_list_add_word(&p2p_groups, s + 1);
3288 return;
3289 }
3290
3291 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3292 s = os_strchr(start, ' ');
3293 if (s == NULL)
3294 return;
3295 cli_txt_list_del_word(&p2p_groups, s + 1);
3296 return;
3297 }
3298#endif /* CONFIG_P2P */
3299}
3300
3301
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003302static int check_terminating(const char *msg)
3303{
3304 const char *pos = msg;
3305
3306 if (*pos == '<') {
3307 /* skip priority */
3308 pos = os_strchr(pos, '>');
3309 if (pos)
3310 pos++;
3311 else
3312 pos = msg;
3313 }
3314
3315 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3316 edit_clear_line();
3317 printf("\rConnection to wpa_supplicant lost - trying to "
3318 "reconnect\n");
3319 edit_redraw();
3320 wpa_cli_attached = 0;
3321 wpa_cli_close_connection();
3322 return 1;
3323 }
3324
3325 return 0;
3326}
3327
3328
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003329static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3330{
3331 if (ctrl_conn == NULL) {
3332 wpa_cli_reconnect();
3333 return;
3334 }
3335 while (wpa_ctrl_pending(ctrl) > 0) {
3336 char buf[256];
3337 size_t len = sizeof(buf) - 1;
3338 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3339 buf[len] = '\0';
3340 if (action_monitor)
3341 wpa_cli_action_process(buf);
3342 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003343 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003344 if (wpa_cli_show_event(buf)) {
3345 edit_clear_line();
3346 printf("\r%s\n", buf);
3347 edit_redraw();
3348 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003349
3350 if (interactive && check_terminating(buf) > 0)
3351 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003352 }
3353 } else {
3354 printf("Could not read pending message.\n");
3355 break;
3356 }
3357 }
3358
3359 if (wpa_ctrl_pending(ctrl) < 0) {
3360 printf("Connection to wpa_supplicant lost - trying to "
3361 "reconnect\n");
3362 wpa_cli_reconnect();
3363 }
3364}
3365
3366#define max_args 10
3367
3368static int tokenize_cmd(char *cmd, char *argv[])
3369{
3370 char *pos;
3371 int argc = 0;
3372
3373 pos = cmd;
3374 for (;;) {
3375 while (*pos == ' ')
3376 pos++;
3377 if (*pos == '\0')
3378 break;
3379 argv[argc] = pos;
3380 argc++;
3381 if (argc == max_args)
3382 break;
3383 if (*pos == '"') {
3384 char *pos2 = os_strrchr(pos, '"');
3385 if (pos2)
3386 pos = pos2 + 1;
3387 }
3388 while (*pos != '\0' && *pos != ' ')
3389 pos++;
3390 if (*pos == ' ')
3391 *pos++ = '\0';
3392 }
3393
3394 return argc;
3395}
3396
3397
3398static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3399{
3400 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3401 printf("Connection to wpa_supplicant lost - trying to "
3402 "reconnect\n");
3403 wpa_cli_close_connection();
3404 }
3405 if (!ctrl_conn)
3406 wpa_cli_reconnect();
3407 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3408}
3409
3410
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003411static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3412{
3413 wpa_cli_recv_pending(mon_conn, 0);
3414}
3415
3416
3417static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3418{
3419 char *argv[max_args];
3420 int argc;
3421 argc = tokenize_cmd(cmd, argv);
3422 if (argc)
3423 wpa_request(ctrl_conn, argc, argv);
3424}
3425
3426
3427static void wpa_cli_edit_eof_cb(void *ctx)
3428{
3429 eloop_terminate();
3430}
3431
3432
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003433static int warning_displayed = 0;
3434static char *hfile = NULL;
3435static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003436
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003437static void start_edit(void)
3438{
3439 char *home;
3440 char *ps = NULL;
3441
3442#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3443 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3444#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003445
3446 home = getenv("HOME");
3447 if (home) {
3448 const char *fname = ".wpa_cli_history";
3449 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3450 hfile = os_malloc(hfile_len);
3451 if (hfile)
3452 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3453 }
3454
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003455 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3456 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3457 eloop_terminate();
3458 return;
3459 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003460
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003461 edit_started = 1;
3462 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3463}
3464
3465
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003466static void update_bssid_list(struct wpa_ctrl *ctrl)
3467{
3468 char buf[4096];
3469 size_t len = sizeof(buf);
3470 int ret;
3471 char *cmd = "BSS RANGE=ALL MASK=0x2";
3472 char *pos, *end;
3473
3474 if (ctrl == NULL)
3475 return;
3476 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3477 if (ret < 0)
3478 return;
3479 buf[len] = '\0';
3480
3481 pos = buf;
3482 while (pos) {
3483 pos = os_strstr(pos, "bssid=");
3484 if (pos == NULL)
3485 break;
3486 pos += 6;
3487 end = os_strchr(pos, '\n');
3488 if (end == NULL)
3489 break;
3490 *end = '\0';
3491 cli_txt_list_add(&bsses, pos);
3492 pos = end + 1;
3493 }
3494}
3495
3496
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003497static void update_ifnames(struct wpa_ctrl *ctrl)
3498{
3499 char buf[4096];
3500 size_t len = sizeof(buf);
3501 int ret;
3502 char *cmd = "INTERFACES";
3503 char *pos, *end;
3504 char txt[200];
3505
3506 cli_txt_list_flush(&ifnames);
3507
3508 if (ctrl == NULL)
3509 return;
3510 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3511 if (ret < 0)
3512 return;
3513 buf[len] = '\0';
3514
3515 pos = buf;
3516 while (pos) {
3517 end = os_strchr(pos, '\n');
3518 if (end == NULL)
3519 break;
3520 *end = '\0';
3521 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3522 if (ret > 0 && ret < (int) sizeof(txt))
3523 cli_txt_list_add(&ifnames, txt);
3524 pos = end + 1;
3525 }
3526}
3527
3528
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003529static void try_connection(void *eloop_ctx, void *timeout_ctx)
3530{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003531 if (ctrl_conn)
3532 goto done;
3533
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003534 if (ctrl_ifname == NULL)
3535 ctrl_ifname = wpa_cli_get_default_ifname();
3536
3537 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3538 if (!warning_displayed) {
3539 printf("Could not connect to wpa_supplicant: "
3540 "%s - re-trying\n", ctrl_ifname);
3541 warning_displayed = 1;
3542 }
3543 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3544 return;
3545 }
3546
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003547 update_bssid_list(ctrl_conn);
3548
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003549 if (warning_displayed)
3550 printf("Connection established.\n");
3551
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003552done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003553 start_edit();
3554}
3555
3556
3557static void wpa_cli_interactive(void)
3558{
3559 printf("\nInteractive mode\n\n");
3560
3561 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003562 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003563 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003564
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003565 cli_txt_list_flush(&p2p_peers);
3566 cli_txt_list_flush(&p2p_groups);
3567 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003568 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003569 if (edit_started)
3570 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003571 os_free(hfile);
3572 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3573 wpa_cli_close_connection();
3574}
3575
3576
3577static void wpa_cli_action(struct wpa_ctrl *ctrl)
3578{
3579#ifdef CONFIG_ANSI_C_EXTRA
3580 /* TODO: ANSI C version(?) */
3581 printf("Action processing not supported in ANSI C build.\n");
3582#else /* CONFIG_ANSI_C_EXTRA */
3583 fd_set rfds;
3584 int fd, res;
3585 struct timeval tv;
3586 char buf[256]; /* note: large enough to fit in unsolicited messages */
3587 size_t len;
3588
3589 fd = wpa_ctrl_get_fd(ctrl);
3590
3591 while (!wpa_cli_quit) {
3592 FD_ZERO(&rfds);
3593 FD_SET(fd, &rfds);
3594 tv.tv_sec = ping_interval;
3595 tv.tv_usec = 0;
3596 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3597 if (res < 0 && errno != EINTR) {
3598 perror("select");
3599 break;
3600 }
3601
3602 if (FD_ISSET(fd, &rfds))
3603 wpa_cli_recv_pending(ctrl, 1);
3604 else {
3605 /* verify that connection is still working */
3606 len = sizeof(buf) - 1;
3607 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3608 wpa_cli_action_cb) < 0 ||
3609 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3610 printf("wpa_supplicant did not reply to PING "
3611 "command - exiting\n");
3612 break;
3613 }
3614 }
3615 }
3616#endif /* CONFIG_ANSI_C_EXTRA */
3617}
3618
3619
3620static void wpa_cli_cleanup(void)
3621{
3622 wpa_cli_close_connection();
3623 if (pid_file)
3624 os_daemonize_terminate(pid_file);
3625
3626 os_program_deinit();
3627}
3628
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003629
3630static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003631{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003632 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003633}
3634
3635
3636static char * wpa_cli_get_default_ifname(void)
3637{
3638 char *ifname = NULL;
3639
3640#ifdef CONFIG_CTRL_IFACE_UNIX
3641 struct dirent *dent;
3642 DIR *dir = opendir(ctrl_iface_dir);
3643 if (!dir) {
3644#ifdef ANDROID
3645 char ifprop[PROPERTY_VALUE_MAX];
3646 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3647 ifname = os_strdup(ifprop);
3648 printf("Using interface '%s'\n", ifname);
3649 return ifname;
3650 }
3651#endif /* ANDROID */
3652 return NULL;
3653 }
3654 while ((dent = readdir(dir))) {
3655#ifdef _DIRENT_HAVE_D_TYPE
3656 /*
3657 * Skip the file if it is not a socket. Also accept
3658 * DT_UNKNOWN (0) in case the C library or underlying
3659 * file system does not support d_type.
3660 */
3661 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3662 continue;
3663#endif /* _DIRENT_HAVE_D_TYPE */
3664 if (os_strcmp(dent->d_name, ".") == 0 ||
3665 os_strcmp(dent->d_name, "..") == 0)
3666 continue;
3667 printf("Selected interface '%s'\n", dent->d_name);
3668 ifname = os_strdup(dent->d_name);
3669 break;
3670 }
3671 closedir(dir);
3672#endif /* CONFIG_CTRL_IFACE_UNIX */
3673
3674#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003675 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003676 size_t len;
3677 struct wpa_ctrl *ctrl;
3678 int ret;
3679
3680 ctrl = wpa_ctrl_open(NULL);
3681 if (ctrl == NULL)
3682 return NULL;
3683
3684 len = sizeof(buf) - 1;
3685 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3686 if (ret >= 0) {
3687 buf[len] = '\0';
3688 pos = os_strchr(buf, '\n');
3689 if (pos)
3690 *pos = '\0';
3691 ifname = os_strdup(buf);
3692 }
3693 wpa_ctrl_close(ctrl);
3694#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3695
3696 return ifname;
3697}
3698
3699
3700int main(int argc, char *argv[])
3701{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003702 int c;
3703 int daemonize = 0;
3704 int ret = 0;
3705 const char *global = NULL;
3706
3707 if (os_program_init())
3708 return -1;
3709
3710 for (;;) {
3711 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3712 if (c < 0)
3713 break;
3714 switch (c) {
3715 case 'a':
3716 action_file = optarg;
3717 break;
3718 case 'B':
3719 daemonize = 1;
3720 break;
3721 case 'g':
3722 global = optarg;
3723 break;
3724 case 'G':
3725 ping_interval = atoi(optarg);
3726 break;
3727 case 'h':
3728 usage();
3729 return 0;
3730 case 'v':
3731 printf("%s\n", wpa_cli_version);
3732 return 0;
3733 case 'i':
3734 os_free(ctrl_ifname);
3735 ctrl_ifname = os_strdup(optarg);
3736 break;
3737 case 'p':
3738 ctrl_iface_dir = optarg;
3739 break;
3740 case 'P':
3741 pid_file = optarg;
3742 break;
3743 default:
3744 usage();
3745 return -1;
3746 }
3747 }
3748
3749 interactive = (argc == optind) && (action_file == NULL);
3750
3751 if (interactive)
3752 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3753
3754 if (eloop_init())
3755 return -1;
3756
3757 if (global) {
3758#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3759 ctrl_conn = wpa_ctrl_open(NULL);
3760#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3761 ctrl_conn = wpa_ctrl_open(global);
3762#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3763 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003764 fprintf(stderr, "Failed to connect to wpa_supplicant "
3765 "global interface: %s error: %s\n",
3766 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003767 return -1;
3768 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003769
3770 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003771 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003772 mon_conn = wpa_ctrl_open(global);
3773 if (mon_conn) {
3774 if (wpa_ctrl_attach(mon_conn) == 0) {
3775 wpa_cli_attached = 1;
3776 eloop_register_read_sock(
3777 wpa_ctrl_get_fd(mon_conn),
3778 wpa_cli_mon_receive,
3779 NULL, NULL);
3780 } else {
3781 printf("Failed to open monitor "
3782 "connection through global "
3783 "control interface\n");
3784 }
3785 }
3786 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003787 }
3788
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003789 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003790
3791 if (ctrl_ifname == NULL)
3792 ctrl_ifname = wpa_cli_get_default_ifname();
3793
3794 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003795 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003796 } else {
3797 if (!global &&
3798 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003799 fprintf(stderr, "Failed to connect to non-global "
3800 "ctrl_ifname: %s error: %s\n",
3801 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003802 return -1;
3803 }
3804
3805 if (action_file) {
3806 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3807 wpa_cli_attached = 1;
3808 } else {
3809 printf("Warning: Failed to attach to "
3810 "wpa_supplicant.\n");
3811 return -1;
3812 }
3813 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003814
3815 if (daemonize && os_daemonize(pid_file))
3816 return -1;
3817
3818 if (action_file)
3819 wpa_cli_action(ctrl_conn);
3820 else
3821 ret = wpa_request(ctrl_conn, argc - optind,
3822 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003823 }
3824
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003825 os_free(ctrl_ifname);
3826 eloop_destroy();
3827 wpa_cli_cleanup();
3828
3829 return ret;
3830}
3831
3832#else /* CONFIG_CTRL_IFACE */
3833int main(int argc, char *argv[])
3834{
3835 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3836 return -1;
3837}
3838#endif /* CONFIG_CTRL_IFACE */