blob: 968534ee7ab84468a80495896549484d8f46edb3 [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 }
409 len = sizeof(buf) - 1;
410 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
411 wpa_cli_msg_cb);
412 if (ret == -2) {
413 printf("'%s' command timed out.\n", cmd);
414 return -2;
415 } else if (ret < 0) {
416 printf("'%s' command failed.\n", cmd);
417 return -1;
418 }
419 if (print) {
420 buf[len] = '\0';
421 printf("%s", buf);
422 if (interactive && len > 0 && buf[len - 1] != '\n')
423 printf("\n");
424 }
425 return 0;
426}
427
428
429static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
430{
431 return _wpa_ctrl_command(ctrl, cmd, 1);
432}
433
434
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700435static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
436 char *argv[])
437{
438 int i, res;
439 char *pos, *end;
440
441 pos = buf;
442 end = buf + buflen;
443
444 res = os_snprintf(pos, end - pos, "%s", cmd);
445 if (res < 0 || res >= end - pos)
446 goto fail;
447 pos += res;
448
449 for (i = 0; i < argc; i++) {
450 res = os_snprintf(pos, end - pos, " %s", argv[i]);
451 if (res < 0 || res >= end - pos)
452 goto fail;
453 pos += res;
454 }
455
456 buf[buflen - 1] = '\0';
457 return 0;
458
459fail:
460 printf("Too long command\n");
461 return -1;
462}
463
464
465static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
466 int argc, char *argv[])
467{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700468 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700469 if (argc < min_args) {
470 printf("Invalid %s command - at least %d argument%s "
471 "required.\n", cmd, min_args,
472 min_args > 1 ? "s are" : " is");
473 return -1;
474 }
475 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
476 return -1;
477 return wpa_ctrl_command(ctrl, buf);
478}
479
480
481static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
482{
483 return wpa_ctrl_command(ctrl, "IFNAME");
484}
485
486
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700487static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
488{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800489 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
490 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
491 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
492 return wpa_ctrl_command(ctrl, "STATUS-WPS");
493 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700494}
495
496
497static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
498{
499 return wpa_ctrl_command(ctrl, "PING");
500}
501
502
503static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
504{
505 return wpa_ctrl_command(ctrl, "RELOG");
506}
507
508
509static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
510{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700511 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700512}
513
514
515static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
516{
517 return wpa_ctrl_command(ctrl, "MIB");
518}
519
520
521static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
522{
523 return wpa_ctrl_command(ctrl, "PMKSA");
524}
525
526
527static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
528{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700529 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700530 return 0;
531}
532
533
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700534static char ** wpa_cli_complete_help(const char *str, int pos)
535{
536 int arg = get_cmd_arg_num(str, pos);
537 char **res = NULL;
538
539 switch (arg) {
540 case 1:
541 res = wpa_list_cmd_list();
542 break;
543 }
544
545 return res;
546}
547
548
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700549static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
550{
551 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
552 return 0;
553}
554
555
556static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
557{
558 wpa_cli_quit = 1;
559 if (interactive)
560 eloop_terminate();
561 return 0;
562}
563
564
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700565static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
566{
567 char cmd[256];
568 int res;
569
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700570 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800571 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700572 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
573 printf("Too long SET command.\n");
574 return -1;
575 }
576 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700577 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700578
579 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
580}
581
582
583static char ** wpa_cli_complete_set(const char *str, int pos)
584{
585 int arg = get_cmd_arg_num(str, pos);
586 const char *fields[] = {
587 /* runtime values */
588 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
589 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
590 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
591 "wps_fragment_size", "wps_version_number", "ampdu",
592 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
593 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
594 "no_keep_alive",
595 /* global configuration parameters */
596 "eapol_version", "ap_scan", "disable_scan_offload",
597 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
598 "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
599 "driver_param", "dot11RSNAConfigPMKLifetime",
600 "dot11RSNAConfigPMKReauthThreshold",
601 "dot11RSNAConfigSATimeout",
602 "update_config", "load_dynamic_eap", "uuid", "device_name",
603 "manufacturer", "model_name", "model_number", "serial_number",
604 "device_type", "os_version", "config_methods",
605 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
606 "p2p_listen_reg_class", "p2p_listen_channel",
607 "p2p_oper_reg_class", "p2p_oper_channel",
608 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
609 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
610 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
611 "p2p_ignore_shared_freq", "country", "bss_max_count",
612 "bss_expiration_age", "bss_expiration_scan_count",
613 "filter_ssids", "filter_rssi", "max_num_sta",
614 "disassoc_low_ack", "hs20", "interworking", "hessid",
615 "access_network_type", "pbc_in_m1", "autoscan",
616 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
617 "wps_nfc_dev_pw", "ext_password_backend",
618 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
619 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
620 "ignore_old_scan_res", "freq_list"
621 };
622 int i, num_fields = sizeof(fields) / sizeof(fields[0]);
623
624 if (arg == 1) {
625 char **res = os_calloc(num_fields + 1, sizeof(char *));
626 if (res == NULL)
627 return NULL;
628 for (i = 0; i < num_fields; i++) {
629 res[i] = os_strdup(fields[i]);
630 if (res[i] == NULL)
631 return res;
632 }
633 return res;
634 }
635
636 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
637 return cli_txt_list_array(&bsses);
638
639 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700640}
641
642
643static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
644{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700645 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700646}
647
648
649static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
650{
651 return wpa_ctrl_command(ctrl, "LOGOFF");
652}
653
654
655static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
656{
657 return wpa_ctrl_command(ctrl, "LOGON");
658}
659
660
661static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
662 char *argv[])
663{
664 return wpa_ctrl_command(ctrl, "REASSOCIATE");
665}
666
667
668static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
669 char *argv[])
670{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700671 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700672}
673
674
675static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
676{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700677 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700678}
679
680
681static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
682 char *argv[])
683{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700684 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700685}
686
687
688static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
689 char *argv[])
690{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700691 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692}
693
694
695static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
696 char *argv[])
697{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700698 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700699}
700
701
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700702static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
703{
704 char cmd[256];
705 int res;
706
707 if (argc < 1)
708 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
709 else
710 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
711 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
712 printf("Too long BSS_FLUSH command.\n");
713 return -1;
714 }
715 return wpa_ctrl_command(ctrl, cmd);
716}
717
718
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700719static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
720 char *argv[])
721{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700722 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700723}
724
725
726static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
727{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700728 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700729}
730
731
732static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
733{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700734 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700735}
736
737
738static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
739{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700740 if (argc == 0) {
741 printf("Invalid WPS_PIN command: need one or two arguments:\n"
742 "- BSSID: use 'any' to select any\n"
743 "- PIN: optional, used only with devices that have no "
744 "display\n");
745 return -1;
746 }
747
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700748 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700749}
750
751
752static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
753 char *argv[])
754{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700755 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700756}
757
758
759static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
760 char *argv[])
761{
762 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
763}
764
765
Dmitry Shmidt04949592012-07-19 12:16:46 -0700766#ifdef CONFIG_WPS_NFC
767
768static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
769{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700770 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700771}
772
773
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800774static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
775 char *argv[])
776{
777 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
778}
779
780
Dmitry Shmidt04949592012-07-19 12:16:46 -0700781static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
782 char *argv[])
783{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700784 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700785}
786
787
788static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
789 char *argv[])
790{
791 int ret;
792 char *buf;
793 size_t buflen;
794
795 if (argc != 1) {
796 printf("Invalid 'wps_nfc_tag_read' command - one argument "
797 "is required.\n");
798 return -1;
799 }
800
801 buflen = 18 + os_strlen(argv[0]);
802 buf = os_malloc(buflen);
803 if (buf == NULL)
804 return -1;
805 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
806
807 ret = wpa_ctrl_command(ctrl, buf);
808 os_free(buf);
809
810 return ret;
811}
812
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800813
814static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
815 char *argv[])
816{
817 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
818}
819
820
821static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
822 char *argv[])
823{
824 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
825}
826
827
828static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
829 char *argv[])
830{
831 int ret;
832 char *buf;
833 size_t buflen;
834
835 if (argc != 1) {
836 printf("Invalid 'nfc_rx_handover_req' command - one argument "
837 "is required.\n");
838 return -1;
839 }
840
841 buflen = 21 + os_strlen(argv[0]);
842 buf = os_malloc(buflen);
843 if (buf == NULL)
844 return -1;
845 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
846
847 ret = wpa_ctrl_command(ctrl, buf);
848 os_free(buf);
849
850 return ret;
851}
852
853
854static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
855 char *argv[])
856{
857 int ret;
858 char *buf;
859 size_t buflen;
860
861 if (argc != 1) {
862 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
863 "is required.\n");
864 return -1;
865 }
866
867 buflen = 21 + os_strlen(argv[0]);
868 buf = os_malloc(buflen);
869 if (buf == NULL)
870 return -1;
871 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
872
873 ret = wpa_ctrl_command(ctrl, buf);
874 os_free(buf);
875
876 return ret;
877}
878
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800879
880static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
881 char *argv[])
882{
883 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
884}
885
Dmitry Shmidt04949592012-07-19 12:16:46 -0700886#endif /* CONFIG_WPS_NFC */
887
888
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700889static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
890{
891 char cmd[256];
892 int res;
893
894 if (argc == 2)
895 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
896 argv[0], argv[1]);
897 else if (argc == 5 || argc == 6) {
898 char ssid_hex[2 * 32 + 1];
899 char key_hex[2 * 64 + 1];
900 int i;
901
902 ssid_hex[0] = '\0';
903 for (i = 0; i < 32; i++) {
904 if (argv[2][i] == '\0')
905 break;
906 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
907 }
908
909 key_hex[0] = '\0';
910 if (argc == 6) {
911 for (i = 0; i < 64; i++) {
912 if (argv[5][i] == '\0')
913 break;
914 os_snprintf(&key_hex[i * 2], 3, "%02x",
915 argv[5][i]);
916 }
917 }
918
919 res = os_snprintf(cmd, sizeof(cmd),
920 "WPS_REG %s %s %s %s %s %s",
921 argv[0], argv[1], ssid_hex, argv[3], argv[4],
922 key_hex);
923 } else {
924 printf("Invalid WPS_REG command: need two arguments:\n"
925 "- BSSID of the target AP\n"
926 "- AP PIN\n");
927 printf("Alternatively, six arguments can be used to "
928 "reconfigure the AP:\n"
929 "- BSSID of the target AP\n"
930 "- AP PIN\n"
931 "- new SSID\n"
932 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
933 "- new encr (NONE, WEP, TKIP, CCMP)\n"
934 "- new key\n");
935 return -1;
936 }
937
938 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
939 printf("Too long WPS_REG command.\n");
940 return -1;
941 }
942 return wpa_ctrl_command(ctrl, cmd);
943}
944
945
946static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
947 char *argv[])
948{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700949 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700950}
951
952
953static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
954 char *argv[])
955{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700956 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700957}
958
959
960static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
961 char *argv[])
962{
963 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
964
965}
966
967
968static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
969 char *argv[])
970{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700971 if (argc < 2) {
972 printf("Invalid WPS_ER_PIN command: need at least two "
973 "arguments:\n"
974 "- UUID: use 'any' to select any\n"
975 "- PIN: Enrollee PIN\n"
976 "optional: - Enrollee MAC address\n");
977 return -1;
978 }
979
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700980 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700981}
982
983
984static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
985 char *argv[])
986{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700987 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700988}
989
990
991static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
992 char *argv[])
993{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700994 if (argc != 2) {
995 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
996 "- UUID: specify which AP to use\n"
997 "- PIN: AP PIN\n");
998 return -1;
999 }
1000
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001001 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002}
1003
1004
1005static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1006 char *argv[])
1007{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008 if (argc != 2) {
1009 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1010 "arguments:\n"
1011 "- UUID: specify which AP to use\n"
1012 "- Network configuration id\n");
1013 return -1;
1014 }
1015
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001016 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001017}
1018
1019
1020static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1021 char *argv[])
1022{
1023 char cmd[256];
1024 int res;
1025
1026 if (argc == 5 || argc == 6) {
1027 char ssid_hex[2 * 32 + 1];
1028 char key_hex[2 * 64 + 1];
1029 int i;
1030
1031 ssid_hex[0] = '\0';
1032 for (i = 0; i < 32; i++) {
1033 if (argv[2][i] == '\0')
1034 break;
1035 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1036 }
1037
1038 key_hex[0] = '\0';
1039 if (argc == 6) {
1040 for (i = 0; i < 64; i++) {
1041 if (argv[5][i] == '\0')
1042 break;
1043 os_snprintf(&key_hex[i * 2], 3, "%02x",
1044 argv[5][i]);
1045 }
1046 }
1047
1048 res = os_snprintf(cmd, sizeof(cmd),
1049 "WPS_ER_CONFIG %s %s %s %s %s %s",
1050 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1051 key_hex);
1052 } else {
1053 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1054 "- AP UUID\n"
1055 "- AP PIN\n"
1056 "- new SSID\n"
1057 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1058 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1059 "- new key\n");
1060 return -1;
1061 }
1062
1063 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1064 printf("Too long WPS_ER_CONFIG command.\n");
1065 return -1;
1066 }
1067 return wpa_ctrl_command(ctrl, cmd);
1068}
1069
1070
Dmitry Shmidt04949592012-07-19 12:16:46 -07001071#ifdef CONFIG_WPS_NFC
1072static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1073 char *argv[])
1074{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001075 if (argc != 2) {
1076 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1077 "arguments:\n"
1078 "- WPS/NDEF: token format\n"
1079 "- UUID: specify which AP to use\n");
1080 return -1;
1081 }
1082
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001083 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001084}
1085#endif /* CONFIG_WPS_NFC */
1086
1087
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001088static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1089{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001090 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001091}
1092
1093
1094static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1095{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001096 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001097}
1098
1099
1100static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1101{
1102 char cmd[256], *pos, *end;
1103 int i, ret;
1104
1105 if (argc < 2) {
1106 printf("Invalid IDENTITY command: needs two arguments "
1107 "(network id and identity)\n");
1108 return -1;
1109 }
1110
1111 end = cmd + sizeof(cmd);
1112 pos = cmd;
1113 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1114 argv[0], argv[1]);
1115 if (ret < 0 || ret >= end - pos) {
1116 printf("Too long IDENTITY command.\n");
1117 return -1;
1118 }
1119 pos += ret;
1120 for (i = 2; i < argc; i++) {
1121 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1122 if (ret < 0 || ret >= end - pos) {
1123 printf("Too long IDENTITY command.\n");
1124 return -1;
1125 }
1126 pos += ret;
1127 }
1128
1129 return wpa_ctrl_command(ctrl, cmd);
1130}
1131
1132
1133static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1134{
1135 char cmd[256], *pos, *end;
1136 int i, ret;
1137
1138 if (argc < 2) {
1139 printf("Invalid PASSWORD command: needs two arguments "
1140 "(network id and password)\n");
1141 return -1;
1142 }
1143
1144 end = cmd + sizeof(cmd);
1145 pos = cmd;
1146 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1147 argv[0], argv[1]);
1148 if (ret < 0 || ret >= end - pos) {
1149 printf("Too long PASSWORD command.\n");
1150 return -1;
1151 }
1152 pos += ret;
1153 for (i = 2; i < argc; i++) {
1154 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1155 if (ret < 0 || ret >= end - pos) {
1156 printf("Too long PASSWORD command.\n");
1157 return -1;
1158 }
1159 pos += ret;
1160 }
1161
1162 return wpa_ctrl_command(ctrl, cmd);
1163}
1164
1165
1166static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1167 char *argv[])
1168{
1169 char cmd[256], *pos, *end;
1170 int i, ret;
1171
1172 if (argc < 2) {
1173 printf("Invalid NEW_PASSWORD command: needs two arguments "
1174 "(network id and password)\n");
1175 return -1;
1176 }
1177
1178 end = cmd + sizeof(cmd);
1179 pos = cmd;
1180 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1181 argv[0], argv[1]);
1182 if (ret < 0 || ret >= end - pos) {
1183 printf("Too long NEW_PASSWORD command.\n");
1184 return -1;
1185 }
1186 pos += ret;
1187 for (i = 2; i < argc; i++) {
1188 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1189 if (ret < 0 || ret >= end - pos) {
1190 printf("Too long NEW_PASSWORD command.\n");
1191 return -1;
1192 }
1193 pos += ret;
1194 }
1195
1196 return wpa_ctrl_command(ctrl, cmd);
1197}
1198
1199
1200static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1201{
1202 char cmd[256], *pos, *end;
1203 int i, ret;
1204
1205 if (argc < 2) {
1206 printf("Invalid PIN command: needs two arguments "
1207 "(network id and pin)\n");
1208 return -1;
1209 }
1210
1211 end = cmd + sizeof(cmd);
1212 pos = cmd;
1213 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1214 argv[0], argv[1]);
1215 if (ret < 0 || ret >= end - pos) {
1216 printf("Too long PIN command.\n");
1217 return -1;
1218 }
1219 pos += ret;
1220 for (i = 2; i < argc; i++) {
1221 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1222 if (ret < 0 || ret >= end - pos) {
1223 printf("Too long PIN command.\n");
1224 return -1;
1225 }
1226 pos += ret;
1227 }
1228 return wpa_ctrl_command(ctrl, cmd);
1229}
1230
1231
1232static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1233{
1234 char cmd[256], *pos, *end;
1235 int i, ret;
1236
1237 if (argc < 2) {
1238 printf("Invalid OTP command: needs two arguments (network "
1239 "id and password)\n");
1240 return -1;
1241 }
1242
1243 end = cmd + sizeof(cmd);
1244 pos = cmd;
1245 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1246 argv[0], argv[1]);
1247 if (ret < 0 || ret >= end - pos) {
1248 printf("Too long OTP command.\n");
1249 return -1;
1250 }
1251 pos += ret;
1252 for (i = 2; i < argc; i++) {
1253 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1254 if (ret < 0 || ret >= end - pos) {
1255 printf("Too long OTP command.\n");
1256 return -1;
1257 }
1258 pos += ret;
1259 }
1260
1261 return wpa_ctrl_command(ctrl, cmd);
1262}
1263
1264
1265static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1266 char *argv[])
1267{
1268 char cmd[256], *pos, *end;
1269 int i, ret;
1270
1271 if (argc < 2) {
1272 printf("Invalid PASSPHRASE command: needs two arguments "
1273 "(network id and passphrase)\n");
1274 return -1;
1275 }
1276
1277 end = cmd + sizeof(cmd);
1278 pos = cmd;
1279 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1280 argv[0], argv[1]);
1281 if (ret < 0 || ret >= end - pos) {
1282 printf("Too long PASSPHRASE command.\n");
1283 return -1;
1284 }
1285 pos += ret;
1286 for (i = 2; i < argc; i++) {
1287 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1288 if (ret < 0 || ret >= end - pos) {
1289 printf("Too long PASSPHRASE command.\n");
1290 return -1;
1291 }
1292 pos += ret;
1293 }
1294
1295 return wpa_ctrl_command(ctrl, cmd);
1296}
1297
1298
1299static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1300{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001301 if (argc < 2) {
1302 printf("Invalid BSSID command: needs two arguments (network "
1303 "id and BSSID)\n");
1304 return -1;
1305 }
1306
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001307 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001308}
1309
1310
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001311static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1312{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001313 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001314}
1315
1316
1317static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1318{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001319 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001320}
1321
1322
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001323static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1324 char *argv[])
1325{
1326 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1327}
1328
1329
1330static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1331 char *argv[])
1332{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001333 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001334}
1335
1336
1337static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1338 char *argv[])
1339{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001340 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001341}
1342
1343
1344static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1345 char *argv[])
1346{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001347 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001348}
1349
1350
1351static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1352 char *argv[])
1353{
1354 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1355}
1356
1357
1358static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1359 char *argv[])
1360{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001361 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001362}
1363
1364
1365static void wpa_cli_show_network_variables(void)
1366{
1367 printf("set_network variables:\n"
1368 " ssid (network name, SSID)\n"
1369 " psk (WPA passphrase or pre-shared key)\n"
1370 " key_mgmt (key management protocol)\n"
1371 " identity (EAP identity)\n"
1372 " password (EAP password)\n"
1373 " ...\n"
1374 "\n"
1375 "Note: Values are entered in the same format as the "
1376 "configuration file is using,\n"
1377 "i.e., strings values need to be inside double quotation "
1378 "marks.\n"
1379 "For example: set_network 1 ssid \"network name\"\n"
1380 "\n"
1381 "Please see wpa_supplicant.conf documentation for full list "
1382 "of\navailable variables.\n");
1383}
1384
1385
1386static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1387 char *argv[])
1388{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001389 if (argc == 0) {
1390 wpa_cli_show_network_variables();
1391 return 0;
1392 }
1393
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001394 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001395 printf("Invalid SET_NETWORK command: needs three arguments\n"
1396 "(network id, variable name, and value)\n");
1397 return -1;
1398 }
1399
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001400 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001401}
1402
1403
1404static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1405 char *argv[])
1406{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001407 if (argc == 0) {
1408 wpa_cli_show_network_variables();
1409 return 0;
1410 }
1411
1412 if (argc != 2) {
1413 printf("Invalid GET_NETWORK command: needs two arguments\n"
1414 "(network id and variable name)\n");
1415 return -1;
1416 }
1417
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001418 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001419}
1420
1421
Dmitry Shmidt04949592012-07-19 12:16:46 -07001422static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1423 char *argv[])
1424{
1425 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1426}
1427
1428
1429static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1430{
1431 return wpa_ctrl_command(ctrl, "ADD_CRED");
1432}
1433
1434
1435static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1436 char *argv[])
1437{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001438 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001439}
1440
1441
1442static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1443{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001444 if (argc != 3) {
1445 printf("Invalid SET_CRED command: needs three arguments\n"
1446 "(cred id, variable name, and value)\n");
1447 return -1;
1448 }
1449
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001450 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001451}
1452
1453
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001454static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1455 char *argv[])
1456{
1457 return wpa_ctrl_command(ctrl, "DISCONNECT");
1458}
1459
1460
1461static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1462 char *argv[])
1463{
1464 return wpa_ctrl_command(ctrl, "RECONNECT");
1465}
1466
1467
1468static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1469 char *argv[])
1470{
1471 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1472}
1473
1474
1475static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1476{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001477 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001478}
1479
1480
1481static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1482 char *argv[])
1483{
1484 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1485}
1486
1487
1488static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1489{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001490 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001491}
1492
1493
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001494static char ** wpa_cli_complete_bss(const char *str, int pos)
1495{
1496 int arg = get_cmd_arg_num(str, pos);
1497 char **res = NULL;
1498
1499 switch (arg) {
1500 case 1:
1501 res = cli_txt_list_array(&bsses);
1502 break;
1503 }
1504
1505 return res;
1506}
1507
1508
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001509static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1510 char *argv[])
1511{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001512 if (argc < 1 || argc > 2) {
1513 printf("Invalid GET_CAPABILITY command: need either one or "
1514 "two arguments\n");
1515 return -1;
1516 }
1517
1518 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1519 printf("Invalid GET_CAPABILITY command: second argument, "
1520 "if any, must be 'strict'\n");
1521 return -1;
1522 }
1523
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001524 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001525}
1526
1527
1528static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1529{
1530 printf("Available interfaces:\n");
1531 return wpa_ctrl_command(ctrl, "INTERFACES");
1532}
1533
1534
1535static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1536{
1537 if (argc < 1) {
1538 wpa_cli_list_interfaces(ctrl);
1539 return 0;
1540 }
1541
1542 wpa_cli_close_connection();
1543 os_free(ctrl_ifname);
1544 ctrl_ifname = os_strdup(argv[0]);
1545
1546 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1547 printf("Connected to interface '%s.\n", ctrl_ifname);
1548 } else {
1549 printf("Could not connect to interface '%s' - re-trying\n",
1550 ctrl_ifname);
1551 }
1552 return 0;
1553}
1554
1555
1556static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1557 char *argv[])
1558{
1559 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1560}
1561
1562
1563static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1564 char *argv[])
1565{
1566 return wpa_ctrl_command(ctrl, "TERMINATE");
1567}
1568
1569
1570static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1571 char *argv[])
1572{
1573 char cmd[256];
1574 int res;
1575
1576 if (argc < 1) {
1577 printf("Invalid INTERFACE_ADD command: needs at least one "
1578 "argument (interface name)\n"
1579 "All arguments: ifname confname driver ctrl_interface "
1580 "driver_param bridge_name\n");
1581 return -1;
1582 }
1583
1584 /*
1585 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1586 * <driver_param>TAB<bridge_name>
1587 */
1588 res = os_snprintf(cmd, sizeof(cmd),
1589 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1590 argv[0],
1591 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1592 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1593 argc > 5 ? argv[5] : "");
1594 if (res < 0 || (size_t) res >= sizeof(cmd))
1595 return -1;
1596 cmd[sizeof(cmd) - 1] = '\0';
1597 return wpa_ctrl_command(ctrl, cmd);
1598}
1599
1600
1601static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1602 char *argv[])
1603{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001604 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001605}
1606
1607
1608static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1609 char *argv[])
1610{
1611 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1612}
1613
1614
1615#ifdef CONFIG_AP
1616static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1617{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001618 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001619}
1620
1621
1622static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1623 char *addr, size_t addr_len)
1624{
1625 char buf[4096], *pos;
1626 size_t len;
1627 int ret;
1628
1629 if (ctrl_conn == NULL) {
1630 printf("Not connected to hostapd - command dropped.\n");
1631 return -1;
1632 }
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07001633 if (ifname_prefix) {
1634 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
1635 ifname_prefix, cmd);
1636 buf[sizeof(buf) - 1] = '\0';
1637 cmd = buf;
1638 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001639 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 */