blob: ba1f20765d7a567b2629806bac05f21b40abd055 [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;
73static int wpa_cli_connected = 0;
74static 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
2058static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2059{
2060 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2061}
2062
2063
2064static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2065 char *argv[])
2066{
2067 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2068}
2069
2070
2071static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2072 char *argv[])
2073{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002074 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002075}
2076
2077
2078static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2079 char *argv[])
2080{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002081 if (argc != 0 && argc != 2 && argc != 4) {
2082 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2083 "(preferred duration, interval; in microsecods).\n"
2084 "Optional second pair can be used to provide "
2085 "acceptable values.\n");
2086 return -1;
2087 }
2088
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002089 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002090}
2091
2092
2093static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2094 char *argv[])
2095{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002096 if (argc != 0 && argc != 2) {
2097 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2098 "(availability period, availability interval; in "
2099 "millisecods).\n"
2100 "Extended Listen Timing can be cancelled with this "
2101 "command when used without parameters.\n");
2102 return -1;
2103 }
2104
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002105 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2106}
2107
2108#endif /* CONFIG_P2P */
2109
2110#ifdef CONFIG_WIFI_DISPLAY
2111
2112static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2113 char *argv[])
2114{
2115 char cmd[100];
2116 int res;
2117
2118 if (argc != 1 && argc != 2) {
2119 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2120 "arguments (subelem, hexdump)\n");
2121 return -1;
2122 }
2123
2124 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2125 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002126 if (res < 0 || (size_t) res >= sizeof(cmd))
2127 return -1;
2128 cmd[sizeof(cmd) - 1] = '\0';
2129 return wpa_ctrl_command(ctrl, cmd);
2130}
2131
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002132
2133static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2134 char *argv[])
2135{
2136 char cmd[100];
2137 int res;
2138
2139 if (argc != 1) {
2140 printf("Invalid WFD_SUBELEM_GET command: needs one "
2141 "argument (subelem)\n");
2142 return -1;
2143 }
2144
2145 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2146 argv[0]);
2147 if (res < 0 || (size_t) res >= sizeof(cmd))
2148 return -1;
2149 cmd[sizeof(cmd) - 1] = '\0';
2150 return wpa_ctrl_command(ctrl, cmd);
2151}
2152#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002153
2154
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002155#ifdef CONFIG_INTERWORKING
2156static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2157 char *argv[])
2158{
2159 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2160}
2161
2162
2163static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2164 char *argv[])
2165{
2166 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2167}
2168
2169
2170static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2171 char *argv[])
2172{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002173 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002174}
2175
2176
2177static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2178 char *argv[])
2179{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002180 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002181}
2182
2183
2184static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2185{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002186 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2187}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002188
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002189
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002190static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2191 char *argv[])
2192{
2193 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2194}
2195
2196
2197static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2198 char *argv[])
2199{
2200 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002201}
2202#endif /* CONFIG_INTERWORKING */
2203
2204
Dmitry Shmidt04949592012-07-19 12:16:46 -07002205#ifdef CONFIG_HS20
2206
2207static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2208 char *argv[])
2209{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002210 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002211}
2212
2213
2214static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2215 char *argv[])
2216{
2217 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002218
2219 if (argc == 0) {
2220 printf("Command needs one or two arguments (dst mac addr and "
2221 "optional home realm)\n");
2222 return -1;
2223 }
2224
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002225 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2226 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002227 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002228
2229 return wpa_ctrl_command(ctrl, cmd);
2230}
2231
2232#endif /* CONFIG_HS20 */
2233
2234
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002235static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2236 char *argv[])
2237{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002238 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002239}
2240
2241
2242static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2243 char *argv[])
2244{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002245 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002246}
2247
2248
2249static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2250 char *argv[])
2251{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002252 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002253}
2254
2255
2256static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2257 char *argv[])
2258{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002259 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002260}
2261
2262
2263static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2264 char *argv[])
2265{
2266 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2267}
2268
2269
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002270static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2271 char *argv[])
2272{
2273 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2274}
2275
2276
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002277static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2278 char *argv[])
2279{
2280 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2281}
2282
Dmitry Shmidt04949592012-07-19 12:16:46 -07002283
2284#ifdef CONFIG_AUTOSCAN
2285
2286static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2287{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002288 if (argc == 0)
2289 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2290
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002291 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002292}
2293
2294#endif /* CONFIG_AUTOSCAN */
2295
2296
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002297#ifdef CONFIG_WNM
2298
2299static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2300{
2301 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2302}
2303
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002304
2305static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2306{
2307 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2308}
2309
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002310#endif /* CONFIG_WNM */
2311
2312
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002313static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2314{
2315 if (argc == 0)
2316 return -1;
2317 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2318}
2319
2320
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002321#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002322static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2323{
2324 char cmd[256];
2325 int i;
2326 int len;
2327
2328 if (argc < 1) {
2329 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2330 return -1;
2331 }
2332
2333 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2334 for (i=1; i < argc; i++)
2335 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2336 cmd[sizeof(cmd) - 1] = '\0';
2337 printf("%s: %s\n", __func__, cmd);
2338 return wpa_ctrl_command(ctrl, cmd);
2339}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002340#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002341
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002342
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002343static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2344{
2345 return wpa_ctrl_command(ctrl, "FLUSH");
2346}
2347
2348
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002349enum wpa_cli_cmd_flags {
2350 cli_cmd_flag_none = 0x00,
2351 cli_cmd_flag_sensitive = 0x01
2352};
2353
2354struct wpa_cli_cmd {
2355 const char *cmd;
2356 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002357 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002358 enum wpa_cli_cmd_flags flags;
2359 const char *usage;
2360};
2361
2362static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002363 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002364 cli_cmd_flag_none,
2365 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002366 { "ifname", wpa_cli_cmd_ifname, NULL,
2367 cli_cmd_flag_none,
2368 "= get current interface name" },
2369 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002370 cli_cmd_flag_none,
2371 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002372 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002373 cli_cmd_flag_none,
2374 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002375 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002376 cli_cmd_flag_none,
2377 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002378 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002379 cli_cmd_flag_none,
2380 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002381 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002382 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002383 "[command] = show usage help" },
2384 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002385 cli_cmd_flag_none,
2386 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002387 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002388 cli_cmd_flag_none,
2389 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002390 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002391 cli_cmd_flag_none,
2392 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002393 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002394 cli_cmd_flag_none,
2395 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002396 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002397 cli_cmd_flag_none,
2398 "= set variables (shows list of variables when run without "
2399 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002400 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002401 cli_cmd_flag_none,
2402 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002403 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002404 cli_cmd_flag_none,
2405 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002406 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002407 cli_cmd_flag_none,
2408 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002409 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002410 cli_cmd_flag_none,
2411 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002412 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002413 cli_cmd_flag_none,
2414 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002415 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002416 cli_cmd_flag_none,
2417 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002418 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002419 cli_cmd_flag_none,
2420 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002421 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002422 cli_cmd_flag_sensitive,
2423 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002424 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002425 cli_cmd_flag_sensitive,
2426 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002427 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002428 cli_cmd_flag_sensitive,
2429 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002430 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002431 cli_cmd_flag_sensitive,
2432 "<network id> <password> = configure one-time-password for an SSID"
2433 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002434 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002435 cli_cmd_flag_sensitive,
2436 "<network id> <passphrase> = configure private key passphrase\n"
2437 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002438 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002439 cli_cmd_flag_none,
2440 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002441 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002442 cli_cmd_flag_none,
2443 "<BSSID> = add a BSSID to the blacklist\n"
2444 "blacklist clear = clear the blacklist\n"
2445 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002446 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002447 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002448 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002449 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002450 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002451 cli_cmd_flag_none,
2452 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002453 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002454 cli_cmd_flag_none,
2455 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002456 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002457 cli_cmd_flag_none,
2458 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002459 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002460 cli_cmd_flag_none,
2461 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002462 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002463 cli_cmd_flag_none,
2464 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002465 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002466 cli_cmd_flag_none,
2467 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002468 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002469 cli_cmd_flag_sensitive,
2470 "<network id> <variable> <value> = set network variables (shows\n"
2471 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002472 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002473 cli_cmd_flag_none,
2474 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002475 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002476 cli_cmd_flag_none,
2477 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002478 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002479 cli_cmd_flag_none,
2480 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002481 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002482 cli_cmd_flag_none,
2483 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002484 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002485 cli_cmd_flag_sensitive,
2486 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002487 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002488 cli_cmd_flag_none,
2489 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002490 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002491 cli_cmd_flag_none,
2492 "= disconnect and wait for reassociate/reconnect command before\n"
2493 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002494 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002495 cli_cmd_flag_none,
2496 "= like reassociate, but only takes effect if already disconnected"
2497 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002498 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002499 cli_cmd_flag_none,
2500 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002501 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 cli_cmd_flag_none,
2503 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002504 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002505 cli_cmd_flag_none,
2506 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002507 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002508 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002509 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002510 "= get capabilies" },
2511 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002512 cli_cmd_flag_none,
2513 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002514 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002515 cli_cmd_flag_none,
2516 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002517 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002518 cli_cmd_flag_none,
2519 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2520 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2521 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002522 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523 cli_cmd_flag_none,
2524 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002525 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 cli_cmd_flag_none,
2527 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002528 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002529 cli_cmd_flag_none,
2530 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002531 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002532 cli_cmd_flag_none,
2533 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002534 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002535 cli_cmd_flag_none,
2536 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002537 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002538 cli_cmd_flag_none,
2539 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002540 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002541 cli_cmd_flag_none,
2542 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002543 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002544 cli_cmd_flag_none,
2545 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002546 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002547 cli_cmd_flag_none,
2548 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002549 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002550 cli_cmd_flag_none,
2551 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002552 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002553 cli_cmd_flag_sensitive,
2554 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2555 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002556 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002557 cli_cmd_flag_sensitive,
2558 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002559 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002561#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002562 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002563 cli_cmd_flag_none,
2564 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002565 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2566 cli_cmd_flag_none,
2567 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002568 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002569 cli_cmd_flag_none,
2570 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002571 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002572 cli_cmd_flag_sensitive,
2573 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002574 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2575 cli_cmd_flag_none,
2576 "<NDEF> <WPS> = create NFC handover request" },
2577 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2578 cli_cmd_flag_none,
2579 "<NDEF> <WPS> = create NFC handover select" },
2580 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2581 cli_cmd_flag_none,
2582 "<hexdump of payload> = report received NFC handover request" },
2583 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2584 cli_cmd_flag_none,
2585 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002586 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2587 cli_cmd_flag_none,
2588 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2589 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002590#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002591 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002592 cli_cmd_flag_sensitive,
2593 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002594 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002595 cli_cmd_flag_sensitive,
2596 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002597 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002598 cli_cmd_flag_none,
2599 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002600 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002601 cli_cmd_flag_none,
2602 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002603 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002604 cli_cmd_flag_sensitive,
2605 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002606 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002607 cli_cmd_flag_none,
2608 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002609 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002610 cli_cmd_flag_sensitive,
2611 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002612 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002613 cli_cmd_flag_none,
2614 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002615 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002616 cli_cmd_flag_sensitive,
2617 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002618#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002619 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002620 cli_cmd_flag_none,
2621 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2622#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002623 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 cli_cmd_flag_none,
2625 "<addr> = request RSN authentication with <addr> in IBSS" },
2626#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002627 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628 cli_cmd_flag_none,
2629 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002630 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002631 cli_cmd_flag_none,
2632 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002633 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002634 cli_cmd_flag_none,
2635 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002636 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002637 cli_cmd_flag_none,
2638 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002639#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002640 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002641 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002642 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002644 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002646 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002647 cli_cmd_flag_none,
2648 "<addr> = roam to the specified BSS" },
2649#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002650 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2651 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002653 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002654 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002655 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2656 cli_cmd_flag_none,
2657 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2658 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002659 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002660 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2661 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002662 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002663 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2664 "[ht40] = add a new P2P group (local end as GO)" },
2665 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2666 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002667 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002668 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002669 cli_cmd_flag_none,
2670 "= get the passphrase for a group (GO only)" },
2671 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002672 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002673 "<addr> <TLVs> = schedule service discovery request" },
2674 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002675 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002676 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002677 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002678 cli_cmd_flag_none,
2679 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002680 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002681 cli_cmd_flag_none,
2682 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002683 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002684 cli_cmd_flag_none,
2685 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002686 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002687 cli_cmd_flag_none,
2688 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002689 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002690 cli_cmd_flag_none,
2691 "<bonjour|upnp> <query|version> <response|service> = add a local "
2692 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002693 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002694 cli_cmd_flag_none,
2695 "<bonjour|upnp> <query|version> [|service] = remove a local "
2696 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002697 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698 cli_cmd_flag_none,
2699 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002700 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002701 cli_cmd_flag_none,
2702 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002703 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002704 "[discovered] = list known (optionally, only fully discovered) P2P "
2705 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002706 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2707 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002708 "<address> = show information about known P2P peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002709 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002710 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002711 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002712 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002713 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002714 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002715 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2716 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002717 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002718 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2719 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002720 "[<duration> <interval>] [<duration> <interval>] = request GO "
2721 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002722 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2723 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002724 "[<period> <interval>] = set extended listen timing" },
2725#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002726#ifdef CONFIG_WIFI_DISPLAY
2727 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2728 cli_cmd_flag_none,
2729 "<subelem> [contents] = set Wi-Fi Display subelement" },
2730 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2731 cli_cmd_flag_none,
2732 "<subelem> = get Wi-Fi Display subelement" },
2733#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002734#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002735 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002736 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002737 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2738 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002739 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002740 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002741 cli_cmd_flag_none,
2742 "[auto] = perform Interworking network selection" },
2743 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002744 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002745 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002746 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2747 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002748 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002749 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2750 cli_cmd_flag_none,
2751 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2752 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2753 wpa_cli_complete_bss, cli_cmd_flag_none,
2754 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002755#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002756#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002757 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2758 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002759 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2760 },
2761 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002762 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002763 "<addr> <home realm> = get HS20 nai home realm list" },
2764#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002765 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2766 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002767 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002768 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002769 cli_cmd_flag_none,
2770 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002771 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002772 cli_cmd_flag_none,
2773 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002774 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002775 cli_cmd_flag_none,
2776 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002777 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 cli_cmd_flag_none,
2779 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002780 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002781 cli_cmd_flag_none,
2782 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002783 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2784 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002785 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002786#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002787 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002788 "[params] = Set or unset (if none) autoscan parameters" },
2789#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002790#ifdef CONFIG_WNM
2791 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2792 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002793 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2794 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002795#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002796 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2797 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002798 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2799 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002800#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002801 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002802 cli_cmd_flag_none,
2803 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002804#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002805 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002806};
2807
2808
2809/*
2810 * Prints command usage, lines are padded with the specified string.
2811 */
2812static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2813{
2814 char c;
2815 size_t n;
2816
2817 printf("%s%s ", pad, cmd->cmd);
2818 for (n = 0; (c = cmd->usage[n]); n++) {
2819 printf("%c", c);
2820 if (c == '\n')
2821 printf("%s", pad);
2822 }
2823 printf("\n");
2824}
2825
2826
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002827static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002828{
2829 int n;
2830 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002831 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2832 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2833 print_cmd_help(&wpa_cli_commands[n], " ");
2834 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002835}
2836
2837
2838static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2839{
2840 const char *c, *delim;
2841 int n;
2842 size_t len;
2843
2844 delim = os_strchr(cmd, ' ');
2845 if (delim)
2846 len = delim - cmd;
2847 else
2848 len = os_strlen(cmd);
2849
2850 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2851 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2852 return (wpa_cli_commands[n].flags &
2853 cli_cmd_flag_sensitive);
2854 }
2855 return 0;
2856}
2857
2858
2859static char ** wpa_list_cmd_list(void)
2860{
2861 char **res;
2862 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002863 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002864
2865 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002866 count += dl_list_len(&p2p_groups);
2867 count += dl_list_len(&ifnames);
2868 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002869 if (res == NULL)
2870 return NULL;
2871
2872 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2873 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2874 if (res[i] == NULL)
2875 break;
2876 }
2877
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002878 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
2879 size_t len = 8 + os_strlen(e->txt);
2880 res[i] = os_malloc(len);
2881 if (res[i] == NULL)
2882 break;
2883 os_snprintf(res[i], len, "ifname=%s", e->txt);
2884 i++;
2885 }
2886
2887 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
2888 res[i] = os_strdup(e->txt);
2889 if (res[i] == NULL)
2890 break;
2891 i++;
2892 }
2893
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002894 return res;
2895}
2896
2897
2898static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2899 int pos)
2900{
2901 int i;
2902
2903 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2904 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002905 if (wpa_cli_commands[i].completion)
2906 return wpa_cli_commands[i].completion(str,
2907 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908 edit_clear_line();
2909 printf("\r%s\n", wpa_cli_commands[i].usage);
2910 edit_redraw();
2911 break;
2912 }
2913 }
2914
2915 return NULL;
2916}
2917
2918
2919static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2920{
2921 char **res;
2922 const char *end;
2923 char *cmd;
2924
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002925 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
2926 end = os_strchr(str, ' ');
2927 if (end && pos > end - str) {
2928 pos -= end - str + 1;
2929 str = end + 1;
2930 }
2931 }
2932
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002933 end = os_strchr(str, ' ');
2934 if (end == NULL || str + pos < end)
2935 return wpa_list_cmd_list();
2936
2937 cmd = os_malloc(pos + 1);
2938 if (cmd == NULL)
2939 return NULL;
2940 os_memcpy(cmd, str, pos);
2941 cmd[end - str] = '\0';
2942 res = wpa_cli_cmd_completion(cmd, str, pos);
2943 os_free(cmd);
2944 return res;
2945}
2946
2947
2948static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2949{
2950 struct wpa_cli_cmd *cmd, *match = NULL;
2951 int count;
2952 int ret = 0;
2953
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002954 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
2955 ifname_prefix = argv[0] + 7;
2956 argv = &argv[1];
2957 argc--;
2958 } else
2959 ifname_prefix = NULL;
2960
2961 if (argc == 0)
2962 return -1;
2963
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002964 count = 0;
2965 cmd = wpa_cli_commands;
2966 while (cmd->cmd) {
2967 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2968 {
2969 match = cmd;
2970 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2971 /* we have an exact match */
2972 count = 1;
2973 break;
2974 }
2975 count++;
2976 }
2977 cmd++;
2978 }
2979
2980 if (count > 1) {
2981 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2982 cmd = wpa_cli_commands;
2983 while (cmd->cmd) {
2984 if (os_strncasecmp(cmd->cmd, argv[0],
2985 os_strlen(argv[0])) == 0) {
2986 printf(" %s", cmd->cmd);
2987 }
2988 cmd++;
2989 }
2990 printf("\n");
2991 ret = 1;
2992 } else if (count == 0) {
2993 printf("Unknown command '%s'\n", argv[0]);
2994 ret = 1;
2995 } else {
2996 ret = match->handler(ctrl, argc - 1, &argv[1]);
2997 }
2998
2999 return ret;
3000}
3001
3002
3003static int str_match(const char *a, const char *b)
3004{
3005 return os_strncmp(a, b, os_strlen(b)) == 0;
3006}
3007
3008
3009static int wpa_cli_exec(const char *program, const char *arg1,
3010 const char *arg2)
3011{
3012 char *cmd;
3013 size_t len;
3014 int res;
3015 int ret = 0;
3016
3017 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3018 cmd = os_malloc(len);
3019 if (cmd == NULL)
3020 return -1;
3021 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3022 if (res < 0 || (size_t) res >= len) {
3023 os_free(cmd);
3024 return -1;
3025 }
3026 cmd[len - 1] = '\0';
3027#ifndef _WIN32_WCE
3028 if (system(cmd) < 0)
3029 ret = -1;
3030#endif /* _WIN32_WCE */
3031 os_free(cmd);
3032
3033 return ret;
3034}
3035
3036
3037static void wpa_cli_action_process(const char *msg)
3038{
3039 const char *pos;
3040 char *copy = NULL, *id, *pos2;
3041
3042 pos = msg;
3043 if (*pos == '<') {
3044 /* skip priority */
3045 pos = os_strchr(pos, '>');
3046 if (pos)
3047 pos++;
3048 else
3049 pos = msg;
3050 }
3051
3052 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3053 int new_id = -1;
3054 os_unsetenv("WPA_ID");
3055 os_unsetenv("WPA_ID_STR");
3056 os_unsetenv("WPA_CTRL_DIR");
3057
3058 pos = os_strstr(pos, "[id=");
3059 if (pos)
3060 copy = os_strdup(pos + 4);
3061
3062 if (copy) {
3063 pos2 = id = copy;
3064 while (*pos2 && *pos2 != ' ')
3065 pos2++;
3066 *pos2++ = '\0';
3067 new_id = atoi(id);
3068 os_setenv("WPA_ID", id, 1);
3069 while (*pos2 && *pos2 != '=')
3070 pos2++;
3071 if (*pos2 == '=')
3072 pos2++;
3073 id = pos2;
3074 while (*pos2 && *pos2 != ']')
3075 pos2++;
3076 *pos2 = '\0';
3077 os_setenv("WPA_ID_STR", id, 1);
3078 os_free(copy);
3079 }
3080
3081 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3082
3083 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3084 wpa_cli_connected = 1;
3085 wpa_cli_last_id = new_id;
3086 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3087 }
3088 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3089 if (wpa_cli_connected) {
3090 wpa_cli_connected = 0;
3091 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3092 }
3093 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3094 wpa_cli_exec(action_file, ctrl_ifname, pos);
3095 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3096 wpa_cli_exec(action_file, ctrl_ifname, pos);
3097 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3098 wpa_cli_exec(action_file, ctrl_ifname, pos);
3099 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3100 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003101 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3102 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003103 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3104 wpa_cli_exec(action_file, ctrl_ifname, pos);
3105 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3106 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003107 } else if (str_match(pos, AP_STA_CONNECTED)) {
3108 wpa_cli_exec(action_file, ctrl_ifname, pos);
3109 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3110 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003111 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3112 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003113 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3114 printf("wpa_supplicant is terminating - stop monitoring\n");
3115 wpa_cli_quit = 1;
3116 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003117}
3118
3119
3120#ifndef CONFIG_ANSI_C_EXTRA
3121static void wpa_cli_action_cb(char *msg, size_t len)
3122{
3123 wpa_cli_action_process(msg);
3124}
3125#endif /* CONFIG_ANSI_C_EXTRA */
3126
3127
3128static void wpa_cli_reconnect(void)
3129{
3130 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003131 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3132 return;
3133
3134 if (interactive) {
3135 edit_clear_line();
3136 printf("\rConnection to wpa_supplicant re-established\n");
3137 edit_redraw();
3138 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003139}
3140
3141
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003142static void cli_event(const char *str)
3143{
3144 const char *start, *s;
3145
3146 start = os_strchr(str, '>');
3147 if (start == NULL)
3148 return;
3149
3150 start++;
3151
3152 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3153 s = os_strchr(start, ' ');
3154 if (s == NULL)
3155 return;
3156 s = os_strchr(s + 1, ' ');
3157 if (s == NULL)
3158 return;
3159 cli_txt_list_add(&bsses, s + 1);
3160 return;
3161 }
3162
3163 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3164 s = os_strchr(start, ' ');
3165 if (s == NULL)
3166 return;
3167 s = os_strchr(s + 1, ' ');
3168 if (s == NULL)
3169 return;
3170 cli_txt_list_del_addr(&bsses, s + 1);
3171 return;
3172 }
3173
3174#ifdef CONFIG_P2P
3175 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3176 s = os_strstr(start, " p2p_dev_addr=");
3177 if (s == NULL)
3178 return;
3179 cli_txt_list_add_addr(&p2p_peers, s + 14);
3180 return;
3181 }
3182
3183 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3184 s = os_strstr(start, " p2p_dev_addr=");
3185 if (s == NULL)
3186 return;
3187 cli_txt_list_del_addr(&p2p_peers, s + 14);
3188 return;
3189 }
3190
3191 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3192 s = os_strchr(start, ' ');
3193 if (s == NULL)
3194 return;
3195 cli_txt_list_add_word(&p2p_groups, s + 1);
3196 return;
3197 }
3198
3199 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3200 s = os_strchr(start, ' ');
3201 if (s == NULL)
3202 return;
3203 cli_txt_list_del_word(&p2p_groups, s + 1);
3204 return;
3205 }
3206#endif /* CONFIG_P2P */
3207}
3208
3209
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003210static int check_terminating(const char *msg)
3211{
3212 const char *pos = msg;
3213
3214 if (*pos == '<') {
3215 /* skip priority */
3216 pos = os_strchr(pos, '>');
3217 if (pos)
3218 pos++;
3219 else
3220 pos = msg;
3221 }
3222
3223 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3224 edit_clear_line();
3225 printf("\rConnection to wpa_supplicant lost - trying to "
3226 "reconnect\n");
3227 edit_redraw();
3228 wpa_cli_attached = 0;
3229 wpa_cli_close_connection();
3230 return 1;
3231 }
3232
3233 return 0;
3234}
3235
3236
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003237static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3238{
3239 if (ctrl_conn == NULL) {
3240 wpa_cli_reconnect();
3241 return;
3242 }
3243 while (wpa_ctrl_pending(ctrl) > 0) {
3244 char buf[256];
3245 size_t len = sizeof(buf) - 1;
3246 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3247 buf[len] = '\0';
3248 if (action_monitor)
3249 wpa_cli_action_process(buf);
3250 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003251 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003252 if (wpa_cli_show_event(buf)) {
3253 edit_clear_line();
3254 printf("\r%s\n", buf);
3255 edit_redraw();
3256 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003257
3258 if (interactive && check_terminating(buf) > 0)
3259 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003260 }
3261 } else {
3262 printf("Could not read pending message.\n");
3263 break;
3264 }
3265 }
3266
3267 if (wpa_ctrl_pending(ctrl) < 0) {
3268 printf("Connection to wpa_supplicant lost - trying to "
3269 "reconnect\n");
3270 wpa_cli_reconnect();
3271 }
3272}
3273
3274#define max_args 10
3275
3276static int tokenize_cmd(char *cmd, char *argv[])
3277{
3278 char *pos;
3279 int argc = 0;
3280
3281 pos = cmd;
3282 for (;;) {
3283 while (*pos == ' ')
3284 pos++;
3285 if (*pos == '\0')
3286 break;
3287 argv[argc] = pos;
3288 argc++;
3289 if (argc == max_args)
3290 break;
3291 if (*pos == '"') {
3292 char *pos2 = os_strrchr(pos, '"');
3293 if (pos2)
3294 pos = pos2 + 1;
3295 }
3296 while (*pos != '\0' && *pos != ' ')
3297 pos++;
3298 if (*pos == ' ')
3299 *pos++ = '\0';
3300 }
3301
3302 return argc;
3303}
3304
3305
3306static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3307{
3308 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3309 printf("Connection to wpa_supplicant lost - trying to "
3310 "reconnect\n");
3311 wpa_cli_close_connection();
3312 }
3313 if (!ctrl_conn)
3314 wpa_cli_reconnect();
3315 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3316}
3317
3318
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003319static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3320{
3321 wpa_cli_recv_pending(mon_conn, 0);
3322}
3323
3324
3325static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3326{
3327 char *argv[max_args];
3328 int argc;
3329 argc = tokenize_cmd(cmd, argv);
3330 if (argc)
3331 wpa_request(ctrl_conn, argc, argv);
3332}
3333
3334
3335static void wpa_cli_edit_eof_cb(void *ctx)
3336{
3337 eloop_terminate();
3338}
3339
3340
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003341static int warning_displayed = 0;
3342static char *hfile = NULL;
3343static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003344
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003345static void start_edit(void)
3346{
3347 char *home;
3348 char *ps = NULL;
3349
3350#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3351 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3352#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003353
3354 home = getenv("HOME");
3355 if (home) {
3356 const char *fname = ".wpa_cli_history";
3357 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3358 hfile = os_malloc(hfile_len);
3359 if (hfile)
3360 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3361 }
3362
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003363 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3364 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3365 eloop_terminate();
3366 return;
3367 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003368
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003369 edit_started = 1;
3370 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3371}
3372
3373
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003374static void update_bssid_list(struct wpa_ctrl *ctrl)
3375{
3376 char buf[4096];
3377 size_t len = sizeof(buf);
3378 int ret;
3379 char *cmd = "BSS RANGE=ALL MASK=0x2";
3380 char *pos, *end;
3381
3382 if (ctrl == NULL)
3383 return;
3384 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3385 if (ret < 0)
3386 return;
3387 buf[len] = '\0';
3388
3389 pos = buf;
3390 while (pos) {
3391 pos = os_strstr(pos, "bssid=");
3392 if (pos == NULL)
3393 break;
3394 pos += 6;
3395 end = os_strchr(pos, '\n');
3396 if (end == NULL)
3397 break;
3398 *end = '\0';
3399 cli_txt_list_add(&bsses, pos);
3400 pos = end + 1;
3401 }
3402}
3403
3404
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003405static void update_ifnames(struct wpa_ctrl *ctrl)
3406{
3407 char buf[4096];
3408 size_t len = sizeof(buf);
3409 int ret;
3410 char *cmd = "INTERFACES";
3411 char *pos, *end;
3412 char txt[200];
3413
3414 cli_txt_list_flush(&ifnames);
3415
3416 if (ctrl == NULL)
3417 return;
3418 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3419 if (ret < 0)
3420 return;
3421 buf[len] = '\0';
3422
3423 pos = buf;
3424 while (pos) {
3425 end = os_strchr(pos, '\n');
3426 if (end == NULL)
3427 break;
3428 *end = '\0';
3429 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3430 if (ret > 0 && ret < (int) sizeof(txt))
3431 cli_txt_list_add(&ifnames, txt);
3432 pos = end + 1;
3433 }
3434}
3435
3436
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003437static void try_connection(void *eloop_ctx, void *timeout_ctx)
3438{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003439 if (ctrl_conn)
3440 goto done;
3441
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003442 if (ctrl_ifname == NULL)
3443 ctrl_ifname = wpa_cli_get_default_ifname();
3444
3445 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3446 if (!warning_displayed) {
3447 printf("Could not connect to wpa_supplicant: "
3448 "%s - re-trying\n", ctrl_ifname);
3449 warning_displayed = 1;
3450 }
3451 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3452 return;
3453 }
3454
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003455 update_bssid_list(ctrl_conn);
3456
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003457 if (warning_displayed)
3458 printf("Connection established.\n");
3459
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003460done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003461 start_edit();
3462}
3463
3464
3465static void wpa_cli_interactive(void)
3466{
3467 printf("\nInteractive mode\n\n");
3468
3469 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003470 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003471 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003472
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003473 cli_txt_list_flush(&p2p_peers);
3474 cli_txt_list_flush(&p2p_groups);
3475 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003476 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003477 if (edit_started)
3478 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003479 os_free(hfile);
3480 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3481 wpa_cli_close_connection();
3482}
3483
3484
3485static void wpa_cli_action(struct wpa_ctrl *ctrl)
3486{
3487#ifdef CONFIG_ANSI_C_EXTRA
3488 /* TODO: ANSI C version(?) */
3489 printf("Action processing not supported in ANSI C build.\n");
3490#else /* CONFIG_ANSI_C_EXTRA */
3491 fd_set rfds;
3492 int fd, res;
3493 struct timeval tv;
3494 char buf[256]; /* note: large enough to fit in unsolicited messages */
3495 size_t len;
3496
3497 fd = wpa_ctrl_get_fd(ctrl);
3498
3499 while (!wpa_cli_quit) {
3500 FD_ZERO(&rfds);
3501 FD_SET(fd, &rfds);
3502 tv.tv_sec = ping_interval;
3503 tv.tv_usec = 0;
3504 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3505 if (res < 0 && errno != EINTR) {
3506 perror("select");
3507 break;
3508 }
3509
3510 if (FD_ISSET(fd, &rfds))
3511 wpa_cli_recv_pending(ctrl, 1);
3512 else {
3513 /* verify that connection is still working */
3514 len = sizeof(buf) - 1;
3515 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3516 wpa_cli_action_cb) < 0 ||
3517 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3518 printf("wpa_supplicant did not reply to PING "
3519 "command - exiting\n");
3520 break;
3521 }
3522 }
3523 }
3524#endif /* CONFIG_ANSI_C_EXTRA */
3525}
3526
3527
3528static void wpa_cli_cleanup(void)
3529{
3530 wpa_cli_close_connection();
3531 if (pid_file)
3532 os_daemonize_terminate(pid_file);
3533
3534 os_program_deinit();
3535}
3536
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003537
3538static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003539{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003540 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003541}
3542
3543
3544static char * wpa_cli_get_default_ifname(void)
3545{
3546 char *ifname = NULL;
3547
3548#ifdef CONFIG_CTRL_IFACE_UNIX
3549 struct dirent *dent;
3550 DIR *dir = opendir(ctrl_iface_dir);
3551 if (!dir) {
3552#ifdef ANDROID
3553 char ifprop[PROPERTY_VALUE_MAX];
3554 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3555 ifname = os_strdup(ifprop);
3556 printf("Using interface '%s'\n", ifname);
3557 return ifname;
3558 }
3559#endif /* ANDROID */
3560 return NULL;
3561 }
3562 while ((dent = readdir(dir))) {
3563#ifdef _DIRENT_HAVE_D_TYPE
3564 /*
3565 * Skip the file if it is not a socket. Also accept
3566 * DT_UNKNOWN (0) in case the C library or underlying
3567 * file system does not support d_type.
3568 */
3569 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3570 continue;
3571#endif /* _DIRENT_HAVE_D_TYPE */
3572 if (os_strcmp(dent->d_name, ".") == 0 ||
3573 os_strcmp(dent->d_name, "..") == 0)
3574 continue;
3575 printf("Selected interface '%s'\n", dent->d_name);
3576 ifname = os_strdup(dent->d_name);
3577 break;
3578 }
3579 closedir(dir);
3580#endif /* CONFIG_CTRL_IFACE_UNIX */
3581
3582#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003583 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003584 size_t len;
3585 struct wpa_ctrl *ctrl;
3586 int ret;
3587
3588 ctrl = wpa_ctrl_open(NULL);
3589 if (ctrl == NULL)
3590 return NULL;
3591
3592 len = sizeof(buf) - 1;
3593 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3594 if (ret >= 0) {
3595 buf[len] = '\0';
3596 pos = os_strchr(buf, '\n');
3597 if (pos)
3598 *pos = '\0';
3599 ifname = os_strdup(buf);
3600 }
3601 wpa_ctrl_close(ctrl);
3602#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3603
3604 return ifname;
3605}
3606
3607
3608int main(int argc, char *argv[])
3609{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003610 int c;
3611 int daemonize = 0;
3612 int ret = 0;
3613 const char *global = NULL;
3614
3615 if (os_program_init())
3616 return -1;
3617
3618 for (;;) {
3619 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3620 if (c < 0)
3621 break;
3622 switch (c) {
3623 case 'a':
3624 action_file = optarg;
3625 break;
3626 case 'B':
3627 daemonize = 1;
3628 break;
3629 case 'g':
3630 global = optarg;
3631 break;
3632 case 'G':
3633 ping_interval = atoi(optarg);
3634 break;
3635 case 'h':
3636 usage();
3637 return 0;
3638 case 'v':
3639 printf("%s\n", wpa_cli_version);
3640 return 0;
3641 case 'i':
3642 os_free(ctrl_ifname);
3643 ctrl_ifname = os_strdup(optarg);
3644 break;
3645 case 'p':
3646 ctrl_iface_dir = optarg;
3647 break;
3648 case 'P':
3649 pid_file = optarg;
3650 break;
3651 default:
3652 usage();
3653 return -1;
3654 }
3655 }
3656
3657 interactive = (argc == optind) && (action_file == NULL);
3658
3659 if (interactive)
3660 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3661
3662 if (eloop_init())
3663 return -1;
3664
3665 if (global) {
3666#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3667 ctrl_conn = wpa_ctrl_open(NULL);
3668#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3669 ctrl_conn = wpa_ctrl_open(global);
3670#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3671 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003672 fprintf(stderr, "Failed to connect to wpa_supplicant "
3673 "global interface: %s error: %s\n",
3674 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003675 return -1;
3676 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003677
3678 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003679 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003680 mon_conn = wpa_ctrl_open(global);
3681 if (mon_conn) {
3682 if (wpa_ctrl_attach(mon_conn) == 0) {
3683 wpa_cli_attached = 1;
3684 eloop_register_read_sock(
3685 wpa_ctrl_get_fd(mon_conn),
3686 wpa_cli_mon_receive,
3687 NULL, NULL);
3688 } else {
3689 printf("Failed to open monitor "
3690 "connection through global "
3691 "control interface\n");
3692 }
3693 }
3694 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003695 }
3696
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003697 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003698
3699 if (ctrl_ifname == NULL)
3700 ctrl_ifname = wpa_cli_get_default_ifname();
3701
3702 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003703 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003704 } else {
3705 if (!global &&
3706 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003707 fprintf(stderr, "Failed to connect to non-global "
3708 "ctrl_ifname: %s error: %s\n",
3709 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003710 return -1;
3711 }
3712
3713 if (action_file) {
3714 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3715 wpa_cli_attached = 1;
3716 } else {
3717 printf("Warning: Failed to attach to "
3718 "wpa_supplicant.\n");
3719 return -1;
3720 }
3721 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003722
3723 if (daemonize && os_daemonize(pid_file))
3724 return -1;
3725
3726 if (action_file)
3727 wpa_cli_action(ctrl_conn);
3728 else
3729 ret = wpa_request(ctrl_conn, argc - optind,
3730 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003731 }
3732
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003733 os_free(ctrl_ifname);
3734 eloop_destroy();
3735 wpa_cli_cleanup();
3736
3737 return ret;
3738}
3739
3740#else /* CONFIG_CTRL_IFACE */
3741int main(int argc, char *argv[])
3742{
3743 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3744 return -1;
3745}
3746#endif /* CONFIG_CTRL_IFACE */