blob: a379d6504e426bbc8c9cb25ec59805f5e46d9009 [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");
499 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700500}
501
502
503static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
504{
505 return wpa_ctrl_command(ctrl, "PING");
506}
507
508
509static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
510{
511 return wpa_ctrl_command(ctrl, "RELOG");
512}
513
514
515static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
516{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700517 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700518}
519
520
521static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
522{
523 return wpa_ctrl_command(ctrl, "MIB");
524}
525
526
527static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
528{
529 return wpa_ctrl_command(ctrl, "PMKSA");
530}
531
532
533static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
534{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700535 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700536 return 0;
537}
538
539
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700540static char ** wpa_cli_complete_help(const char *str, int pos)
541{
542 int arg = get_cmd_arg_num(str, pos);
543 char **res = NULL;
544
545 switch (arg) {
546 case 1:
547 res = wpa_list_cmd_list();
548 break;
549 }
550
551 return res;
552}
553
554
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700555static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
556{
557 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
558 return 0;
559}
560
561
562static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
563{
564 wpa_cli_quit = 1;
565 if (interactive)
566 eloop_terminate();
567 return 0;
568}
569
570
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700571static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
572{
573 char cmd[256];
574 int res;
575
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700576 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800577 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700578 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
579 printf("Too long SET command.\n");
580 return -1;
581 }
582 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700583 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700584
585 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
586}
587
588
589static char ** wpa_cli_complete_set(const char *str, int pos)
590{
591 int arg = get_cmd_arg_num(str, pos);
592 const char *fields[] = {
593 /* runtime values */
594 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
595 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
596 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
597 "wps_fragment_size", "wps_version_number", "ampdu",
598 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
599 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
600 "no_keep_alive",
601 /* global configuration parameters */
602 "eapol_version", "ap_scan", "disable_scan_offload",
603 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
604 "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
605 "driver_param", "dot11RSNAConfigPMKLifetime",
606 "dot11RSNAConfigPMKReauthThreshold",
607 "dot11RSNAConfigSATimeout",
608 "update_config", "load_dynamic_eap", "uuid", "device_name",
609 "manufacturer", "model_name", "model_number", "serial_number",
610 "device_type", "os_version", "config_methods",
611 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
612 "p2p_listen_reg_class", "p2p_listen_channel",
613 "p2p_oper_reg_class", "p2p_oper_channel",
614 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
615 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
616 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
617 "p2p_ignore_shared_freq", "country", "bss_max_count",
618 "bss_expiration_age", "bss_expiration_scan_count",
619 "filter_ssids", "filter_rssi", "max_num_sta",
620 "disassoc_low_ack", "hs20", "interworking", "hessid",
621 "access_network_type", "pbc_in_m1", "autoscan",
622 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
623 "wps_nfc_dev_pw", "ext_password_backend",
624 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
625 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
626 "ignore_old_scan_res", "freq_list"
627 };
628 int i, num_fields = sizeof(fields) / sizeof(fields[0]);
629
630 if (arg == 1) {
631 char **res = os_calloc(num_fields + 1, sizeof(char *));
632 if (res == NULL)
633 return NULL;
634 for (i = 0; i < num_fields; i++) {
635 res[i] = os_strdup(fields[i]);
636 if (res[i] == NULL)
637 return res;
638 }
639 return res;
640 }
641
642 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
643 return cli_txt_list_array(&bsses);
644
645 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700646}
647
648
649static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
650{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700651 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700652}
653
654
655static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
656{
657 return wpa_ctrl_command(ctrl, "LOGOFF");
658}
659
660
661static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
662{
663 return wpa_ctrl_command(ctrl, "LOGON");
664}
665
666
667static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
668 char *argv[])
669{
670 return wpa_ctrl_command(ctrl, "REASSOCIATE");
671}
672
673
674static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
675 char *argv[])
676{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700677 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700678}
679
680
681static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
682{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700683 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684}
685
686
687static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
688 char *argv[])
689{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700690 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700691}
692
693
694static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
695 char *argv[])
696{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700697 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700698}
699
700
701static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
702 char *argv[])
703{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700704 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700705}
706
707
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700708static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
709{
710 char cmd[256];
711 int res;
712
713 if (argc < 1)
714 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
715 else
716 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
717 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
718 printf("Too long BSS_FLUSH command.\n");
719 return -1;
720 }
721 return wpa_ctrl_command(ctrl, cmd);
722}
723
724
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700725static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
726 char *argv[])
727{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700728 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700729}
730
731
732static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
733{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700734 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700735}
736
737
738static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
739{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700740 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700741}
742
743
744static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
745{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700746 if (argc == 0) {
747 printf("Invalid WPS_PIN command: need one or two arguments:\n"
748 "- BSSID: use 'any' to select any\n"
749 "- PIN: optional, used only with devices that have no "
750 "display\n");
751 return -1;
752 }
753
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700754 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700755}
756
757
758static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
759 char *argv[])
760{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700761 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700762}
763
764
765static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
766 char *argv[])
767{
768 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
769}
770
771
Dmitry Shmidt04949592012-07-19 12:16:46 -0700772#ifdef CONFIG_WPS_NFC
773
774static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
775{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700776 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700777}
778
779
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800780static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
781 char *argv[])
782{
783 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
784}
785
786
Dmitry Shmidt04949592012-07-19 12:16:46 -0700787static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
788 char *argv[])
789{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700790 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700791}
792
793
794static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
795 char *argv[])
796{
797 int ret;
798 char *buf;
799 size_t buflen;
800
801 if (argc != 1) {
802 printf("Invalid 'wps_nfc_tag_read' command - one argument "
803 "is required.\n");
804 return -1;
805 }
806
807 buflen = 18 + os_strlen(argv[0]);
808 buf = os_malloc(buflen);
809 if (buf == NULL)
810 return -1;
811 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
812
813 ret = wpa_ctrl_command(ctrl, buf);
814 os_free(buf);
815
816 return ret;
817}
818
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800819
820static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
821 char *argv[])
822{
823 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
824}
825
826
827static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
828 char *argv[])
829{
830 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
831}
832
833
834static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
835 char *argv[])
836{
837 int ret;
838 char *buf;
839 size_t buflen;
840
841 if (argc != 1) {
842 printf("Invalid 'nfc_rx_handover_req' command - one argument "
843 "is required.\n");
844 return -1;
845 }
846
847 buflen = 21 + os_strlen(argv[0]);
848 buf = os_malloc(buflen);
849 if (buf == NULL)
850 return -1;
851 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
852
853 ret = wpa_ctrl_command(ctrl, buf);
854 os_free(buf);
855
856 return ret;
857}
858
859
860static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
861 char *argv[])
862{
863 int ret;
864 char *buf;
865 size_t buflen;
866
867 if (argc != 1) {
868 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
869 "is required.\n");
870 return -1;
871 }
872
873 buflen = 21 + os_strlen(argv[0]);
874 buf = os_malloc(buflen);
875 if (buf == NULL)
876 return -1;
877 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
878
879 ret = wpa_ctrl_command(ctrl, buf);
880 os_free(buf);
881
882 return ret;
883}
884
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800885
886static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
887 char *argv[])
888{
889 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
890}
891
Dmitry Shmidt04949592012-07-19 12:16:46 -0700892#endif /* CONFIG_WPS_NFC */
893
894
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700895static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
896{
897 char cmd[256];
898 int res;
899
900 if (argc == 2)
901 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
902 argv[0], argv[1]);
903 else if (argc == 5 || argc == 6) {
904 char ssid_hex[2 * 32 + 1];
905 char key_hex[2 * 64 + 1];
906 int i;
907
908 ssid_hex[0] = '\0';
909 for (i = 0; i < 32; i++) {
910 if (argv[2][i] == '\0')
911 break;
912 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
913 }
914
915 key_hex[0] = '\0';
916 if (argc == 6) {
917 for (i = 0; i < 64; i++) {
918 if (argv[5][i] == '\0')
919 break;
920 os_snprintf(&key_hex[i * 2], 3, "%02x",
921 argv[5][i]);
922 }
923 }
924
925 res = os_snprintf(cmd, sizeof(cmd),
926 "WPS_REG %s %s %s %s %s %s",
927 argv[0], argv[1], ssid_hex, argv[3], argv[4],
928 key_hex);
929 } else {
930 printf("Invalid WPS_REG command: need two arguments:\n"
931 "- BSSID of the target AP\n"
932 "- AP PIN\n");
933 printf("Alternatively, six arguments can be used to "
934 "reconfigure the AP:\n"
935 "- BSSID of the target AP\n"
936 "- AP PIN\n"
937 "- new SSID\n"
938 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
939 "- new encr (NONE, WEP, TKIP, CCMP)\n"
940 "- new key\n");
941 return -1;
942 }
943
944 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
945 printf("Too long WPS_REG command.\n");
946 return -1;
947 }
948 return wpa_ctrl_command(ctrl, cmd);
949}
950
951
952static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
953 char *argv[])
954{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700955 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700956}
957
958
959static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
960 char *argv[])
961{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700962 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700963}
964
965
966static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
967 char *argv[])
968{
969 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
970
971}
972
973
974static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
975 char *argv[])
976{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700977 if (argc < 2) {
978 printf("Invalid WPS_ER_PIN command: need at least two "
979 "arguments:\n"
980 "- UUID: use 'any' to select any\n"
981 "- PIN: Enrollee PIN\n"
982 "optional: - Enrollee MAC address\n");
983 return -1;
984 }
985
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700986 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700987}
988
989
990static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
991 char *argv[])
992{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700993 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700994}
995
996
997static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
998 char *argv[])
999{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001000 if (argc != 2) {
1001 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1002 "- UUID: specify which AP to use\n"
1003 "- PIN: AP PIN\n");
1004 return -1;
1005 }
1006
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001007 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008}
1009
1010
1011static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1012 char *argv[])
1013{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001014 if (argc != 2) {
1015 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1016 "arguments:\n"
1017 "- UUID: specify which AP to use\n"
1018 "- Network configuration id\n");
1019 return -1;
1020 }
1021
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001022 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001023}
1024
1025
1026static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1027 char *argv[])
1028{
1029 char cmd[256];
1030 int res;
1031
1032 if (argc == 5 || argc == 6) {
1033 char ssid_hex[2 * 32 + 1];
1034 char key_hex[2 * 64 + 1];
1035 int i;
1036
1037 ssid_hex[0] = '\0';
1038 for (i = 0; i < 32; i++) {
1039 if (argv[2][i] == '\0')
1040 break;
1041 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1042 }
1043
1044 key_hex[0] = '\0';
1045 if (argc == 6) {
1046 for (i = 0; i < 64; i++) {
1047 if (argv[5][i] == '\0')
1048 break;
1049 os_snprintf(&key_hex[i * 2], 3, "%02x",
1050 argv[5][i]);
1051 }
1052 }
1053
1054 res = os_snprintf(cmd, sizeof(cmd),
1055 "WPS_ER_CONFIG %s %s %s %s %s %s",
1056 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1057 key_hex);
1058 } else {
1059 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1060 "- AP UUID\n"
1061 "- AP PIN\n"
1062 "- new SSID\n"
1063 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1064 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1065 "- new key\n");
1066 return -1;
1067 }
1068
1069 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1070 printf("Too long WPS_ER_CONFIG command.\n");
1071 return -1;
1072 }
1073 return wpa_ctrl_command(ctrl, cmd);
1074}
1075
1076
Dmitry Shmidt04949592012-07-19 12:16:46 -07001077#ifdef CONFIG_WPS_NFC
1078static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1079 char *argv[])
1080{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001081 if (argc != 2) {
1082 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1083 "arguments:\n"
1084 "- WPS/NDEF: token format\n"
1085 "- UUID: specify which AP to use\n");
1086 return -1;
1087 }
1088
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001089 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001090}
1091#endif /* CONFIG_WPS_NFC */
1092
1093
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001094static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1095{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001096 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001097}
1098
1099
1100static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1101{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001102 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001103}
1104
1105
1106static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1107{
1108 char cmd[256], *pos, *end;
1109 int i, ret;
1110
1111 if (argc < 2) {
1112 printf("Invalid IDENTITY command: needs two arguments "
1113 "(network id and identity)\n");
1114 return -1;
1115 }
1116
1117 end = cmd + sizeof(cmd);
1118 pos = cmd;
1119 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1120 argv[0], argv[1]);
1121 if (ret < 0 || ret >= end - pos) {
1122 printf("Too long IDENTITY command.\n");
1123 return -1;
1124 }
1125 pos += ret;
1126 for (i = 2; i < argc; i++) {
1127 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1128 if (ret < 0 || ret >= end - pos) {
1129 printf("Too long IDENTITY command.\n");
1130 return -1;
1131 }
1132 pos += ret;
1133 }
1134
1135 return wpa_ctrl_command(ctrl, cmd);
1136}
1137
1138
1139static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1140{
1141 char cmd[256], *pos, *end;
1142 int i, ret;
1143
1144 if (argc < 2) {
1145 printf("Invalid PASSWORD command: needs two arguments "
1146 "(network id and password)\n");
1147 return -1;
1148 }
1149
1150 end = cmd + sizeof(cmd);
1151 pos = cmd;
1152 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1153 argv[0], argv[1]);
1154 if (ret < 0 || ret >= end - pos) {
1155 printf("Too long PASSWORD command.\n");
1156 return -1;
1157 }
1158 pos += ret;
1159 for (i = 2; i < argc; i++) {
1160 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1161 if (ret < 0 || ret >= end - pos) {
1162 printf("Too long PASSWORD command.\n");
1163 return -1;
1164 }
1165 pos += ret;
1166 }
1167
1168 return wpa_ctrl_command(ctrl, cmd);
1169}
1170
1171
1172static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1173 char *argv[])
1174{
1175 char cmd[256], *pos, *end;
1176 int i, ret;
1177
1178 if (argc < 2) {
1179 printf("Invalid NEW_PASSWORD command: needs two arguments "
1180 "(network id and password)\n");
1181 return -1;
1182 }
1183
1184 end = cmd + sizeof(cmd);
1185 pos = cmd;
1186 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1187 argv[0], argv[1]);
1188 if (ret < 0 || ret >= end - pos) {
1189 printf("Too long NEW_PASSWORD command.\n");
1190 return -1;
1191 }
1192 pos += ret;
1193 for (i = 2; i < argc; i++) {
1194 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1195 if (ret < 0 || ret >= end - pos) {
1196 printf("Too long NEW_PASSWORD command.\n");
1197 return -1;
1198 }
1199 pos += ret;
1200 }
1201
1202 return wpa_ctrl_command(ctrl, cmd);
1203}
1204
1205
1206static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1207{
1208 char cmd[256], *pos, *end;
1209 int i, ret;
1210
1211 if (argc < 2) {
1212 printf("Invalid PIN command: needs two arguments "
1213 "(network id and pin)\n");
1214 return -1;
1215 }
1216
1217 end = cmd + sizeof(cmd);
1218 pos = cmd;
1219 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1220 argv[0], argv[1]);
1221 if (ret < 0 || ret >= end - pos) {
1222 printf("Too long PIN command.\n");
1223 return -1;
1224 }
1225 pos += ret;
1226 for (i = 2; i < argc; i++) {
1227 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1228 if (ret < 0 || ret >= end - pos) {
1229 printf("Too long PIN command.\n");
1230 return -1;
1231 }
1232 pos += ret;
1233 }
1234 return wpa_ctrl_command(ctrl, cmd);
1235}
1236
1237
1238static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1239{
1240 char cmd[256], *pos, *end;
1241 int i, ret;
1242
1243 if (argc < 2) {
1244 printf("Invalid OTP command: needs two arguments (network "
1245 "id and password)\n");
1246 return -1;
1247 }
1248
1249 end = cmd + sizeof(cmd);
1250 pos = cmd;
1251 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1252 argv[0], argv[1]);
1253 if (ret < 0 || ret >= end - pos) {
1254 printf("Too long OTP command.\n");
1255 return -1;
1256 }
1257 pos += ret;
1258 for (i = 2; i < argc; i++) {
1259 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1260 if (ret < 0 || ret >= end - pos) {
1261 printf("Too long OTP command.\n");
1262 return -1;
1263 }
1264 pos += ret;
1265 }
1266
1267 return wpa_ctrl_command(ctrl, cmd);
1268}
1269
1270
1271static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1272 char *argv[])
1273{
1274 char cmd[256], *pos, *end;
1275 int i, ret;
1276
1277 if (argc < 2) {
1278 printf("Invalid PASSPHRASE command: needs two arguments "
1279 "(network id and passphrase)\n");
1280 return -1;
1281 }
1282
1283 end = cmd + sizeof(cmd);
1284 pos = cmd;
1285 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1286 argv[0], argv[1]);
1287 if (ret < 0 || ret >= end - pos) {
1288 printf("Too long PASSPHRASE command.\n");
1289 return -1;
1290 }
1291 pos += ret;
1292 for (i = 2; i < argc; i++) {
1293 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1294 if (ret < 0 || ret >= end - pos) {
1295 printf("Too long PASSPHRASE command.\n");
1296 return -1;
1297 }
1298 pos += ret;
1299 }
1300
1301 return wpa_ctrl_command(ctrl, cmd);
1302}
1303
1304
1305static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1306{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001307 if (argc < 2) {
1308 printf("Invalid BSSID command: needs two arguments (network "
1309 "id and BSSID)\n");
1310 return -1;
1311 }
1312
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001313 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001314}
1315
1316
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001317static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1318{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001319 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001320}
1321
1322
1323static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1324{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001325 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001326}
1327
1328
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001329static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1330 char *argv[])
1331{
1332 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1333}
1334
1335
1336static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1337 char *argv[])
1338{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001339 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001340}
1341
1342
1343static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1344 char *argv[])
1345{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001346 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001347}
1348
1349
1350static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1351 char *argv[])
1352{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001353 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001354}
1355
1356
1357static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1358 char *argv[])
1359{
1360 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1361}
1362
1363
1364static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1365 char *argv[])
1366{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001367 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001368}
1369
1370
1371static void wpa_cli_show_network_variables(void)
1372{
1373 printf("set_network variables:\n"
1374 " ssid (network name, SSID)\n"
1375 " psk (WPA passphrase or pre-shared key)\n"
1376 " key_mgmt (key management protocol)\n"
1377 " identity (EAP identity)\n"
1378 " password (EAP password)\n"
1379 " ...\n"
1380 "\n"
1381 "Note: Values are entered in the same format as the "
1382 "configuration file is using,\n"
1383 "i.e., strings values need to be inside double quotation "
1384 "marks.\n"
1385 "For example: set_network 1 ssid \"network name\"\n"
1386 "\n"
1387 "Please see wpa_supplicant.conf documentation for full list "
1388 "of\navailable variables.\n");
1389}
1390
1391
1392static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1393 char *argv[])
1394{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001395 if (argc == 0) {
1396 wpa_cli_show_network_variables();
1397 return 0;
1398 }
1399
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001400 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001401 printf("Invalid SET_NETWORK command: needs three arguments\n"
1402 "(network id, variable name, and value)\n");
1403 return -1;
1404 }
1405
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001406 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001407}
1408
1409
1410static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1411 char *argv[])
1412{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001413 if (argc == 0) {
1414 wpa_cli_show_network_variables();
1415 return 0;
1416 }
1417
1418 if (argc != 2) {
1419 printf("Invalid GET_NETWORK command: needs two arguments\n"
1420 "(network id and variable name)\n");
1421 return -1;
1422 }
1423
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001424 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001425}
1426
1427
Dmitry Shmidt04949592012-07-19 12:16:46 -07001428static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1429 char *argv[])
1430{
1431 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1432}
1433
1434
1435static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1436{
1437 return wpa_ctrl_command(ctrl, "ADD_CRED");
1438}
1439
1440
1441static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1442 char *argv[])
1443{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001444 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001445}
1446
1447
1448static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1449{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001450 if (argc != 3) {
1451 printf("Invalid SET_CRED command: needs three arguments\n"
1452 "(cred id, variable name, and value)\n");
1453 return -1;
1454 }
1455
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001456 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001457}
1458
1459
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001460static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1461 char *argv[])
1462{
1463 return wpa_ctrl_command(ctrl, "DISCONNECT");
1464}
1465
1466
1467static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1468 char *argv[])
1469{
1470 return wpa_ctrl_command(ctrl, "RECONNECT");
1471}
1472
1473
1474static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1475 char *argv[])
1476{
1477 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1478}
1479
1480
1481static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1482{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001483 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001484}
1485
1486
1487static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1488 char *argv[])
1489{
1490 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1491}
1492
1493
1494static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1495{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001496 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001497}
1498
1499
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001500static char ** wpa_cli_complete_bss(const char *str, int pos)
1501{
1502 int arg = get_cmd_arg_num(str, pos);
1503 char **res = NULL;
1504
1505 switch (arg) {
1506 case 1:
1507 res = cli_txt_list_array(&bsses);
1508 break;
1509 }
1510
1511 return res;
1512}
1513
1514
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001515static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1516 char *argv[])
1517{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001518 if (argc < 1 || argc > 2) {
1519 printf("Invalid GET_CAPABILITY command: need either one or "
1520 "two arguments\n");
1521 return -1;
1522 }
1523
1524 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1525 printf("Invalid GET_CAPABILITY command: second argument, "
1526 "if any, must be 'strict'\n");
1527 return -1;
1528 }
1529
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001530 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001531}
1532
1533
1534static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1535{
1536 printf("Available interfaces:\n");
1537 return wpa_ctrl_command(ctrl, "INTERFACES");
1538}
1539
1540
1541static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1542{
1543 if (argc < 1) {
1544 wpa_cli_list_interfaces(ctrl);
1545 return 0;
1546 }
1547
1548 wpa_cli_close_connection();
1549 os_free(ctrl_ifname);
1550 ctrl_ifname = os_strdup(argv[0]);
1551
1552 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1553 printf("Connected to interface '%s.\n", ctrl_ifname);
1554 } else {
1555 printf("Could not connect to interface '%s' - re-trying\n",
1556 ctrl_ifname);
1557 }
1558 return 0;
1559}
1560
1561
1562static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1563 char *argv[])
1564{
1565 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1566}
1567
1568
1569static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1570 char *argv[])
1571{
1572 return wpa_ctrl_command(ctrl, "TERMINATE");
1573}
1574
1575
1576static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1577 char *argv[])
1578{
1579 char cmd[256];
1580 int res;
1581
1582 if (argc < 1) {
1583 printf("Invalid INTERFACE_ADD command: needs at least one "
1584 "argument (interface name)\n"
1585 "All arguments: ifname confname driver ctrl_interface "
1586 "driver_param bridge_name\n");
1587 return -1;
1588 }
1589
1590 /*
1591 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1592 * <driver_param>TAB<bridge_name>
1593 */
1594 res = os_snprintf(cmd, sizeof(cmd),
1595 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1596 argv[0],
1597 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1598 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1599 argc > 5 ? argv[5] : "");
1600 if (res < 0 || (size_t) res >= sizeof(cmd))
1601 return -1;
1602 cmd[sizeof(cmd) - 1] = '\0';
1603 return wpa_ctrl_command(ctrl, cmd);
1604}
1605
1606
1607static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1608 char *argv[])
1609{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001610 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001611}
1612
1613
1614static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1615 char *argv[])
1616{
1617 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1618}
1619
1620
1621#ifdef CONFIG_AP
1622static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1623{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001624 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001625}
1626
1627
1628static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1629 char *addr, size_t addr_len)
1630{
1631 char buf[4096], *pos;
1632 size_t len;
1633 int ret;
1634
1635 if (ctrl_conn == NULL) {
1636 printf("Not connected to hostapd - command dropped.\n");
1637 return -1;
1638 }
1639 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001640 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001641 wpa_cli_msg_cb);
1642 if (ret == -2) {
1643 printf("'%s' command timed out.\n", cmd);
1644 return -2;
1645 } else if (ret < 0) {
1646 printf("'%s' command failed.\n", cmd);
1647 return -1;
1648 }
1649
1650 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001651 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001652 return -1;
1653 printf("%s", buf);
1654
1655 pos = buf;
1656 while (*pos != '\0' && *pos != '\n')
1657 pos++;
1658 *pos = '\0';
1659 os_strlcpy(addr, buf, addr_len);
1660 return 0;
1661}
1662
1663
1664static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1665{
1666 char addr[32], cmd[64];
1667
1668 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1669 return 0;
1670 do {
1671 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1672 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1673
1674 return -1;
1675}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001676
1677
1678static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1679 char *argv[])
1680{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001681 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001682}
1683
1684
1685static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1686 char *argv[])
1687{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001688 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001689}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001690#endif /* CONFIG_AP */
1691
1692
1693static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1694{
1695 return wpa_ctrl_command(ctrl, "SUSPEND");
1696}
1697
1698
1699static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1700{
1701 return wpa_ctrl_command(ctrl, "RESUME");
1702}
1703
1704
1705static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1706{
1707 return wpa_ctrl_command(ctrl, "DROP_SA");
1708}
1709
1710
1711static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1712{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001713 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001714}
1715
1716
1717#ifdef CONFIG_P2P
1718
1719static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1720{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001721 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1722}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001723
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001724
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001725static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1726{
1727 char **res = NULL;
1728 int arg = get_cmd_arg_num(str, pos);
1729
1730 res = os_calloc(6, sizeof(char *));
1731 if (res == NULL)
1732 return NULL;
1733 res[0] = os_strdup("type=social");
1734 if (res[0] == NULL) {
1735 os_free(res);
1736 return NULL;
1737 }
1738 res[1] = os_strdup("type=progressive");
1739 if (res[1] == NULL)
1740 return res;
1741 res[2] = os_strdup("delay=");
1742 if (res[2] == NULL)
1743 return res;
1744 res[3] = os_strdup("dev_id=");
1745 if (res[3] == NULL)
1746 return res;
1747 if (arg == 1)
1748 res[4] = os_strdup("[timeout]");
1749
1750 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001751}
1752
1753
1754static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1755 char *argv[])
1756{
1757 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1758}
1759
1760
1761static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1762 char *argv[])
1763{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001764 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001765}
1766
1767
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001768static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1769{
1770 int arg = get_cmd_arg_num(str, pos);
1771 char **res = NULL;
1772
1773 switch (arg) {
1774 case 1:
1775 res = cli_txt_list_array(&p2p_peers);
1776 break;
1777 }
1778
1779 return res;
1780}
1781
1782
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001783static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1784 char *argv[])
1785{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001786 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787}
1788
1789
1790static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1791 char *argv[])
1792{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001793 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001794}
1795
1796
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001797static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1798{
1799 int arg = get_cmd_arg_num(str, pos);
1800 char **res = NULL;
1801
1802 switch (arg) {
1803 case 1:
1804 res = cli_txt_list_array(&p2p_groups);
1805 break;
1806 }
1807
1808 return res;
1809}
1810
1811
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001812static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1813 char *argv[])
1814{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001815 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001816}
1817
1818
1819static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1820 char *argv[])
1821{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001822 if (argc != 2 && argc != 3) {
1823 printf("Invalid P2P_PROV_DISC command: needs at least "
1824 "two arguments, address and config method\n"
1825 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001826 return -1;
1827 }
1828
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001829 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001830}
1831
1832
1833static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1834 char *argv[])
1835{
1836 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1837}
1838
1839
1840static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1841 char *argv[])
1842{
1843 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001844
1845 if (argc != 2 && argc != 4) {
1846 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1847 "arguments (address and TLVs) or four arguments "
1848 "(address, \"upnp\", version, search target "
1849 "(SSDP ST:)\n");
1850 return -1;
1851 }
1852
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001853 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001854 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001855 return wpa_ctrl_command(ctrl, cmd);
1856}
1857
1858
1859static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1860 int argc, char *argv[])
1861{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001862 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001863}
1864
1865
1866static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1867 char *argv[])
1868{
1869 char cmd[4096];
1870 int res;
1871
1872 if (argc != 4) {
1873 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1874 "arguments (freq, address, dialog token, and TLVs)\n");
1875 return -1;
1876 }
1877
1878 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1879 argv[0], argv[1], argv[2], argv[3]);
1880 if (res < 0 || (size_t) res >= sizeof(cmd))
1881 return -1;
1882 cmd[sizeof(cmd) - 1] = '\0';
1883 return wpa_ctrl_command(ctrl, cmd);
1884}
1885
1886
1887static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1888 char *argv[])
1889{
1890 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1891}
1892
1893
1894static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1895 int argc, char *argv[])
1896{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001897 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001898}
1899
1900
1901static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1902 char *argv[])
1903{
1904 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1905}
1906
1907
1908static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1909 char *argv[])
1910{
1911 char cmd[4096];
1912 int res;
1913
1914 if (argc != 3 && argc != 4) {
1915 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1916 "arguments\n");
1917 return -1;
1918 }
1919
1920 if (argc == 4)
1921 res = os_snprintf(cmd, sizeof(cmd),
1922 "P2P_SERVICE_ADD %s %s %s %s",
1923 argv[0], argv[1], argv[2], argv[3]);
1924 else
1925 res = os_snprintf(cmd, sizeof(cmd),
1926 "P2P_SERVICE_ADD %s %s %s",
1927 argv[0], argv[1], argv[2]);
1928 if (res < 0 || (size_t) res >= sizeof(cmd))
1929 return -1;
1930 cmd[sizeof(cmd) - 1] = '\0';
1931 return wpa_ctrl_command(ctrl, cmd);
1932}
1933
1934
1935static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1936 char *argv[])
1937{
1938 char cmd[4096];
1939 int res;
1940
1941 if (argc != 2 && argc != 3) {
1942 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1943 "arguments\n");
1944 return -1;
1945 }
1946
1947 if (argc == 3)
1948 res = os_snprintf(cmd, sizeof(cmd),
1949 "P2P_SERVICE_DEL %s %s %s",
1950 argv[0], argv[1], argv[2]);
1951 else
1952 res = os_snprintf(cmd, sizeof(cmd),
1953 "P2P_SERVICE_DEL %s %s",
1954 argv[0], argv[1]);
1955 if (res < 0 || (size_t) res >= sizeof(cmd))
1956 return -1;
1957 cmd[sizeof(cmd) - 1] = '\0';
1958 return wpa_ctrl_command(ctrl, cmd);
1959}
1960
1961
1962static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1963 int argc, char *argv[])
1964{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001965 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001966}
1967
1968
1969static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1970 int argc, char *argv[])
1971{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001972 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001973}
1974
1975
1976static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1977{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001978 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001979}
1980
1981
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001982static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1983{
1984 int arg = get_cmd_arg_num(str, pos);
1985 char **res = NULL;
1986
1987 switch (arg) {
1988 case 1:
1989 res = cli_txt_list_array(&p2p_peers);
1990 break;
1991 }
1992
1993 return res;
1994}
1995
1996
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001997static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1998 char *addr, size_t addr_len,
1999 int discovered)
2000{
2001 char buf[4096], *pos;
2002 size_t len;
2003 int ret;
2004
2005 if (ctrl_conn == NULL)
2006 return -1;
2007 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002008 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009 wpa_cli_msg_cb);
2010 if (ret == -2) {
2011 printf("'%s' command timed out.\n", cmd);
2012 return -2;
2013 } else if (ret < 0) {
2014 printf("'%s' command failed.\n", cmd);
2015 return -1;
2016 }
2017
2018 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002019 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002020 return -1;
2021
2022 pos = buf;
2023 while (*pos != '\0' && *pos != '\n')
2024 pos++;
2025 *pos++ = '\0';
2026 os_strlcpy(addr, buf, addr_len);
2027 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2028 printf("%s\n", addr);
2029 return 0;
2030}
2031
2032
2033static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2034{
2035 char addr[32], cmd[64];
2036 int discovered;
2037
2038 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2039
2040 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2041 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002042 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002043 do {
2044 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2045 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2046 discovered) == 0);
2047
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002048 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002049}
2050
2051
2052static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2053{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002054 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002055}
2056
2057
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002058static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2059{
2060 int arg = get_cmd_arg_num(str, pos);
2061 const char *fields[] = {
2062 "discoverability",
2063 "managed",
2064 "listen_channel",
2065 "ssid_postfix",
2066 "noa",
2067 "ps",
2068 "oppps",
2069 "ctwindow",
2070 "disabled",
2071 "conc_pref",
2072 "force_long_sd",
2073 "peer_filter",
2074 "cross_connect",
2075 "go_apsd",
2076 "client_apsd",
2077 "disallow_freq",
2078 "disc_int",
2079 "per_sta_psk",
2080 };
2081 int i, num_fields = sizeof(fields) / sizeof(fields[0]);
2082
2083 if (arg == 1) {
2084 char **res = os_calloc(num_fields + 1, sizeof(char *));
2085 if (res == NULL)
2086 return NULL;
2087 for (i = 0; i < num_fields; i++) {
2088 res[i] = os_strdup(fields[i]);
2089 if (res[i] == NULL)
2090 return res;
2091 }
2092 return res;
2093 }
2094
2095 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2096 return cli_txt_list_array(&p2p_peers);
2097
2098 return NULL;
2099}
2100
2101
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002102static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2103{
2104 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2105}
2106
2107
2108static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2109 char *argv[])
2110{
2111 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2112}
2113
2114
2115static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2116 char *argv[])
2117{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002118 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002119}
2120
2121
2122static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2123 char *argv[])
2124{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002125 if (argc != 0 && argc != 2 && argc != 4) {
2126 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2127 "(preferred duration, interval; in microsecods).\n"
2128 "Optional second pair can be used to provide "
2129 "acceptable values.\n");
2130 return -1;
2131 }
2132
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002133 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002134}
2135
2136
2137static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2138 char *argv[])
2139{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002140 if (argc != 0 && argc != 2) {
2141 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2142 "(availability period, availability interval; in "
2143 "millisecods).\n"
2144 "Extended Listen Timing can be cancelled with this "
2145 "command when used without parameters.\n");
2146 return -1;
2147 }
2148
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002149 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2150}
2151
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002152
2153static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2154 char *argv[])
2155{
2156 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2157}
2158
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002159#endif /* CONFIG_P2P */
2160
2161#ifdef CONFIG_WIFI_DISPLAY
2162
2163static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2164 char *argv[])
2165{
2166 char cmd[100];
2167 int res;
2168
2169 if (argc != 1 && argc != 2) {
2170 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2171 "arguments (subelem, hexdump)\n");
2172 return -1;
2173 }
2174
2175 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2176 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002177 if (res < 0 || (size_t) res >= sizeof(cmd))
2178 return -1;
2179 cmd[sizeof(cmd) - 1] = '\0';
2180 return wpa_ctrl_command(ctrl, cmd);
2181}
2182
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002183
2184static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2185 char *argv[])
2186{
2187 char cmd[100];
2188 int res;
2189
2190 if (argc != 1) {
2191 printf("Invalid WFD_SUBELEM_GET command: needs one "
2192 "argument (subelem)\n");
2193 return -1;
2194 }
2195
2196 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2197 argv[0]);
2198 if (res < 0 || (size_t) res >= sizeof(cmd))
2199 return -1;
2200 cmd[sizeof(cmd) - 1] = '\0';
2201 return wpa_ctrl_command(ctrl, cmd);
2202}
2203#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002204
2205
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002206#ifdef CONFIG_INTERWORKING
2207static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2208 char *argv[])
2209{
2210 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2211}
2212
2213
2214static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2215 char *argv[])
2216{
2217 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2218}
2219
2220
2221static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2222 char *argv[])
2223{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002224 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002225}
2226
2227
2228static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2229 char *argv[])
2230{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002231 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002232}
2233
2234
2235static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2236{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002237 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2238}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002239
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002240
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002241static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2242 char *argv[])
2243{
2244 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2245}
2246
2247
2248static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2249 char *argv[])
2250{
2251 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002252}
2253#endif /* CONFIG_INTERWORKING */
2254
2255
Dmitry Shmidt04949592012-07-19 12:16:46 -07002256#ifdef CONFIG_HS20
2257
2258static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2259 char *argv[])
2260{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002261 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002262}
2263
2264
2265static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2266 char *argv[])
2267{
2268 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002269
2270 if (argc == 0) {
2271 printf("Command needs one or two arguments (dst mac addr and "
2272 "optional home realm)\n");
2273 return -1;
2274 }
2275
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002276 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2277 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002278 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002279
2280 return wpa_ctrl_command(ctrl, cmd);
2281}
2282
2283#endif /* CONFIG_HS20 */
2284
2285
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002286static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2287 char *argv[])
2288{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002289 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002290}
2291
2292
2293static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2294 char *argv[])
2295{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002296 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002297}
2298
2299
2300static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2301 char *argv[])
2302{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002303 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002304}
2305
2306
2307static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2308 char *argv[])
2309{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002310 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002311}
2312
2313
2314static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2315 char *argv[])
2316{
2317 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2318}
2319
2320
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002321static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2322 char *argv[])
2323{
2324 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2325}
2326
2327
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002328static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2329 char *argv[])
2330{
2331 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2332}
2333
Dmitry Shmidt04949592012-07-19 12:16:46 -07002334
2335#ifdef CONFIG_AUTOSCAN
2336
2337static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2338{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002339 if (argc == 0)
2340 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2341
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002342 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002343}
2344
2345#endif /* CONFIG_AUTOSCAN */
2346
2347
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002348#ifdef CONFIG_WNM
2349
2350static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2351{
2352 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2353}
2354
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002355
2356static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2357{
2358 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2359}
2360
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002361#endif /* CONFIG_WNM */
2362
2363
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002364static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2365{
2366 if (argc == 0)
2367 return -1;
2368 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2369}
2370
2371
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002372#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002373static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2374{
2375 char cmd[256];
2376 int i;
2377 int len;
2378
2379 if (argc < 1) {
2380 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2381 return -1;
2382 }
2383
2384 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2385 for (i=1; i < argc; i++)
2386 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2387 cmd[sizeof(cmd) - 1] = '\0';
2388 printf("%s: %s\n", __func__, cmd);
2389 return wpa_ctrl_command(ctrl, cmd);
2390}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002391#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002392
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002393
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002394static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2395{
2396 return wpa_ctrl_command(ctrl, "FLUSH");
2397}
2398
2399
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002400enum wpa_cli_cmd_flags {
2401 cli_cmd_flag_none = 0x00,
2402 cli_cmd_flag_sensitive = 0x01
2403};
2404
2405struct wpa_cli_cmd {
2406 const char *cmd;
2407 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002408 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002409 enum wpa_cli_cmd_flags flags;
2410 const char *usage;
2411};
2412
2413static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002414 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002415 cli_cmd_flag_none,
2416 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002417 { "ifname", wpa_cli_cmd_ifname, NULL,
2418 cli_cmd_flag_none,
2419 "= get current interface name" },
2420 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002421 cli_cmd_flag_none,
2422 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002423 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002424 cli_cmd_flag_none,
2425 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002426 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002427 cli_cmd_flag_none,
2428 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002429 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002430 cli_cmd_flag_none,
2431 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002432 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002434 "[command] = show usage help" },
2435 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002436 cli_cmd_flag_none,
2437 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002438 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002439 cli_cmd_flag_none,
2440 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002441 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002442 cli_cmd_flag_none,
2443 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002444 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002445 cli_cmd_flag_none,
2446 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002447 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002448 cli_cmd_flag_none,
2449 "= set variables (shows list of variables when run without "
2450 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002451 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002452 cli_cmd_flag_none,
2453 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002454 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002455 cli_cmd_flag_none,
2456 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002457 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002458 cli_cmd_flag_none,
2459 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002460 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002461 cli_cmd_flag_none,
2462 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002463 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002464 cli_cmd_flag_none,
2465 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002466 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002467 cli_cmd_flag_none,
2468 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002469 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002470 cli_cmd_flag_none,
2471 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002472 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002473 cli_cmd_flag_sensitive,
2474 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002475 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 cli_cmd_flag_sensitive,
2477 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002478 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002479 cli_cmd_flag_sensitive,
2480 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002481 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002482 cli_cmd_flag_sensitive,
2483 "<network id> <password> = configure one-time-password for an SSID"
2484 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002485 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002486 cli_cmd_flag_sensitive,
2487 "<network id> <passphrase> = configure private key passphrase\n"
2488 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002489 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002490 cli_cmd_flag_none,
2491 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002492 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002493 cli_cmd_flag_none,
2494 "<BSSID> = add a BSSID to the blacklist\n"
2495 "blacklist clear = clear the blacklist\n"
2496 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002497 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002498 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002499 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002500 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002501 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 cli_cmd_flag_none,
2503 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002504 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002505 cli_cmd_flag_none,
2506 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002507 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002508 cli_cmd_flag_none,
2509 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002510 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002511 cli_cmd_flag_none,
2512 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002513 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514 cli_cmd_flag_none,
2515 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002516 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 cli_cmd_flag_none,
2518 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002519 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 cli_cmd_flag_sensitive,
2521 "<network id> <variable> <value> = set network variables (shows\n"
2522 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002523 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002524 cli_cmd_flag_none,
2525 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002526 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002527 cli_cmd_flag_none,
2528 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002529 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002530 cli_cmd_flag_none,
2531 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002532 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002533 cli_cmd_flag_none,
2534 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002535 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002536 cli_cmd_flag_sensitive,
2537 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002538 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002539 cli_cmd_flag_none,
2540 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002541 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542 cli_cmd_flag_none,
2543 "= disconnect and wait for reassociate/reconnect command before\n"
2544 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002545 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002546 cli_cmd_flag_none,
2547 "= like reassociate, but only takes effect if already disconnected"
2548 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002549 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002550 cli_cmd_flag_none,
2551 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002552 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002553 cli_cmd_flag_none,
2554 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002555 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002556 cli_cmd_flag_none,
2557 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002558 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002559 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002560 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002561 "= get capabilies" },
2562 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002563 cli_cmd_flag_none,
2564 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002565 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002566 cli_cmd_flag_none,
2567 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002568 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002569 cli_cmd_flag_none,
2570 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2571 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2572 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002573 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002574 cli_cmd_flag_none,
2575 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002576 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002577 cli_cmd_flag_none,
2578 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002579 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002580 cli_cmd_flag_none,
2581 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002582 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002583 cli_cmd_flag_none,
2584 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002585 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002586 cli_cmd_flag_none,
2587 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002588 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002589 cli_cmd_flag_none,
2590 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002591 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002592 cli_cmd_flag_none,
2593 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002594 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002595 cli_cmd_flag_none,
2596 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002597 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002598 cli_cmd_flag_none,
2599 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002600 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002601 cli_cmd_flag_none,
2602 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002603 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002604 cli_cmd_flag_sensitive,
2605 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2606 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002607 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002608 cli_cmd_flag_sensitive,
2609 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002610 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002612#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002613 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002614 cli_cmd_flag_none,
2615 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002616 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2617 cli_cmd_flag_none,
2618 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002619 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002620 cli_cmd_flag_none,
2621 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002622 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002623 cli_cmd_flag_sensitive,
2624 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002625 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2626 cli_cmd_flag_none,
2627 "<NDEF> <WPS> = create NFC handover request" },
2628 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2629 cli_cmd_flag_none,
2630 "<NDEF> <WPS> = create NFC handover select" },
2631 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2632 cli_cmd_flag_none,
2633 "<hexdump of payload> = report received NFC handover request" },
2634 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2635 cli_cmd_flag_none,
2636 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002637 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2638 cli_cmd_flag_none,
2639 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2640 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002641#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002642 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643 cli_cmd_flag_sensitive,
2644 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002645 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646 cli_cmd_flag_sensitive,
2647 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002648 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002649 cli_cmd_flag_none,
2650 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002651 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652 cli_cmd_flag_none,
2653 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002654 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002655 cli_cmd_flag_sensitive,
2656 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002657 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002658 cli_cmd_flag_none,
2659 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002660 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 cli_cmd_flag_sensitive,
2662 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002663 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002664 cli_cmd_flag_none,
2665 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002666 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002667 cli_cmd_flag_sensitive,
2668 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002669#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002670 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002671 cli_cmd_flag_none,
2672 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2673#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002674 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002675 cli_cmd_flag_none,
2676 "<addr> = request RSN authentication with <addr> in IBSS" },
2677#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002678 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002679 cli_cmd_flag_none,
2680 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002681 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002682 cli_cmd_flag_none,
2683 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002684 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002685 cli_cmd_flag_none,
2686 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002687 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002688 cli_cmd_flag_none,
2689 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002690#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002691 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002692 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002693 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002694 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002695 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002696 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002697 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698 cli_cmd_flag_none,
2699 "<addr> = roam to the specified BSS" },
2700#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002701 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2702 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002703 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002704 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002705 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002706 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2707 cli_cmd_flag_none,
2708 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2709 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002710 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002711 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2712 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002713 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002714 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2715 "[ht40] = add a new P2P group (local end as GO)" },
2716 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2717 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002718 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002719 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002720 cli_cmd_flag_none,
2721 "= get the passphrase for a group (GO only)" },
2722 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002723 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002724 "<addr> <TLVs> = schedule service discovery request" },
2725 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002726 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002727 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002728 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002729 cli_cmd_flag_none,
2730 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002731 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002732 cli_cmd_flag_none,
2733 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002734 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002735 cli_cmd_flag_none,
2736 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002737 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002738 cli_cmd_flag_none,
2739 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002740 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002741 cli_cmd_flag_none,
2742 "<bonjour|upnp> <query|version> <response|service> = add a local "
2743 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002744 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002745 cli_cmd_flag_none,
2746 "<bonjour|upnp> <query|version> [|service] = remove a local "
2747 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002748 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002749 cli_cmd_flag_none,
2750 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002751 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002752 cli_cmd_flag_none,
2753 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002754 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002755 "[discovered] = list known (optionally, only fully discovered) P2P "
2756 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002757 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2758 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002759 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002760 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2761 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002762 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002763 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002764 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002765 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002766 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002767 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2768 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002769 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002770 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2771 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002772 "[<duration> <interval>] [<duration> <interval>] = request GO "
2773 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002774 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2775 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002776 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002777 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2778 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2779 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002780#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002781#ifdef CONFIG_WIFI_DISPLAY
2782 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2783 cli_cmd_flag_none,
2784 "<subelem> [contents] = set Wi-Fi Display subelement" },
2785 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2786 cli_cmd_flag_none,
2787 "<subelem> = get Wi-Fi Display subelement" },
2788#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002789#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002790 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002791 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002792 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2793 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002794 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002795 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002796 cli_cmd_flag_none,
2797 "[auto] = perform Interworking network selection" },
2798 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002799 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002800 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002801 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2802 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002803 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002804 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2805 cli_cmd_flag_none,
2806 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2807 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2808 wpa_cli_complete_bss, cli_cmd_flag_none,
2809 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002810#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002811#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002812 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2813 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002814 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2815 },
2816 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002817 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002818 "<addr> <home realm> = get HS20 nai home realm list" },
2819#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002820 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2821 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002822 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002823 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002824 cli_cmd_flag_none,
2825 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002826 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002827 cli_cmd_flag_none,
2828 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002829 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002830 cli_cmd_flag_none,
2831 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002832 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002833 cli_cmd_flag_none,
2834 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002835 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002836 cli_cmd_flag_none,
2837 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002838 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2839 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002840 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002841#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002842 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002843 "[params] = Set or unset (if none) autoscan parameters" },
2844#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002845#ifdef CONFIG_WNM
2846 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2847 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002848 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2849 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002850#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002851 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2852 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002853 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2854 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002855#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002856 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002857 cli_cmd_flag_none,
2858 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002859#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002860 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002861};
2862
2863
2864/*
2865 * Prints command usage, lines are padded with the specified string.
2866 */
2867static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2868{
2869 char c;
2870 size_t n;
2871
2872 printf("%s%s ", pad, cmd->cmd);
2873 for (n = 0; (c = cmd->usage[n]); n++) {
2874 printf("%c", c);
2875 if (c == '\n')
2876 printf("%s", pad);
2877 }
2878 printf("\n");
2879}
2880
2881
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002882static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002883{
2884 int n;
2885 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002886 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2887 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2888 print_cmd_help(&wpa_cli_commands[n], " ");
2889 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002890}
2891
2892
2893static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2894{
2895 const char *c, *delim;
2896 int n;
2897 size_t len;
2898
2899 delim = os_strchr(cmd, ' ');
2900 if (delim)
2901 len = delim - cmd;
2902 else
2903 len = os_strlen(cmd);
2904
2905 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2906 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2907 return (wpa_cli_commands[n].flags &
2908 cli_cmd_flag_sensitive);
2909 }
2910 return 0;
2911}
2912
2913
2914static char ** wpa_list_cmd_list(void)
2915{
2916 char **res;
2917 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002918 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002919
2920 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002921 count += dl_list_len(&p2p_groups);
2922 count += dl_list_len(&ifnames);
2923 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002924 if (res == NULL)
2925 return NULL;
2926
2927 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2928 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2929 if (res[i] == NULL)
2930 break;
2931 }
2932
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002933 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
2934 size_t len = 8 + os_strlen(e->txt);
2935 res[i] = os_malloc(len);
2936 if (res[i] == NULL)
2937 break;
2938 os_snprintf(res[i], len, "ifname=%s", e->txt);
2939 i++;
2940 }
2941
2942 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
2943 res[i] = os_strdup(e->txt);
2944 if (res[i] == NULL)
2945 break;
2946 i++;
2947 }
2948
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002949 return res;
2950}
2951
2952
2953static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2954 int pos)
2955{
2956 int i;
2957
2958 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2959 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002960 if (wpa_cli_commands[i].completion)
2961 return wpa_cli_commands[i].completion(str,
2962 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002963 edit_clear_line();
2964 printf("\r%s\n", wpa_cli_commands[i].usage);
2965 edit_redraw();
2966 break;
2967 }
2968 }
2969
2970 return NULL;
2971}
2972
2973
2974static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2975{
2976 char **res;
2977 const char *end;
2978 char *cmd;
2979
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002980 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
2981 end = os_strchr(str, ' ');
2982 if (end && pos > end - str) {
2983 pos -= end - str + 1;
2984 str = end + 1;
2985 }
2986 }
2987
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002988 end = os_strchr(str, ' ');
2989 if (end == NULL || str + pos < end)
2990 return wpa_list_cmd_list();
2991
2992 cmd = os_malloc(pos + 1);
2993 if (cmd == NULL)
2994 return NULL;
2995 os_memcpy(cmd, str, pos);
2996 cmd[end - str] = '\0';
2997 res = wpa_cli_cmd_completion(cmd, str, pos);
2998 os_free(cmd);
2999 return res;
3000}
3001
3002
3003static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3004{
3005 struct wpa_cli_cmd *cmd, *match = NULL;
3006 int count;
3007 int ret = 0;
3008
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003009 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3010 ifname_prefix = argv[0] + 7;
3011 argv = &argv[1];
3012 argc--;
3013 } else
3014 ifname_prefix = NULL;
3015
3016 if (argc == 0)
3017 return -1;
3018
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003019 count = 0;
3020 cmd = wpa_cli_commands;
3021 while (cmd->cmd) {
3022 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3023 {
3024 match = cmd;
3025 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3026 /* we have an exact match */
3027 count = 1;
3028 break;
3029 }
3030 count++;
3031 }
3032 cmd++;
3033 }
3034
3035 if (count > 1) {
3036 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3037 cmd = wpa_cli_commands;
3038 while (cmd->cmd) {
3039 if (os_strncasecmp(cmd->cmd, argv[0],
3040 os_strlen(argv[0])) == 0) {
3041 printf(" %s", cmd->cmd);
3042 }
3043 cmd++;
3044 }
3045 printf("\n");
3046 ret = 1;
3047 } else if (count == 0) {
3048 printf("Unknown command '%s'\n", argv[0]);
3049 ret = 1;
3050 } else {
3051 ret = match->handler(ctrl, argc - 1, &argv[1]);
3052 }
3053
3054 return ret;
3055}
3056
3057
3058static int str_match(const char *a, const char *b)
3059{
3060 return os_strncmp(a, b, os_strlen(b)) == 0;
3061}
3062
3063
3064static int wpa_cli_exec(const char *program, const char *arg1,
3065 const char *arg2)
3066{
3067 char *cmd;
3068 size_t len;
3069 int res;
3070 int ret = 0;
3071
3072 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3073 cmd = os_malloc(len);
3074 if (cmd == NULL)
3075 return -1;
3076 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3077 if (res < 0 || (size_t) res >= len) {
3078 os_free(cmd);
3079 return -1;
3080 }
3081 cmd[len - 1] = '\0';
3082#ifndef _WIN32_WCE
3083 if (system(cmd) < 0)
3084 ret = -1;
3085#endif /* _WIN32_WCE */
3086 os_free(cmd);
3087
3088 return ret;
3089}
3090
3091
3092static void wpa_cli_action_process(const char *msg)
3093{
3094 const char *pos;
3095 char *copy = NULL, *id, *pos2;
3096
3097 pos = msg;
3098 if (*pos == '<') {
3099 /* skip priority */
3100 pos = os_strchr(pos, '>');
3101 if (pos)
3102 pos++;
3103 else
3104 pos = msg;
3105 }
3106
3107 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3108 int new_id = -1;
3109 os_unsetenv("WPA_ID");
3110 os_unsetenv("WPA_ID_STR");
3111 os_unsetenv("WPA_CTRL_DIR");
3112
3113 pos = os_strstr(pos, "[id=");
3114 if (pos)
3115 copy = os_strdup(pos + 4);
3116
3117 if (copy) {
3118 pos2 = id = copy;
3119 while (*pos2 && *pos2 != ' ')
3120 pos2++;
3121 *pos2++ = '\0';
3122 new_id = atoi(id);
3123 os_setenv("WPA_ID", id, 1);
3124 while (*pos2 && *pos2 != '=')
3125 pos2++;
3126 if (*pos2 == '=')
3127 pos2++;
3128 id = pos2;
3129 while (*pos2 && *pos2 != ']')
3130 pos2++;
3131 *pos2 = '\0';
3132 os_setenv("WPA_ID_STR", id, 1);
3133 os_free(copy);
3134 }
3135
3136 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3137
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003138 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003139 wpa_cli_connected = 1;
3140 wpa_cli_last_id = new_id;
3141 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3142 }
3143 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3144 if (wpa_cli_connected) {
3145 wpa_cli_connected = 0;
3146 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3147 }
3148 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3149 wpa_cli_exec(action_file, ctrl_ifname, pos);
3150 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3151 wpa_cli_exec(action_file, ctrl_ifname, pos);
3152 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3153 wpa_cli_exec(action_file, ctrl_ifname, pos);
3154 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3155 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003156 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3157 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003158 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3159 wpa_cli_exec(action_file, ctrl_ifname, pos);
3160 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3161 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003162 } else if (str_match(pos, AP_STA_CONNECTED)) {
3163 wpa_cli_exec(action_file, ctrl_ifname, pos);
3164 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3165 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003166 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3167 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003168 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3169 printf("wpa_supplicant is terminating - stop monitoring\n");
3170 wpa_cli_quit = 1;
3171 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003172}
3173
3174
3175#ifndef CONFIG_ANSI_C_EXTRA
3176static void wpa_cli_action_cb(char *msg, size_t len)
3177{
3178 wpa_cli_action_process(msg);
3179}
3180#endif /* CONFIG_ANSI_C_EXTRA */
3181
3182
3183static void wpa_cli_reconnect(void)
3184{
3185 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003186 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3187 return;
3188
3189 if (interactive) {
3190 edit_clear_line();
3191 printf("\rConnection to wpa_supplicant re-established\n");
3192 edit_redraw();
3193 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003194}
3195
3196
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003197static void cli_event(const char *str)
3198{
3199 const char *start, *s;
3200
3201 start = os_strchr(str, '>');
3202 if (start == NULL)
3203 return;
3204
3205 start++;
3206
3207 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3208 s = os_strchr(start, ' ');
3209 if (s == NULL)
3210 return;
3211 s = os_strchr(s + 1, ' ');
3212 if (s == NULL)
3213 return;
3214 cli_txt_list_add(&bsses, s + 1);
3215 return;
3216 }
3217
3218 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3219 s = os_strchr(start, ' ');
3220 if (s == NULL)
3221 return;
3222 s = os_strchr(s + 1, ' ');
3223 if (s == NULL)
3224 return;
3225 cli_txt_list_del_addr(&bsses, s + 1);
3226 return;
3227 }
3228
3229#ifdef CONFIG_P2P
3230 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3231 s = os_strstr(start, " p2p_dev_addr=");
3232 if (s == NULL)
3233 return;
3234 cli_txt_list_add_addr(&p2p_peers, s + 14);
3235 return;
3236 }
3237
3238 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3239 s = os_strstr(start, " p2p_dev_addr=");
3240 if (s == NULL)
3241 return;
3242 cli_txt_list_del_addr(&p2p_peers, s + 14);
3243 return;
3244 }
3245
3246 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3247 s = os_strchr(start, ' ');
3248 if (s == NULL)
3249 return;
3250 cli_txt_list_add_word(&p2p_groups, s + 1);
3251 return;
3252 }
3253
3254 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3255 s = os_strchr(start, ' ');
3256 if (s == NULL)
3257 return;
3258 cli_txt_list_del_word(&p2p_groups, s + 1);
3259 return;
3260 }
3261#endif /* CONFIG_P2P */
3262}
3263
3264
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003265static int check_terminating(const char *msg)
3266{
3267 const char *pos = msg;
3268
3269 if (*pos == '<') {
3270 /* skip priority */
3271 pos = os_strchr(pos, '>');
3272 if (pos)
3273 pos++;
3274 else
3275 pos = msg;
3276 }
3277
3278 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3279 edit_clear_line();
3280 printf("\rConnection to wpa_supplicant lost - trying to "
3281 "reconnect\n");
3282 edit_redraw();
3283 wpa_cli_attached = 0;
3284 wpa_cli_close_connection();
3285 return 1;
3286 }
3287
3288 return 0;
3289}
3290
3291
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003292static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3293{
3294 if (ctrl_conn == NULL) {
3295 wpa_cli_reconnect();
3296 return;
3297 }
3298 while (wpa_ctrl_pending(ctrl) > 0) {
3299 char buf[256];
3300 size_t len = sizeof(buf) - 1;
3301 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3302 buf[len] = '\0';
3303 if (action_monitor)
3304 wpa_cli_action_process(buf);
3305 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003306 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003307 if (wpa_cli_show_event(buf)) {
3308 edit_clear_line();
3309 printf("\r%s\n", buf);
3310 edit_redraw();
3311 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003312
3313 if (interactive && check_terminating(buf) > 0)
3314 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003315 }
3316 } else {
3317 printf("Could not read pending message.\n");
3318 break;
3319 }
3320 }
3321
3322 if (wpa_ctrl_pending(ctrl) < 0) {
3323 printf("Connection to wpa_supplicant lost - trying to "
3324 "reconnect\n");
3325 wpa_cli_reconnect();
3326 }
3327}
3328
3329#define max_args 10
3330
3331static int tokenize_cmd(char *cmd, char *argv[])
3332{
3333 char *pos;
3334 int argc = 0;
3335
3336 pos = cmd;
3337 for (;;) {
3338 while (*pos == ' ')
3339 pos++;
3340 if (*pos == '\0')
3341 break;
3342 argv[argc] = pos;
3343 argc++;
3344 if (argc == max_args)
3345 break;
3346 if (*pos == '"') {
3347 char *pos2 = os_strrchr(pos, '"');
3348 if (pos2)
3349 pos = pos2 + 1;
3350 }
3351 while (*pos != '\0' && *pos != ' ')
3352 pos++;
3353 if (*pos == ' ')
3354 *pos++ = '\0';
3355 }
3356
3357 return argc;
3358}
3359
3360
3361static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3362{
3363 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3364 printf("Connection to wpa_supplicant lost - trying to "
3365 "reconnect\n");
3366 wpa_cli_close_connection();
3367 }
3368 if (!ctrl_conn)
3369 wpa_cli_reconnect();
3370 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3371}
3372
3373
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003374static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3375{
3376 wpa_cli_recv_pending(mon_conn, 0);
3377}
3378
3379
3380static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3381{
3382 char *argv[max_args];
3383 int argc;
3384 argc = tokenize_cmd(cmd, argv);
3385 if (argc)
3386 wpa_request(ctrl_conn, argc, argv);
3387}
3388
3389
3390static void wpa_cli_edit_eof_cb(void *ctx)
3391{
3392 eloop_terminate();
3393}
3394
3395
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003396static int warning_displayed = 0;
3397static char *hfile = NULL;
3398static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003399
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003400static void start_edit(void)
3401{
3402 char *home;
3403 char *ps = NULL;
3404
3405#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3406 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3407#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003408
3409 home = getenv("HOME");
3410 if (home) {
3411 const char *fname = ".wpa_cli_history";
3412 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3413 hfile = os_malloc(hfile_len);
3414 if (hfile)
3415 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3416 }
3417
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003418 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3419 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3420 eloop_terminate();
3421 return;
3422 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003423
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003424 edit_started = 1;
3425 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3426}
3427
3428
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003429static void update_bssid_list(struct wpa_ctrl *ctrl)
3430{
3431 char buf[4096];
3432 size_t len = sizeof(buf);
3433 int ret;
3434 char *cmd = "BSS RANGE=ALL MASK=0x2";
3435 char *pos, *end;
3436
3437 if (ctrl == NULL)
3438 return;
3439 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3440 if (ret < 0)
3441 return;
3442 buf[len] = '\0';
3443
3444 pos = buf;
3445 while (pos) {
3446 pos = os_strstr(pos, "bssid=");
3447 if (pos == NULL)
3448 break;
3449 pos += 6;
3450 end = os_strchr(pos, '\n');
3451 if (end == NULL)
3452 break;
3453 *end = '\0';
3454 cli_txt_list_add(&bsses, pos);
3455 pos = end + 1;
3456 }
3457}
3458
3459
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003460static void update_ifnames(struct wpa_ctrl *ctrl)
3461{
3462 char buf[4096];
3463 size_t len = sizeof(buf);
3464 int ret;
3465 char *cmd = "INTERFACES";
3466 char *pos, *end;
3467 char txt[200];
3468
3469 cli_txt_list_flush(&ifnames);
3470
3471 if (ctrl == NULL)
3472 return;
3473 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3474 if (ret < 0)
3475 return;
3476 buf[len] = '\0';
3477
3478 pos = buf;
3479 while (pos) {
3480 end = os_strchr(pos, '\n');
3481 if (end == NULL)
3482 break;
3483 *end = '\0';
3484 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3485 if (ret > 0 && ret < (int) sizeof(txt))
3486 cli_txt_list_add(&ifnames, txt);
3487 pos = end + 1;
3488 }
3489}
3490
3491
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003492static void try_connection(void *eloop_ctx, void *timeout_ctx)
3493{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003494 if (ctrl_conn)
3495 goto done;
3496
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003497 if (ctrl_ifname == NULL)
3498 ctrl_ifname = wpa_cli_get_default_ifname();
3499
3500 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3501 if (!warning_displayed) {
3502 printf("Could not connect to wpa_supplicant: "
3503 "%s - re-trying\n", ctrl_ifname);
3504 warning_displayed = 1;
3505 }
3506 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3507 return;
3508 }
3509
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003510 update_bssid_list(ctrl_conn);
3511
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003512 if (warning_displayed)
3513 printf("Connection established.\n");
3514
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003515done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003516 start_edit();
3517}
3518
3519
3520static void wpa_cli_interactive(void)
3521{
3522 printf("\nInteractive mode\n\n");
3523
3524 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003525 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003526 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003527
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003528 cli_txt_list_flush(&p2p_peers);
3529 cli_txt_list_flush(&p2p_groups);
3530 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003531 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003532 if (edit_started)
3533 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003534 os_free(hfile);
3535 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3536 wpa_cli_close_connection();
3537}
3538
3539
3540static void wpa_cli_action(struct wpa_ctrl *ctrl)
3541{
3542#ifdef CONFIG_ANSI_C_EXTRA
3543 /* TODO: ANSI C version(?) */
3544 printf("Action processing not supported in ANSI C build.\n");
3545#else /* CONFIG_ANSI_C_EXTRA */
3546 fd_set rfds;
3547 int fd, res;
3548 struct timeval tv;
3549 char buf[256]; /* note: large enough to fit in unsolicited messages */
3550 size_t len;
3551
3552 fd = wpa_ctrl_get_fd(ctrl);
3553
3554 while (!wpa_cli_quit) {
3555 FD_ZERO(&rfds);
3556 FD_SET(fd, &rfds);
3557 tv.tv_sec = ping_interval;
3558 tv.tv_usec = 0;
3559 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3560 if (res < 0 && errno != EINTR) {
3561 perror("select");
3562 break;
3563 }
3564
3565 if (FD_ISSET(fd, &rfds))
3566 wpa_cli_recv_pending(ctrl, 1);
3567 else {
3568 /* verify that connection is still working */
3569 len = sizeof(buf) - 1;
3570 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3571 wpa_cli_action_cb) < 0 ||
3572 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3573 printf("wpa_supplicant did not reply to PING "
3574 "command - exiting\n");
3575 break;
3576 }
3577 }
3578 }
3579#endif /* CONFIG_ANSI_C_EXTRA */
3580}
3581
3582
3583static void wpa_cli_cleanup(void)
3584{
3585 wpa_cli_close_connection();
3586 if (pid_file)
3587 os_daemonize_terminate(pid_file);
3588
3589 os_program_deinit();
3590}
3591
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003592
3593static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003594{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003595 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003596}
3597
3598
3599static char * wpa_cli_get_default_ifname(void)
3600{
3601 char *ifname = NULL;
3602
3603#ifdef CONFIG_CTRL_IFACE_UNIX
3604 struct dirent *dent;
3605 DIR *dir = opendir(ctrl_iface_dir);
3606 if (!dir) {
3607#ifdef ANDROID
3608 char ifprop[PROPERTY_VALUE_MAX];
3609 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3610 ifname = os_strdup(ifprop);
3611 printf("Using interface '%s'\n", ifname);
3612 return ifname;
3613 }
3614#endif /* ANDROID */
3615 return NULL;
3616 }
3617 while ((dent = readdir(dir))) {
3618#ifdef _DIRENT_HAVE_D_TYPE
3619 /*
3620 * Skip the file if it is not a socket. Also accept
3621 * DT_UNKNOWN (0) in case the C library or underlying
3622 * file system does not support d_type.
3623 */
3624 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3625 continue;
3626#endif /* _DIRENT_HAVE_D_TYPE */
3627 if (os_strcmp(dent->d_name, ".") == 0 ||
3628 os_strcmp(dent->d_name, "..") == 0)
3629 continue;
3630 printf("Selected interface '%s'\n", dent->d_name);
3631 ifname = os_strdup(dent->d_name);
3632 break;
3633 }
3634 closedir(dir);
3635#endif /* CONFIG_CTRL_IFACE_UNIX */
3636
3637#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003638 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003639 size_t len;
3640 struct wpa_ctrl *ctrl;
3641 int ret;
3642
3643 ctrl = wpa_ctrl_open(NULL);
3644 if (ctrl == NULL)
3645 return NULL;
3646
3647 len = sizeof(buf) - 1;
3648 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3649 if (ret >= 0) {
3650 buf[len] = '\0';
3651 pos = os_strchr(buf, '\n');
3652 if (pos)
3653 *pos = '\0';
3654 ifname = os_strdup(buf);
3655 }
3656 wpa_ctrl_close(ctrl);
3657#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3658
3659 return ifname;
3660}
3661
3662
3663int main(int argc, char *argv[])
3664{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003665 int c;
3666 int daemonize = 0;
3667 int ret = 0;
3668 const char *global = NULL;
3669
3670 if (os_program_init())
3671 return -1;
3672
3673 for (;;) {
3674 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3675 if (c < 0)
3676 break;
3677 switch (c) {
3678 case 'a':
3679 action_file = optarg;
3680 break;
3681 case 'B':
3682 daemonize = 1;
3683 break;
3684 case 'g':
3685 global = optarg;
3686 break;
3687 case 'G':
3688 ping_interval = atoi(optarg);
3689 break;
3690 case 'h':
3691 usage();
3692 return 0;
3693 case 'v':
3694 printf("%s\n", wpa_cli_version);
3695 return 0;
3696 case 'i':
3697 os_free(ctrl_ifname);
3698 ctrl_ifname = os_strdup(optarg);
3699 break;
3700 case 'p':
3701 ctrl_iface_dir = optarg;
3702 break;
3703 case 'P':
3704 pid_file = optarg;
3705 break;
3706 default:
3707 usage();
3708 return -1;
3709 }
3710 }
3711
3712 interactive = (argc == optind) && (action_file == NULL);
3713
3714 if (interactive)
3715 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3716
3717 if (eloop_init())
3718 return -1;
3719
3720 if (global) {
3721#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3722 ctrl_conn = wpa_ctrl_open(NULL);
3723#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3724 ctrl_conn = wpa_ctrl_open(global);
3725#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3726 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003727 fprintf(stderr, "Failed to connect to wpa_supplicant "
3728 "global interface: %s error: %s\n",
3729 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003730 return -1;
3731 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003732
3733 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003734 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003735 mon_conn = wpa_ctrl_open(global);
3736 if (mon_conn) {
3737 if (wpa_ctrl_attach(mon_conn) == 0) {
3738 wpa_cli_attached = 1;
3739 eloop_register_read_sock(
3740 wpa_ctrl_get_fd(mon_conn),
3741 wpa_cli_mon_receive,
3742 NULL, NULL);
3743 } else {
3744 printf("Failed to open monitor "
3745 "connection through global "
3746 "control interface\n");
3747 }
3748 }
3749 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003750 }
3751
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003752 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003753
3754 if (ctrl_ifname == NULL)
3755 ctrl_ifname = wpa_cli_get_default_ifname();
3756
3757 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003758 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003759 } else {
3760 if (!global &&
3761 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003762 fprintf(stderr, "Failed to connect to non-global "
3763 "ctrl_ifname: %s error: %s\n",
3764 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003765 return -1;
3766 }
3767
3768 if (action_file) {
3769 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3770 wpa_cli_attached = 1;
3771 } else {
3772 printf("Warning: Failed to attach to "
3773 "wpa_supplicant.\n");
3774 return -1;
3775 }
3776 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003777
3778 if (daemonize && os_daemonize(pid_file))
3779 return -1;
3780
3781 if (action_file)
3782 wpa_cli_action(ctrl_conn);
3783 else
3784 ret = wpa_request(ctrl_conn, argc - optind,
3785 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003786 }
3787
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003788 os_free(ctrl_ifname);
3789 eloop_destroy();
3790 wpa_cli_cleanup();
3791
3792 return ret;
3793}
3794
3795#else /* CONFIG_CTRL_IFACE */
3796int main(int argc, char *argv[])
3797{
3798 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3799 return -1;
3800}
3801#endif /* CONFIG_CTRL_IFACE */