blob: b66dcd0572f63cfe9db1ad5afeba0a818175cabf [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
Dmitry Shmidt04949592012-07-19 12:16:46 -07003 * Copyright (c) 2004-2012, 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 Shmidt2fb777c2012-05-02 12:29:53 -070084#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
85static char* redirect_interface = NULL;
86#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070087
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080088struct cli_txt_entry {
89 struct dl_list list;
90 char *txt;
91};
92
93static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
94static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
95static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
96
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070097
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070098static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070099static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700100static void wpa_cli_close_connection(void);
101static char * wpa_cli_get_default_ifname(void);
102static char ** wpa_list_cmd_list(void);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700103
104
105static void usage(void)
106{
107 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
108 "[-a<action file>] \\\n"
109 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
110 "[command..]\n"
111 " -h = help (show this usage text)\n"
112 " -v = shown version information\n"
113 " -a = run in daemon mode executing the action file based on "
114 "events from\n"
115 " wpa_supplicant\n"
116 " -B = run a daemon in the background\n"
117 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
118 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700119 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700120}
121
122
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800123static void cli_txt_list_free(struct cli_txt_entry *e)
124{
125 dl_list_del(&e->list);
126 os_free(e->txt);
127 os_free(e);
128}
129
130
131static void cli_txt_list_flush(struct dl_list *list)
132{
133 struct cli_txt_entry *e;
134 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
135 cli_txt_list_free(e);
136}
137
138
139static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
140 const char *txt)
141{
142 struct cli_txt_entry *e;
143 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
144 if (os_strcmp(e->txt, txt) == 0)
145 return e;
146 }
147 return NULL;
148}
149
150
151static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
152{
153 struct cli_txt_entry *e;
154 e = cli_txt_list_get(txt_list, txt);
155 if (e)
156 cli_txt_list_free(e);
157}
158
159
160static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
161{
162 u8 addr[ETH_ALEN];
163 char buf[18];
164 if (hwaddr_aton(txt, addr) < 0)
165 return;
166 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
167 cli_txt_list_del(txt_list, buf);
168}
169
170
171#ifdef CONFIG_P2P
172static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
173{
174 const char *end;
175 char *buf;
176 end = os_strchr(txt, ' ');
177 if (end == NULL)
178 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700179 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800180 if (buf == NULL)
181 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800182 cli_txt_list_del(txt_list, buf);
183 os_free(buf);
184}
185#endif /* CONFIG_P2P */
186
187
188static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
189{
190 struct cli_txt_entry *e;
191 e = cli_txt_list_get(txt_list, txt);
192 if (e)
193 return 0;
194 e = os_zalloc(sizeof(*e));
195 if (e == NULL)
196 return -1;
197 e->txt = os_strdup(txt);
198 if (e->txt == NULL) {
199 os_free(e);
200 return -1;
201 }
202 dl_list_add(txt_list, &e->list);
203 return 0;
204}
205
206
207#ifdef CONFIG_P2P
208static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
209{
210 u8 addr[ETH_ALEN];
211 char buf[18];
212 if (hwaddr_aton(txt, addr) < 0)
213 return -1;
214 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
215 return cli_txt_list_add(txt_list, buf);
216}
217
218
219static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
220{
221 const char *end;
222 char *buf;
223 int ret;
224 end = os_strchr(txt, ' ');
225 if (end == NULL)
226 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700227 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800228 if (buf == NULL)
229 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800230 ret = cli_txt_list_add(txt_list, buf);
231 os_free(buf);
232 return ret;
233}
234#endif /* CONFIG_P2P */
235
236
237static char ** cli_txt_list_array(struct dl_list *txt_list)
238{
239 unsigned int i, count = dl_list_len(txt_list);
240 char **res;
241 struct cli_txt_entry *e;
242
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700243 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800244 if (res == NULL)
245 return NULL;
246
247 i = 0;
248 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
249 res[i] = os_strdup(e->txt);
250 if (res[i] == NULL)
251 break;
252 i++;
253 }
254
255 return res;
256}
257
258
259static int get_cmd_arg_num(const char *str, int pos)
260{
261 int arg = 0, i;
262
263 for (i = 0; i <= pos; i++) {
264 if (str[i] != ' ') {
265 arg++;
266 while (i <= pos && str[i] != ' ')
267 i++;
268 }
269 }
270
271 if (arg > 0)
272 arg--;
273 return arg;
274}
275
276
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700277static int str_starts(const char *src, const char *match)
278{
279 return os_strncmp(src, match, os_strlen(match)) == 0;
280}
281
282
283static int wpa_cli_show_event(const char *event)
284{
285 const char *start;
286
287 start = os_strchr(event, '>');
288 if (start == NULL)
289 return 1;
290
291 start++;
292 /*
293 * Skip BSS added/removed events since they can be relatively frequent
294 * and are likely of not much use for an interactive user.
295 */
296 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
297 str_starts(start, WPA_EVENT_BSS_REMOVED))
298 return 0;
299
300 return 1;
301}
302
303
304static int wpa_cli_open_connection(const char *ifname, int attach)
305{
306#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
307 ctrl_conn = wpa_ctrl_open(ifname);
308 if (ctrl_conn == NULL)
309 return -1;
310
311 if (attach && interactive)
312 mon_conn = wpa_ctrl_open(ifname);
313 else
314 mon_conn = NULL;
315#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
316 char *cfile = NULL;
317 int flen, res;
318
319 if (ifname == NULL)
320 return -1;
321
322#ifdef ANDROID
323 if (access(ctrl_iface_dir, F_OK) < 0) {
324 cfile = os_strdup(ifname);
325 if (cfile == NULL)
326 return -1;
327 }
328#endif /* ANDROID */
329
330 if (cfile == NULL) {
331 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
332 cfile = os_malloc(flen);
333 if (cfile == NULL)
334 return -1;
335 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
336 ifname);
337 if (res < 0 || res >= flen) {
338 os_free(cfile);
339 return -1;
340 }
341 }
342
343 ctrl_conn = wpa_ctrl_open(cfile);
344 if (ctrl_conn == NULL) {
345 os_free(cfile);
346 return -1;
347 }
348
349 if (attach && interactive)
350 mon_conn = wpa_ctrl_open(cfile);
351 else
352 mon_conn = NULL;
353 os_free(cfile);
354#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
355
356 if (mon_conn) {
357 if (wpa_ctrl_attach(mon_conn) == 0) {
358 wpa_cli_attached = 1;
359 if (interactive)
360 eloop_register_read_sock(
361 wpa_ctrl_get_fd(mon_conn),
362 wpa_cli_mon_receive, NULL, NULL);
363 } else {
364 printf("Warning: Failed to attach to "
365 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700366 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700367 return -1;
368 }
369 }
370
371 return 0;
372}
373
374
375static void wpa_cli_close_connection(void)
376{
377 if (ctrl_conn == NULL)
378 return;
379
380 if (wpa_cli_attached) {
381 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
382 wpa_cli_attached = 0;
383 }
384 wpa_ctrl_close(ctrl_conn);
385 ctrl_conn = NULL;
386 if (mon_conn) {
387 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
388 wpa_ctrl_close(mon_conn);
389 mon_conn = NULL;
390 }
391}
392
393
394static void wpa_cli_msg_cb(char *msg, size_t len)
395{
396 printf("%s\n", msg);
397}
398
399
400static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
401{
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700402 char buf[4096];
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -0700403#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
404 char _cmd[256];
405#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700406 size_t len;
407 int ret;
408
409 if (ctrl_conn == NULL) {
410 printf("Not connected to wpa_supplicant - command dropped.\n");
411 return -1;
412 }
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -0700413#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
414 if (redirect_interface) {
415 char *arg;
416 arg = os_strchr(cmd, ' ');
417 if (arg) {
418 *arg++ = '\0';
419 ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s %s", cmd, redirect_interface, arg);
420 }
421 else {
422 ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s", cmd, redirect_interface);
423 }
424 cmd = _cmd;
425 os_free(redirect_interface);
426 redirect_interface = NULL;
427 }
428#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700429 len = sizeof(buf) - 1;
430 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
431 wpa_cli_msg_cb);
432 if (ret == -2) {
433 printf("'%s' command timed out.\n", cmd);
434 return -2;
435 } else if (ret < 0) {
436 printf("'%s' command failed.\n", cmd);
437 return -1;
438 }
439 if (print) {
440 buf[len] = '\0';
441 printf("%s", buf);
442 if (interactive && len > 0 && buf[len - 1] != '\n')
443 printf("\n");
444 }
445 return 0;
446}
447
448
449static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
450{
451 return _wpa_ctrl_command(ctrl, cmd, 1);
452}
453
454
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700455static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
456 char *argv[])
457{
458 int i, res;
459 char *pos, *end;
460
461 pos = buf;
462 end = buf + buflen;
463
464 res = os_snprintf(pos, end - pos, "%s", cmd);
465 if (res < 0 || res >= end - pos)
466 goto fail;
467 pos += res;
468
469 for (i = 0; i < argc; i++) {
470 res = os_snprintf(pos, end - pos, " %s", argv[i]);
471 if (res < 0 || res >= end - pos)
472 goto fail;
473 pos += res;
474 }
475
476 buf[buflen - 1] = '\0';
477 return 0;
478
479fail:
480 printf("Too long command\n");
481 return -1;
482}
483
484
485static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
486 int argc, char *argv[])
487{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700488 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700489 if (argc < min_args) {
490 printf("Invalid %s command - at least %d argument%s "
491 "required.\n", cmd, min_args,
492 min_args > 1 ? "s are" : " is");
493 return -1;
494 }
495 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
496 return -1;
497 return wpa_ctrl_command(ctrl, buf);
498}
499
500
501static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
502{
503 return wpa_ctrl_command(ctrl, "IFNAME");
504}
505
506
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700507static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
508{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800509 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
510 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
511 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
512 return wpa_ctrl_command(ctrl, "STATUS-WPS");
513 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700514}
515
516
517static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
518{
519 return wpa_ctrl_command(ctrl, "PING");
520}
521
522
523static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
524{
525 return wpa_ctrl_command(ctrl, "RELOG");
526}
527
528
529static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
530{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700531 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700532}
533
534
535static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
536{
537 return wpa_ctrl_command(ctrl, "MIB");
538}
539
540
541static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
542{
543 return wpa_ctrl_command(ctrl, "PMKSA");
544}
545
546
547static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
548{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700549 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700550 return 0;
551}
552
553
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700554static char ** wpa_cli_complete_help(const char *str, int pos)
555{
556 int arg = get_cmd_arg_num(str, pos);
557 char **res = NULL;
558
559 switch (arg) {
560 case 1:
561 res = wpa_list_cmd_list();
562 break;
563 }
564
565 return res;
566}
567
568
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700569static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
570{
571 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
572 return 0;
573}
574
575
576static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
577{
578 wpa_cli_quit = 1;
579 if (interactive)
580 eloop_terminate();
581 return 0;
582}
583
584
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700585static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
586{
587 char cmd[256];
588 int res;
589
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700590 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800591 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700592 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
593 printf("Too long SET command.\n");
594 return -1;
595 }
596 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700597 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700598
599 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
600}
601
602
603static char ** wpa_cli_complete_set(const char *str, int pos)
604{
605 int arg = get_cmd_arg_num(str, pos);
606 const char *fields[] = {
607 /* runtime values */
608 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
609 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
610 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
611 "wps_fragment_size", "wps_version_number", "ampdu",
612 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
613 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
614 "no_keep_alive",
615 /* global configuration parameters */
616 "eapol_version", "ap_scan", "disable_scan_offload",
617 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
618 "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
619 "driver_param", "dot11RSNAConfigPMKLifetime",
620 "dot11RSNAConfigPMKReauthThreshold",
621 "dot11RSNAConfigSATimeout",
622 "update_config", "load_dynamic_eap", "uuid", "device_name",
623 "manufacturer", "model_name", "model_number", "serial_number",
624 "device_type", "os_version", "config_methods",
625 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
626 "p2p_listen_reg_class", "p2p_listen_channel",
627 "p2p_oper_reg_class", "p2p_oper_channel",
628 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
629 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
630 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
631 "p2p_ignore_shared_freq", "country", "bss_max_count",
632 "bss_expiration_age", "bss_expiration_scan_count",
633 "filter_ssids", "filter_rssi", "max_num_sta",
634 "disassoc_low_ack", "hs20", "interworking", "hessid",
635 "access_network_type", "pbc_in_m1", "autoscan",
636 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
637 "wps_nfc_dev_pw", "ext_password_backend",
638 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
639 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
640 "ignore_old_scan_res", "freq_list"
641 };
642 int i, num_fields = sizeof(fields) / sizeof(fields[0]);
643
644 if (arg == 1) {
645 char **res = os_calloc(num_fields + 1, sizeof(char *));
646 if (res == NULL)
647 return NULL;
648 for (i = 0; i < num_fields; i++) {
649 res[i] = os_strdup(fields[i]);
650 if (res[i] == NULL)
651 return res;
652 }
653 return res;
654 }
655
656 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
657 return cli_txt_list_array(&bsses);
658
659 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700660}
661
662
663static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
664{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700665 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700666}
667
668
669static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
670{
671 return wpa_ctrl_command(ctrl, "LOGOFF");
672}
673
674
675static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
676{
677 return wpa_ctrl_command(ctrl, "LOGON");
678}
679
680
681static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
682 char *argv[])
683{
684 return wpa_ctrl_command(ctrl, "REASSOCIATE");
685}
686
687
688static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
689 char *argv[])
690{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700691 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692}
693
694
695static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
696{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700697 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700698}
699
700
701static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
702 char *argv[])
703{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700704 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700705}
706
707
708static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
709 char *argv[])
710{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700711 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700712}
713
714
715static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
716 char *argv[])
717{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700718 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700719}
720
721
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700722static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
723{
724 char cmd[256];
725 int res;
726
727 if (argc < 1)
728 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
729 else
730 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
731 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
732 printf("Too long BSS_FLUSH command.\n");
733 return -1;
734 }
735 return wpa_ctrl_command(ctrl, cmd);
736}
737
738
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700739static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
740 char *argv[])
741{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700742 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743}
744
745
746static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
747{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700748 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700749}
750
751
752static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
753{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700754 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700755}
756
757
758static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
759{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700760 if (argc == 0) {
761 printf("Invalid WPS_PIN command: need one or two arguments:\n"
762 "- BSSID: use 'any' to select any\n"
763 "- PIN: optional, used only with devices that have no "
764 "display\n");
765 return -1;
766 }
767
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700768 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700769}
770
771
772static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
773 char *argv[])
774{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700775 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700776}
777
778
779static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
780 char *argv[])
781{
782 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
783}
784
785
Dmitry Shmidt04949592012-07-19 12:16:46 -0700786#ifdef CONFIG_WPS_NFC
787
788static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
789{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700790 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700791}
792
793
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800794static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
795 char *argv[])
796{
797 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
798}
799
800
Dmitry Shmidt04949592012-07-19 12:16:46 -0700801static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
802 char *argv[])
803{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700804 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700805}
806
807
808static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
809 char *argv[])
810{
811 int ret;
812 char *buf;
813 size_t buflen;
814
815 if (argc != 1) {
816 printf("Invalid 'wps_nfc_tag_read' command - one argument "
817 "is required.\n");
818 return -1;
819 }
820
821 buflen = 18 + os_strlen(argv[0]);
822 buf = os_malloc(buflen);
823 if (buf == NULL)
824 return -1;
825 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
826
827 ret = wpa_ctrl_command(ctrl, buf);
828 os_free(buf);
829
830 return ret;
831}
832
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800833
834static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
835 char *argv[])
836{
837 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
838}
839
840
841static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
842 char *argv[])
843{
844 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
845}
846
847
848static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
849 char *argv[])
850{
851 int ret;
852 char *buf;
853 size_t buflen;
854
855 if (argc != 1) {
856 printf("Invalid 'nfc_rx_handover_req' command - one argument "
857 "is required.\n");
858 return -1;
859 }
860
861 buflen = 21 + os_strlen(argv[0]);
862 buf = os_malloc(buflen);
863 if (buf == NULL)
864 return -1;
865 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
866
867 ret = wpa_ctrl_command(ctrl, buf);
868 os_free(buf);
869
870 return ret;
871}
872
873
874static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
875 char *argv[])
876{
877 int ret;
878 char *buf;
879 size_t buflen;
880
881 if (argc != 1) {
882 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
883 "is required.\n");
884 return -1;
885 }
886
887 buflen = 21 + os_strlen(argv[0]);
888 buf = os_malloc(buflen);
889 if (buf == NULL)
890 return -1;
891 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
892
893 ret = wpa_ctrl_command(ctrl, buf);
894 os_free(buf);
895
896 return ret;
897}
898
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800899
900static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
901 char *argv[])
902{
903 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
904}
905
Dmitry Shmidt04949592012-07-19 12:16:46 -0700906#endif /* CONFIG_WPS_NFC */
907
908
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700909static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
910{
911 char cmd[256];
912 int res;
913
914 if (argc == 2)
915 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
916 argv[0], argv[1]);
917 else if (argc == 5 || argc == 6) {
918 char ssid_hex[2 * 32 + 1];
919 char key_hex[2 * 64 + 1];
920 int i;
921
922 ssid_hex[0] = '\0';
923 for (i = 0; i < 32; i++) {
924 if (argv[2][i] == '\0')
925 break;
926 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
927 }
928
929 key_hex[0] = '\0';
930 if (argc == 6) {
931 for (i = 0; i < 64; i++) {
932 if (argv[5][i] == '\0')
933 break;
934 os_snprintf(&key_hex[i * 2], 3, "%02x",
935 argv[5][i]);
936 }
937 }
938
939 res = os_snprintf(cmd, sizeof(cmd),
940 "WPS_REG %s %s %s %s %s %s",
941 argv[0], argv[1], ssid_hex, argv[3], argv[4],
942 key_hex);
943 } else {
944 printf("Invalid WPS_REG command: need two arguments:\n"
945 "- BSSID of the target AP\n"
946 "- AP PIN\n");
947 printf("Alternatively, six arguments can be used to "
948 "reconfigure the AP:\n"
949 "- BSSID of the target AP\n"
950 "- AP PIN\n"
951 "- new SSID\n"
952 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
953 "- new encr (NONE, WEP, TKIP, CCMP)\n"
954 "- new key\n");
955 return -1;
956 }
957
958 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
959 printf("Too long WPS_REG command.\n");
960 return -1;
961 }
962 return wpa_ctrl_command(ctrl, cmd);
963}
964
965
966static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
967 char *argv[])
968{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700969 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700970}
971
972
973static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
974 char *argv[])
975{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700976 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700977}
978
979
980static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
981 char *argv[])
982{
983 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
984
985}
986
987
988static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
989 char *argv[])
990{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700991 if (argc < 2) {
992 printf("Invalid WPS_ER_PIN command: need at least two "
993 "arguments:\n"
994 "- UUID: use 'any' to select any\n"
995 "- PIN: Enrollee PIN\n"
996 "optional: - Enrollee MAC address\n");
997 return -1;
998 }
999
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001000 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001001}
1002
1003
1004static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
1005 char *argv[])
1006{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001007 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008}
1009
1010
1011static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
1012 char *argv[])
1013{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001014 if (argc != 2) {
1015 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1016 "- UUID: specify which AP to use\n"
1017 "- PIN: AP PIN\n");
1018 return -1;
1019 }
1020
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001021 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001022}
1023
1024
1025static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1026 char *argv[])
1027{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001028 if (argc != 2) {
1029 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1030 "arguments:\n"
1031 "- UUID: specify which AP to use\n"
1032 "- Network configuration id\n");
1033 return -1;
1034 }
1035
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001036 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001037}
1038
1039
1040static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1041 char *argv[])
1042{
1043 char cmd[256];
1044 int res;
1045
1046 if (argc == 5 || argc == 6) {
1047 char ssid_hex[2 * 32 + 1];
1048 char key_hex[2 * 64 + 1];
1049 int i;
1050
1051 ssid_hex[0] = '\0';
1052 for (i = 0; i < 32; i++) {
1053 if (argv[2][i] == '\0')
1054 break;
1055 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1056 }
1057
1058 key_hex[0] = '\0';
1059 if (argc == 6) {
1060 for (i = 0; i < 64; i++) {
1061 if (argv[5][i] == '\0')
1062 break;
1063 os_snprintf(&key_hex[i * 2], 3, "%02x",
1064 argv[5][i]);
1065 }
1066 }
1067
1068 res = os_snprintf(cmd, sizeof(cmd),
1069 "WPS_ER_CONFIG %s %s %s %s %s %s",
1070 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1071 key_hex);
1072 } else {
1073 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1074 "- AP UUID\n"
1075 "- AP PIN\n"
1076 "- new SSID\n"
1077 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1078 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1079 "- new key\n");
1080 return -1;
1081 }
1082
1083 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1084 printf("Too long WPS_ER_CONFIG command.\n");
1085 return -1;
1086 }
1087 return wpa_ctrl_command(ctrl, cmd);
1088}
1089
1090
Dmitry Shmidt04949592012-07-19 12:16:46 -07001091#ifdef CONFIG_WPS_NFC
1092static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1093 char *argv[])
1094{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001095 if (argc != 2) {
1096 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1097 "arguments:\n"
1098 "- WPS/NDEF: token format\n"
1099 "- UUID: specify which AP to use\n");
1100 return -1;
1101 }
1102
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001103 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001104}
1105#endif /* CONFIG_WPS_NFC */
1106
1107
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001108static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1109{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001110 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001111}
1112
1113
1114static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1115{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001116 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001117}
1118
1119
1120static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1121{
1122 char cmd[256], *pos, *end;
1123 int i, ret;
1124
1125 if (argc < 2) {
1126 printf("Invalid IDENTITY command: needs two arguments "
1127 "(network id and identity)\n");
1128 return -1;
1129 }
1130
1131 end = cmd + sizeof(cmd);
1132 pos = cmd;
1133 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1134 argv[0], argv[1]);
1135 if (ret < 0 || ret >= end - pos) {
1136 printf("Too long IDENTITY command.\n");
1137 return -1;
1138 }
1139 pos += ret;
1140 for (i = 2; i < argc; i++) {
1141 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1142 if (ret < 0 || ret >= end - pos) {
1143 printf("Too long IDENTITY command.\n");
1144 return -1;
1145 }
1146 pos += ret;
1147 }
1148
1149 return wpa_ctrl_command(ctrl, cmd);
1150}
1151
1152
1153static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1154{
1155 char cmd[256], *pos, *end;
1156 int i, ret;
1157
1158 if (argc < 2) {
1159 printf("Invalid PASSWORD command: needs two arguments "
1160 "(network id and password)\n");
1161 return -1;
1162 }
1163
1164 end = cmd + sizeof(cmd);
1165 pos = cmd;
1166 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1167 argv[0], argv[1]);
1168 if (ret < 0 || ret >= end - pos) {
1169 printf("Too long PASSWORD command.\n");
1170 return -1;
1171 }
1172 pos += ret;
1173 for (i = 2; i < argc; i++) {
1174 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1175 if (ret < 0 || ret >= end - pos) {
1176 printf("Too long PASSWORD command.\n");
1177 return -1;
1178 }
1179 pos += ret;
1180 }
1181
1182 return wpa_ctrl_command(ctrl, cmd);
1183}
1184
1185
1186static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1187 char *argv[])
1188{
1189 char cmd[256], *pos, *end;
1190 int i, ret;
1191
1192 if (argc < 2) {
1193 printf("Invalid NEW_PASSWORD command: needs two arguments "
1194 "(network id and password)\n");
1195 return -1;
1196 }
1197
1198 end = cmd + sizeof(cmd);
1199 pos = cmd;
1200 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1201 argv[0], argv[1]);
1202 if (ret < 0 || ret >= end - pos) {
1203 printf("Too long NEW_PASSWORD command.\n");
1204 return -1;
1205 }
1206 pos += ret;
1207 for (i = 2; i < argc; i++) {
1208 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1209 if (ret < 0 || ret >= end - pos) {
1210 printf("Too long NEW_PASSWORD command.\n");
1211 return -1;
1212 }
1213 pos += ret;
1214 }
1215
1216 return wpa_ctrl_command(ctrl, cmd);
1217}
1218
1219
1220static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1221{
1222 char cmd[256], *pos, *end;
1223 int i, ret;
1224
1225 if (argc < 2) {
1226 printf("Invalid PIN command: needs two arguments "
1227 "(network id and pin)\n");
1228 return -1;
1229 }
1230
1231 end = cmd + sizeof(cmd);
1232 pos = cmd;
1233 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1234 argv[0], argv[1]);
1235 if (ret < 0 || ret >= end - pos) {
1236 printf("Too long PIN command.\n");
1237 return -1;
1238 }
1239 pos += ret;
1240 for (i = 2; i < argc; i++) {
1241 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1242 if (ret < 0 || ret >= end - pos) {
1243 printf("Too long PIN command.\n");
1244 return -1;
1245 }
1246 pos += ret;
1247 }
1248 return wpa_ctrl_command(ctrl, cmd);
1249}
1250
1251
1252static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1253{
1254 char cmd[256], *pos, *end;
1255 int i, ret;
1256
1257 if (argc < 2) {
1258 printf("Invalid OTP command: needs two arguments (network "
1259 "id and password)\n");
1260 return -1;
1261 }
1262
1263 end = cmd + sizeof(cmd);
1264 pos = cmd;
1265 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1266 argv[0], argv[1]);
1267 if (ret < 0 || ret >= end - pos) {
1268 printf("Too long OTP command.\n");
1269 return -1;
1270 }
1271 pos += ret;
1272 for (i = 2; i < argc; i++) {
1273 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1274 if (ret < 0 || ret >= end - pos) {
1275 printf("Too long OTP command.\n");
1276 return -1;
1277 }
1278 pos += ret;
1279 }
1280
1281 return wpa_ctrl_command(ctrl, cmd);
1282}
1283
1284
1285static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1286 char *argv[])
1287{
1288 char cmd[256], *pos, *end;
1289 int i, ret;
1290
1291 if (argc < 2) {
1292 printf("Invalid PASSPHRASE command: needs two arguments "
1293 "(network id and passphrase)\n");
1294 return -1;
1295 }
1296
1297 end = cmd + sizeof(cmd);
1298 pos = cmd;
1299 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1300 argv[0], argv[1]);
1301 if (ret < 0 || ret >= end - pos) {
1302 printf("Too long PASSPHRASE command.\n");
1303 return -1;
1304 }
1305 pos += ret;
1306 for (i = 2; i < argc; i++) {
1307 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1308 if (ret < 0 || ret >= end - pos) {
1309 printf("Too long PASSPHRASE command.\n");
1310 return -1;
1311 }
1312 pos += ret;
1313 }
1314
1315 return wpa_ctrl_command(ctrl, cmd);
1316}
1317
1318
1319static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1320{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001321 if (argc < 2) {
1322 printf("Invalid BSSID command: needs two arguments (network "
1323 "id and BSSID)\n");
1324 return -1;
1325 }
1326
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001327 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001328}
1329
1330
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001331static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1332{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001333 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001334}
1335
1336
1337static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1338{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001339 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001340}
1341
1342
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001343static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1344 char *argv[])
1345{
1346 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1347}
1348
1349
1350static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1351 char *argv[])
1352{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001353 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001354}
1355
1356
1357static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1358 char *argv[])
1359{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001360 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001361}
1362
1363
1364static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1365 char *argv[])
1366{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001367 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001368}
1369
1370
1371static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1372 char *argv[])
1373{
1374 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1375}
1376
1377
1378static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1379 char *argv[])
1380{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001381 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001382}
1383
1384
1385static void wpa_cli_show_network_variables(void)
1386{
1387 printf("set_network variables:\n"
1388 " ssid (network name, SSID)\n"
1389 " psk (WPA passphrase or pre-shared key)\n"
1390 " key_mgmt (key management protocol)\n"
1391 " identity (EAP identity)\n"
1392 " password (EAP password)\n"
1393 " ...\n"
1394 "\n"
1395 "Note: Values are entered in the same format as the "
1396 "configuration file is using,\n"
1397 "i.e., strings values need to be inside double quotation "
1398 "marks.\n"
1399 "For example: set_network 1 ssid \"network name\"\n"
1400 "\n"
1401 "Please see wpa_supplicant.conf documentation for full list "
1402 "of\navailable variables.\n");
1403}
1404
1405
1406static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1407 char *argv[])
1408{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001409 if (argc == 0) {
1410 wpa_cli_show_network_variables();
1411 return 0;
1412 }
1413
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001414 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001415 printf("Invalid SET_NETWORK command: needs three arguments\n"
1416 "(network id, variable name, and value)\n");
1417 return -1;
1418 }
1419
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001420 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001421}
1422
1423
1424static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1425 char *argv[])
1426{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001427 if (argc == 0) {
1428 wpa_cli_show_network_variables();
1429 return 0;
1430 }
1431
1432 if (argc != 2) {
1433 printf("Invalid GET_NETWORK command: needs two arguments\n"
1434 "(network id and variable name)\n");
1435 return -1;
1436 }
1437
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001438 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001439}
1440
1441
Dmitry Shmidt04949592012-07-19 12:16:46 -07001442static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1443 char *argv[])
1444{
1445 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1446}
1447
1448
1449static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1450{
1451 return wpa_ctrl_command(ctrl, "ADD_CRED");
1452}
1453
1454
1455static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1456 char *argv[])
1457{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001458 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001459}
1460
1461
1462static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1463{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001464 if (argc != 3) {
1465 printf("Invalid SET_CRED command: needs three arguments\n"
1466 "(cred id, variable name, and value)\n");
1467 return -1;
1468 }
1469
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001470 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001471}
1472
1473
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001474static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1475 char *argv[])
1476{
1477 return wpa_ctrl_command(ctrl, "DISCONNECT");
1478}
1479
1480
1481static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1482 char *argv[])
1483{
1484 return wpa_ctrl_command(ctrl, "RECONNECT");
1485}
1486
1487
1488static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1489 char *argv[])
1490{
1491 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1492}
1493
1494
1495static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1496{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001497 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001498}
1499
1500
1501static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1502 char *argv[])
1503{
1504 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1505}
1506
1507
1508static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1509{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001510 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001511}
1512
1513
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001514static char ** wpa_cli_complete_bss(const char *str, int pos)
1515{
1516 int arg = get_cmd_arg_num(str, pos);
1517 char **res = NULL;
1518
1519 switch (arg) {
1520 case 1:
1521 res = cli_txt_list_array(&bsses);
1522 break;
1523 }
1524
1525 return res;
1526}
1527
1528
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001529static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1530 char *argv[])
1531{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001532 if (argc < 1 || argc > 2) {
1533 printf("Invalid GET_CAPABILITY command: need either one or "
1534 "two arguments\n");
1535 return -1;
1536 }
1537
1538 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1539 printf("Invalid GET_CAPABILITY command: second argument, "
1540 "if any, must be 'strict'\n");
1541 return -1;
1542 }
1543
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001544 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001545}
1546
1547
1548static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1549{
1550 printf("Available interfaces:\n");
1551 return wpa_ctrl_command(ctrl, "INTERFACES");
1552}
1553
1554
1555static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1556{
1557 if (argc < 1) {
1558 wpa_cli_list_interfaces(ctrl);
1559 return 0;
1560 }
1561
1562 wpa_cli_close_connection();
1563 os_free(ctrl_ifname);
1564 ctrl_ifname = os_strdup(argv[0]);
1565
1566 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1567 printf("Connected to interface '%s.\n", ctrl_ifname);
1568 } else {
1569 printf("Could not connect to interface '%s' - re-trying\n",
1570 ctrl_ifname);
1571 }
1572 return 0;
1573}
1574
1575
1576static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1577 char *argv[])
1578{
1579 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1580}
1581
1582
1583static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1584 char *argv[])
1585{
1586 return wpa_ctrl_command(ctrl, "TERMINATE");
1587}
1588
1589
1590static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1591 char *argv[])
1592{
1593 char cmd[256];
1594 int res;
1595
1596 if (argc < 1) {
1597 printf("Invalid INTERFACE_ADD command: needs at least one "
1598 "argument (interface name)\n"
1599 "All arguments: ifname confname driver ctrl_interface "
1600 "driver_param bridge_name\n");
1601 return -1;
1602 }
1603
1604 /*
1605 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1606 * <driver_param>TAB<bridge_name>
1607 */
1608 res = os_snprintf(cmd, sizeof(cmd),
1609 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1610 argv[0],
1611 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1612 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1613 argc > 5 ? argv[5] : "");
1614 if (res < 0 || (size_t) res >= sizeof(cmd))
1615 return -1;
1616 cmd[sizeof(cmd) - 1] = '\0';
1617 return wpa_ctrl_command(ctrl, cmd);
1618}
1619
1620
1621static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1622 char *argv[])
1623{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001624 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001625}
1626
1627
1628static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1629 char *argv[])
1630{
1631 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1632}
1633
1634
1635#ifdef CONFIG_AP
1636static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1637{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001638 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001639}
1640
1641
1642static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1643 char *addr, size_t addr_len)
1644{
1645 char buf[4096], *pos;
1646 size_t len;
1647 int ret;
1648
1649 if (ctrl_conn == NULL) {
1650 printf("Not connected to hostapd - command dropped.\n");
1651 return -1;
1652 }
1653 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001654 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001655 wpa_cli_msg_cb);
1656 if (ret == -2) {
1657 printf("'%s' command timed out.\n", cmd);
1658 return -2;
1659 } else if (ret < 0) {
1660 printf("'%s' command failed.\n", cmd);
1661 return -1;
1662 }
1663
1664 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001665 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001666 return -1;
1667 printf("%s", buf);
1668
1669 pos = buf;
1670 while (*pos != '\0' && *pos != '\n')
1671 pos++;
1672 *pos = '\0';
1673 os_strlcpy(addr, buf, addr_len);
1674 return 0;
1675}
1676
1677
1678static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1679{
1680 char addr[32], cmd[64];
1681
1682 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1683 return 0;
1684 do {
1685 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1686 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1687
1688 return -1;
1689}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001690
1691
1692static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1693 char *argv[])
1694{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001695 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001696}
1697
1698
1699static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1700 char *argv[])
1701{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001702 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001703}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001704#endif /* CONFIG_AP */
1705
1706
1707static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1708{
1709 return wpa_ctrl_command(ctrl, "SUSPEND");
1710}
1711
1712
1713static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1714{
1715 return wpa_ctrl_command(ctrl, "RESUME");
1716}
1717
1718
1719static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1720{
1721 return wpa_ctrl_command(ctrl, "DROP_SA");
1722}
1723
1724
1725static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1726{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001727 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001728}
1729
1730
1731#ifdef CONFIG_P2P
1732
1733static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1734{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001735 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1736}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001737
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001738
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001739static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1740{
1741 char **res = NULL;
1742 int arg = get_cmd_arg_num(str, pos);
1743
1744 res = os_calloc(6, sizeof(char *));
1745 if (res == NULL)
1746 return NULL;
1747 res[0] = os_strdup("type=social");
1748 if (res[0] == NULL) {
1749 os_free(res);
1750 return NULL;
1751 }
1752 res[1] = os_strdup("type=progressive");
1753 if (res[1] == NULL)
1754 return res;
1755 res[2] = os_strdup("delay=");
1756 if (res[2] == NULL)
1757 return res;
1758 res[3] = os_strdup("dev_id=");
1759 if (res[3] == NULL)
1760 return res;
1761 if (arg == 1)
1762 res[4] = os_strdup("[timeout]");
1763
1764 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001765}
1766
1767
1768static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1769 char *argv[])
1770{
1771 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1772}
1773
1774
1775static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1776 char *argv[])
1777{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001778 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001779}
1780
1781
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001782static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1783{
1784 int arg = get_cmd_arg_num(str, pos);
1785 char **res = NULL;
1786
1787 switch (arg) {
1788 case 1:
1789 res = cli_txt_list_array(&p2p_peers);
1790 break;
1791 }
1792
1793 return res;
1794}
1795
1796
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1798 char *argv[])
1799{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001800 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001801}
1802
1803
1804static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1805 char *argv[])
1806{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001807 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001808}
1809
1810
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001811static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1812{
1813 int arg = get_cmd_arg_num(str, pos);
1814 char **res = NULL;
1815
1816 switch (arg) {
1817 case 1:
1818 res = cli_txt_list_array(&p2p_groups);
1819 break;
1820 }
1821
1822 return res;
1823}
1824
1825
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001826static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1827 char *argv[])
1828{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001829 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001830}
1831
1832
1833static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1834 char *argv[])
1835{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001836 if (argc != 2 && argc != 3) {
1837 printf("Invalid P2P_PROV_DISC command: needs at least "
1838 "two arguments, address and config method\n"
1839 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001840 return -1;
1841 }
1842
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001843 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001844}
1845
1846
1847static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1848 char *argv[])
1849{
1850 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1851}
1852
1853
1854static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1855 char *argv[])
1856{
1857 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001858
1859 if (argc != 2 && argc != 4) {
1860 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1861 "arguments (address and TLVs) or four arguments "
1862 "(address, \"upnp\", version, search target "
1863 "(SSDP ST:)\n");
1864 return -1;
1865 }
1866
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001867 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001868 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001869 return wpa_ctrl_command(ctrl, cmd);
1870}
1871
1872
1873static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1874 int argc, char *argv[])
1875{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001876 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001877}
1878
1879
1880static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1881 char *argv[])
1882{
1883 char cmd[4096];
1884 int res;
1885
1886 if (argc != 4) {
1887 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1888 "arguments (freq, address, dialog token, and TLVs)\n");
1889 return -1;
1890 }
1891
1892 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1893 argv[0], argv[1], argv[2], argv[3]);
1894 if (res < 0 || (size_t) res >= sizeof(cmd))
1895 return -1;
1896 cmd[sizeof(cmd) - 1] = '\0';
1897 return wpa_ctrl_command(ctrl, cmd);
1898}
1899
1900
1901static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1902 char *argv[])
1903{
1904 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1905}
1906
1907
1908static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1909 int argc, char *argv[])
1910{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001911 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001912}
1913
1914
1915static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1916 char *argv[])
1917{
1918 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1919}
1920
1921
1922static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1923 char *argv[])
1924{
1925 char cmd[4096];
1926 int res;
1927
1928 if (argc != 3 && argc != 4) {
1929 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1930 "arguments\n");
1931 return -1;
1932 }
1933
1934 if (argc == 4)
1935 res = os_snprintf(cmd, sizeof(cmd),
1936 "P2P_SERVICE_ADD %s %s %s %s",
1937 argv[0], argv[1], argv[2], argv[3]);
1938 else
1939 res = os_snprintf(cmd, sizeof(cmd),
1940 "P2P_SERVICE_ADD %s %s %s",
1941 argv[0], argv[1], argv[2]);
1942 if (res < 0 || (size_t) res >= sizeof(cmd))
1943 return -1;
1944 cmd[sizeof(cmd) - 1] = '\0';
1945 return wpa_ctrl_command(ctrl, cmd);
1946}
1947
1948
1949static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1950 char *argv[])
1951{
1952 char cmd[4096];
1953 int res;
1954
1955 if (argc != 2 && argc != 3) {
1956 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1957 "arguments\n");
1958 return -1;
1959 }
1960
1961 if (argc == 3)
1962 res = os_snprintf(cmd, sizeof(cmd),
1963 "P2P_SERVICE_DEL %s %s %s",
1964 argv[0], argv[1], argv[2]);
1965 else
1966 res = os_snprintf(cmd, sizeof(cmd),
1967 "P2P_SERVICE_DEL %s %s",
1968 argv[0], argv[1]);
1969 if (res < 0 || (size_t) res >= sizeof(cmd))
1970 return -1;
1971 cmd[sizeof(cmd) - 1] = '\0';
1972 return wpa_ctrl_command(ctrl, cmd);
1973}
1974
1975
1976static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1977 int argc, char *argv[])
1978{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001979 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001980}
1981
1982
1983static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1984 int argc, char *argv[])
1985{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001986 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001987}
1988
1989
1990static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1991{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001992 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001993}
1994
1995
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001996static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1997{
1998 int arg = get_cmd_arg_num(str, pos);
1999 char **res = NULL;
2000
2001 switch (arg) {
2002 case 1:
2003 res = cli_txt_list_array(&p2p_peers);
2004 break;
2005 }
2006
2007 return res;
2008}
2009
2010
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002011static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2012 char *addr, size_t addr_len,
2013 int discovered)
2014{
2015 char buf[4096], *pos;
2016 size_t len;
2017 int ret;
2018
2019 if (ctrl_conn == NULL)
2020 return -1;
2021 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002022 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002023 wpa_cli_msg_cb);
2024 if (ret == -2) {
2025 printf("'%s' command timed out.\n", cmd);
2026 return -2;
2027 } else if (ret < 0) {
2028 printf("'%s' command failed.\n", cmd);
2029 return -1;
2030 }
2031
2032 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002033 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002034 return -1;
2035
2036 pos = buf;
2037 while (*pos != '\0' && *pos != '\n')
2038 pos++;
2039 *pos++ = '\0';
2040 os_strlcpy(addr, buf, addr_len);
2041 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2042 printf("%s\n", addr);
2043 return 0;
2044}
2045
2046
2047static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2048{
2049 char addr[32], cmd[64];
2050 int discovered;
2051
2052 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2053
2054 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2055 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002056 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002057 do {
2058 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2059 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2060 discovered) == 0);
2061
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002062 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002063}
2064
2065
2066static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2067{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002068 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002069}
2070
2071
2072static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2073{
2074 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2075}
2076
2077
2078static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2079 char *argv[])
2080{
2081 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2082}
2083
2084
2085static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2086 char *argv[])
2087{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002088 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002089}
2090
2091
2092static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2093 char *argv[])
2094{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002095 if (argc != 0 && argc != 2 && argc != 4) {
2096 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2097 "(preferred duration, interval; in microsecods).\n"
2098 "Optional second pair can be used to provide "
2099 "acceptable values.\n");
2100 return -1;
2101 }
2102
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002103 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002104}
2105
2106
2107static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2108 char *argv[])
2109{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002110 if (argc != 0 && argc != 2) {
2111 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2112 "(availability period, availability interval; in "
2113 "millisecods).\n"
2114 "Extended Listen Timing can be cancelled with this "
2115 "command when used without parameters.\n");
2116 return -1;
2117 }
2118
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002119 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2120}
2121
2122#endif /* CONFIG_P2P */
2123
2124#ifdef CONFIG_WIFI_DISPLAY
2125
2126static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2127 char *argv[])
2128{
2129 char cmd[100];
2130 int res;
2131
2132 if (argc != 1 && argc != 2) {
2133 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2134 "arguments (subelem, hexdump)\n");
2135 return -1;
2136 }
2137
2138 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2139 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002140 if (res < 0 || (size_t) res >= sizeof(cmd))
2141 return -1;
2142 cmd[sizeof(cmd) - 1] = '\0';
2143 return wpa_ctrl_command(ctrl, cmd);
2144}
2145
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002146
2147static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2148 char *argv[])
2149{
2150 char cmd[100];
2151 int res;
2152
2153 if (argc != 1) {
2154 printf("Invalid WFD_SUBELEM_GET command: needs one "
2155 "argument (subelem)\n");
2156 return -1;
2157 }
2158
2159 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2160 argv[0]);
2161 if (res < 0 || (size_t) res >= sizeof(cmd))
2162 return -1;
2163 cmd[sizeof(cmd) - 1] = '\0';
2164 return wpa_ctrl_command(ctrl, cmd);
2165}
2166#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002167
2168
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002169#ifdef CONFIG_INTERWORKING
2170static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2171 char *argv[])
2172{
2173 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2174}
2175
2176
2177static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2178 char *argv[])
2179{
2180 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2181}
2182
2183
2184static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2185 char *argv[])
2186{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002187 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002188}
2189
2190
2191static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2192 char *argv[])
2193{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002194 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002195}
2196
2197
2198static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2199{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002200 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2201}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002202
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002203
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002204static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2205 char *argv[])
2206{
2207 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2208}
2209
2210
2211static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2212 char *argv[])
2213{
2214 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002215}
2216#endif /* CONFIG_INTERWORKING */
2217
2218
Dmitry Shmidt04949592012-07-19 12:16:46 -07002219#ifdef CONFIG_HS20
2220
2221static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2222 char *argv[])
2223{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002224 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002225}
2226
2227
2228static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2229 char *argv[])
2230{
2231 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002232
2233 if (argc == 0) {
2234 printf("Command needs one or two arguments (dst mac addr and "
2235 "optional home realm)\n");
2236 return -1;
2237 }
2238
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002239 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2240 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002241 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002242
2243 return wpa_ctrl_command(ctrl, cmd);
2244}
2245
2246#endif /* CONFIG_HS20 */
2247
2248
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002249static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2250 char *argv[])
2251{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002252 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002253}
2254
2255
2256static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2257 char *argv[])
2258{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002259 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002260}
2261
2262
2263static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2264 char *argv[])
2265{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002266 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002267}
2268
2269
2270static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2271 char *argv[])
2272{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002273 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002274}
2275
2276
2277static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2278 char *argv[])
2279{
2280 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2281}
2282
2283
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002284static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2285 char *argv[])
2286{
2287 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2288}
2289
2290
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002291static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2292 char *argv[])
2293{
2294 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2295}
2296
Dmitry Shmidt04949592012-07-19 12:16:46 -07002297
2298#ifdef CONFIG_AUTOSCAN
2299
2300static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2301{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002302 if (argc == 0)
2303 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2304
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002305 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002306}
2307
2308#endif /* CONFIG_AUTOSCAN */
2309
2310
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002311#ifdef CONFIG_WNM
2312
2313static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2314{
2315 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2316}
2317
2318#endif /* CONFIG_WNM */
2319
2320
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002321static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2322{
2323 if (argc == 0)
2324 return -1;
2325 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2326}
2327
2328
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002329#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002330static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2331{
2332 char cmd[256];
2333 int i;
2334 int len;
2335
2336 if (argc < 1) {
2337 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2338 return -1;
2339 }
2340
2341 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2342 for (i=1; i < argc; i++)
2343 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2344 cmd[sizeof(cmd) - 1] = '\0';
2345 printf("%s: %s\n", __func__, cmd);
2346 return wpa_ctrl_command(ctrl, cmd);
2347}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002348#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002349
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002350
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002351static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2352{
2353 return wpa_ctrl_command(ctrl, "FLUSH");
2354}
2355
2356
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002357enum wpa_cli_cmd_flags {
2358 cli_cmd_flag_none = 0x00,
2359 cli_cmd_flag_sensitive = 0x01
2360};
2361
2362struct wpa_cli_cmd {
2363 const char *cmd;
2364 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002365 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002366 enum wpa_cli_cmd_flags flags;
2367 const char *usage;
2368};
2369
2370static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002371 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002372 cli_cmd_flag_none,
2373 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002374 { "ifname", wpa_cli_cmd_ifname, NULL,
2375 cli_cmd_flag_none,
2376 "= get current interface name" },
2377 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002378 cli_cmd_flag_none,
2379 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002380 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002381 cli_cmd_flag_none,
2382 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002383 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002384 cli_cmd_flag_none,
2385 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002386 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002387 cli_cmd_flag_none,
2388 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002389 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002390 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002391 "[command] = show usage help" },
2392 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002393 cli_cmd_flag_none,
2394 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002395 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002396 cli_cmd_flag_none,
2397 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002398 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002399 cli_cmd_flag_none,
2400 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002401 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002402 cli_cmd_flag_none,
2403 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002404 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002405 cli_cmd_flag_none,
2406 "= set variables (shows list of variables when run without "
2407 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002408 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002409 cli_cmd_flag_none,
2410 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002411 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002412 cli_cmd_flag_none,
2413 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002414 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002415 cli_cmd_flag_none,
2416 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002417 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002418 cli_cmd_flag_none,
2419 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002420 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002421 cli_cmd_flag_none,
2422 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002423 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002424 cli_cmd_flag_none,
2425 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002426 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002427 cli_cmd_flag_none,
2428 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002429 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002430 cli_cmd_flag_sensitive,
2431 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002432 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 cli_cmd_flag_sensitive,
2434 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002435 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002436 cli_cmd_flag_sensitive,
2437 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002438 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002439 cli_cmd_flag_sensitive,
2440 "<network id> <password> = configure one-time-password for an SSID"
2441 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002442 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002443 cli_cmd_flag_sensitive,
2444 "<network id> <passphrase> = configure private key passphrase\n"
2445 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002446 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002447 cli_cmd_flag_none,
2448 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002449 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002450 cli_cmd_flag_none,
2451 "<BSSID> = add a BSSID to the blacklist\n"
2452 "blacklist clear = clear the blacklist\n"
2453 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002454 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002455 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002456 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002457 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002458 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002459 cli_cmd_flag_none,
2460 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002461 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002462 cli_cmd_flag_none,
2463 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002464 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002465 cli_cmd_flag_none,
2466 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002467 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 cli_cmd_flag_none,
2469 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002470 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002471 cli_cmd_flag_none,
2472 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002473 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002474 cli_cmd_flag_none,
2475 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002476 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002477 cli_cmd_flag_sensitive,
2478 "<network id> <variable> <value> = set network variables (shows\n"
2479 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002480 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002481 cli_cmd_flag_none,
2482 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002483 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002484 cli_cmd_flag_none,
2485 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002486 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002487 cli_cmd_flag_none,
2488 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002489 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002490 cli_cmd_flag_none,
2491 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002492 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002493 cli_cmd_flag_sensitive,
2494 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002495 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002496 cli_cmd_flag_none,
2497 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002498 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002499 cli_cmd_flag_none,
2500 "= disconnect and wait for reassociate/reconnect command before\n"
2501 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002502 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002503 cli_cmd_flag_none,
2504 "= like reassociate, but only takes effect if already disconnected"
2505 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002506 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507 cli_cmd_flag_none,
2508 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002509 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002510 cli_cmd_flag_none,
2511 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002512 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 cli_cmd_flag_none,
2514 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002515 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002516 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002517 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002518 "= get capabilies" },
2519 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 cli_cmd_flag_none,
2521 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002522 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523 cli_cmd_flag_none,
2524 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002525 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 cli_cmd_flag_none,
2527 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2528 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2529 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002530 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531 cli_cmd_flag_none,
2532 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002533 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002534 cli_cmd_flag_none,
2535 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002536 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002537 cli_cmd_flag_none,
2538 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002539 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002540 cli_cmd_flag_none,
2541 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002542 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002543 cli_cmd_flag_none,
2544 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002545 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002546 cli_cmd_flag_none,
2547 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002548 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002549 cli_cmd_flag_none,
2550 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002551 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002552 cli_cmd_flag_none,
2553 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002554 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555 cli_cmd_flag_none,
2556 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002557 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558 cli_cmd_flag_none,
2559 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002560 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561 cli_cmd_flag_sensitive,
2562 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2563 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002564 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002565 cli_cmd_flag_sensitive,
2566 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002567 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002568 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002569#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002570 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002571 cli_cmd_flag_none,
2572 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002573 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2574 cli_cmd_flag_none,
2575 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002576 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002577 cli_cmd_flag_none,
2578 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002579 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002580 cli_cmd_flag_sensitive,
2581 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002582 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2583 cli_cmd_flag_none,
2584 "<NDEF> <WPS> = create NFC handover request" },
2585 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2586 cli_cmd_flag_none,
2587 "<NDEF> <WPS> = create NFC handover select" },
2588 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2589 cli_cmd_flag_none,
2590 "<hexdump of payload> = report received NFC handover request" },
2591 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2592 cli_cmd_flag_none,
2593 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002594 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2595 cli_cmd_flag_none,
2596 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2597 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002598#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002599 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002600 cli_cmd_flag_sensitive,
2601 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002602 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603 cli_cmd_flag_sensitive,
2604 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002605 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002606 cli_cmd_flag_none,
2607 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002608 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 cli_cmd_flag_none,
2610 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002611 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002612 cli_cmd_flag_sensitive,
2613 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002614 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002615 cli_cmd_flag_none,
2616 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002617 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002618 cli_cmd_flag_sensitive,
2619 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002620 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002621 cli_cmd_flag_none,
2622 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002623 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 cli_cmd_flag_sensitive,
2625 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002626#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002627 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002628 cli_cmd_flag_none,
2629 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2630#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002631 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002632 cli_cmd_flag_none,
2633 "<addr> = request RSN authentication with <addr> in IBSS" },
2634#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002635 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002636 cli_cmd_flag_none,
2637 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002638 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002639 cli_cmd_flag_none,
2640 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002641 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002642 cli_cmd_flag_none,
2643 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002644 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002645 cli_cmd_flag_none,
2646 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002647#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002648 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002649 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002650 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002652 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002653 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002654 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002655 cli_cmd_flag_none,
2656 "<addr> = roam to the specified BSS" },
2657#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002658 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2659 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002660 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002661 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002662 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002663 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2664 cli_cmd_flag_none,
2665 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2666 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002667 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002668 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2669 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002670 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002671 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2672 "[ht40] = add a new P2P group (local end as GO)" },
2673 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2674 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002675 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002676 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002677 cli_cmd_flag_none,
2678 "= get the passphrase for a group (GO only)" },
2679 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002680 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002681 "<addr> <TLVs> = schedule service discovery request" },
2682 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002683 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002684 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002685 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002686 cli_cmd_flag_none,
2687 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002688 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002689 cli_cmd_flag_none,
2690 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002691 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002692 cli_cmd_flag_none,
2693 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002694 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002695 cli_cmd_flag_none,
2696 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002697 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698 cli_cmd_flag_none,
2699 "<bonjour|upnp> <query|version> <response|service> = add a local "
2700 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002701 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002702 cli_cmd_flag_none,
2703 "<bonjour|upnp> <query|version> [|service] = remove a local "
2704 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002705 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002706 cli_cmd_flag_none,
2707 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002708 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002709 cli_cmd_flag_none,
2710 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002711 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002712 "[discovered] = list known (optionally, only fully discovered) P2P "
2713 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002714 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2715 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002716 "<address> = show information about known P2P peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002717 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002718 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002719 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002720 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002721 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002723 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2724 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002725 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002726 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2727 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002728 "[<duration> <interval>] [<duration> <interval>] = request GO "
2729 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002730 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2731 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002732 "[<period> <interval>] = set extended listen timing" },
2733#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002734#ifdef CONFIG_WIFI_DISPLAY
2735 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2736 cli_cmd_flag_none,
2737 "<subelem> [contents] = set Wi-Fi Display subelement" },
2738 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2739 cli_cmd_flag_none,
2740 "<subelem> = get Wi-Fi Display subelement" },
2741#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002742#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002743 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002744 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002745 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2746 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002747 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002748 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002749 cli_cmd_flag_none,
2750 "[auto] = perform Interworking network selection" },
2751 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002752 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002753 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002754 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2755 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002756 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002757 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2758 cli_cmd_flag_none,
2759 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2760 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2761 wpa_cli_complete_bss, cli_cmd_flag_none,
2762 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002763#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002764#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002765 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2766 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002767 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2768 },
2769 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002770 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002771 "<addr> <home realm> = get HS20 nai home realm list" },
2772#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002773 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2774 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002775 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002776 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002777 cli_cmd_flag_none,
2778 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002779 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002780 cli_cmd_flag_none,
2781 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002782 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783 cli_cmd_flag_none,
2784 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002785 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002786 cli_cmd_flag_none,
2787 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002788 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002789 cli_cmd_flag_none,
2790 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002791 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2792 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002793 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002794#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002795 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002796 "[params] = Set or unset (if none) autoscan parameters" },
2797#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002798#ifdef CONFIG_WNM
2799 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2800 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
2801#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002802 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2803 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002804 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2805 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002806#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002807 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002808 cli_cmd_flag_none,
2809 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002810#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002811 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002812};
2813
2814
2815/*
2816 * Prints command usage, lines are padded with the specified string.
2817 */
2818static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2819{
2820 char c;
2821 size_t n;
2822
2823 printf("%s%s ", pad, cmd->cmd);
2824 for (n = 0; (c = cmd->usage[n]); n++) {
2825 printf("%c", c);
2826 if (c == '\n')
2827 printf("%s", pad);
2828 }
2829 printf("\n");
2830}
2831
2832
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002833static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002834{
2835 int n;
2836 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002837 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2838 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2839 print_cmd_help(&wpa_cli_commands[n], " ");
2840 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002841}
2842
2843
2844static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2845{
2846 const char *c, *delim;
2847 int n;
2848 size_t len;
2849
2850 delim = os_strchr(cmd, ' ');
2851 if (delim)
2852 len = delim - cmd;
2853 else
2854 len = os_strlen(cmd);
2855
2856 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2857 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2858 return (wpa_cli_commands[n].flags &
2859 cli_cmd_flag_sensitive);
2860 }
2861 return 0;
2862}
2863
2864
2865static char ** wpa_list_cmd_list(void)
2866{
2867 char **res;
2868 int i, count;
2869
2870 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002871 res = os_calloc(count, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002872 if (res == NULL)
2873 return NULL;
2874
2875 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2876 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2877 if (res[i] == NULL)
2878 break;
2879 }
2880
2881 return res;
2882}
2883
2884
2885static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2886 int pos)
2887{
2888 int i;
2889
2890 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2891 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002892 if (wpa_cli_commands[i].completion)
2893 return wpa_cli_commands[i].completion(str,
2894 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002895 edit_clear_line();
2896 printf("\r%s\n", wpa_cli_commands[i].usage);
2897 edit_redraw();
2898 break;
2899 }
2900 }
2901
2902 return NULL;
2903}
2904
2905
2906static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2907{
2908 char **res;
2909 const char *end;
2910 char *cmd;
2911
2912 end = os_strchr(str, ' ');
2913 if (end == NULL || str + pos < end)
2914 return wpa_list_cmd_list();
2915
2916 cmd = os_malloc(pos + 1);
2917 if (cmd == NULL)
2918 return NULL;
2919 os_memcpy(cmd, str, pos);
2920 cmd[end - str] = '\0';
2921 res = wpa_cli_cmd_completion(cmd, str, pos);
2922 os_free(cmd);
2923 return res;
2924}
2925
2926
2927static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2928{
2929 struct wpa_cli_cmd *cmd, *match = NULL;
2930 int count;
2931 int ret = 0;
2932
2933 count = 0;
2934 cmd = wpa_cli_commands;
2935 while (cmd->cmd) {
2936 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2937 {
2938 match = cmd;
2939 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2940 /* we have an exact match */
2941 count = 1;
2942 break;
2943 }
2944 count++;
2945 }
2946 cmd++;
2947 }
2948
2949 if (count > 1) {
2950 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2951 cmd = wpa_cli_commands;
2952 while (cmd->cmd) {
2953 if (os_strncasecmp(cmd->cmd, argv[0],
2954 os_strlen(argv[0])) == 0) {
2955 printf(" %s", cmd->cmd);
2956 }
2957 cmd++;
2958 }
2959 printf("\n");
2960 ret = 1;
2961 } else if (count == 0) {
2962 printf("Unknown command '%s'\n", argv[0]);
2963 ret = 1;
2964 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07002965#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
2966 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
2967 redirect_interface = os_strdup(argv[1]);
2968 ret = match->handler(ctrl, argc - 2, &argv[2]);
2969 }
2970 else
2971#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002972 ret = match->handler(ctrl, argc - 1, &argv[1]);
2973 }
2974
2975 return ret;
2976}
2977
2978
2979static int str_match(const char *a, const char *b)
2980{
2981 return os_strncmp(a, b, os_strlen(b)) == 0;
2982}
2983
2984
2985static int wpa_cli_exec(const char *program, const char *arg1,
2986 const char *arg2)
2987{
2988 char *cmd;
2989 size_t len;
2990 int res;
2991 int ret = 0;
2992
2993 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2994 cmd = os_malloc(len);
2995 if (cmd == NULL)
2996 return -1;
2997 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2998 if (res < 0 || (size_t) res >= len) {
2999 os_free(cmd);
3000 return -1;
3001 }
3002 cmd[len - 1] = '\0';
3003#ifndef _WIN32_WCE
3004 if (system(cmd) < 0)
3005 ret = -1;
3006#endif /* _WIN32_WCE */
3007 os_free(cmd);
3008
3009 return ret;
3010}
3011
3012
3013static void wpa_cli_action_process(const char *msg)
3014{
3015 const char *pos;
3016 char *copy = NULL, *id, *pos2;
3017
3018 pos = msg;
3019 if (*pos == '<') {
3020 /* skip priority */
3021 pos = os_strchr(pos, '>');
3022 if (pos)
3023 pos++;
3024 else
3025 pos = msg;
3026 }
3027
3028 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3029 int new_id = -1;
3030 os_unsetenv("WPA_ID");
3031 os_unsetenv("WPA_ID_STR");
3032 os_unsetenv("WPA_CTRL_DIR");
3033
3034 pos = os_strstr(pos, "[id=");
3035 if (pos)
3036 copy = os_strdup(pos + 4);
3037
3038 if (copy) {
3039 pos2 = id = copy;
3040 while (*pos2 && *pos2 != ' ')
3041 pos2++;
3042 *pos2++ = '\0';
3043 new_id = atoi(id);
3044 os_setenv("WPA_ID", id, 1);
3045 while (*pos2 && *pos2 != '=')
3046 pos2++;
3047 if (*pos2 == '=')
3048 pos2++;
3049 id = pos2;
3050 while (*pos2 && *pos2 != ']')
3051 pos2++;
3052 *pos2 = '\0';
3053 os_setenv("WPA_ID_STR", id, 1);
3054 os_free(copy);
3055 }
3056
3057 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3058
3059 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3060 wpa_cli_connected = 1;
3061 wpa_cli_last_id = new_id;
3062 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3063 }
3064 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3065 if (wpa_cli_connected) {
3066 wpa_cli_connected = 0;
3067 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3068 }
3069 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3070 wpa_cli_exec(action_file, ctrl_ifname, pos);
3071 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3072 wpa_cli_exec(action_file, ctrl_ifname, pos);
3073 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3074 wpa_cli_exec(action_file, ctrl_ifname, pos);
3075 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3076 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003077 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3078 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003079 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3080 wpa_cli_exec(action_file, ctrl_ifname, pos);
3081 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3082 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003083 } else if (str_match(pos, AP_STA_CONNECTED)) {
3084 wpa_cli_exec(action_file, ctrl_ifname, pos);
3085 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3086 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003087 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3088 printf("wpa_supplicant is terminating - stop monitoring\n");
3089 wpa_cli_quit = 1;
3090 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003091}
3092
3093
3094#ifndef CONFIG_ANSI_C_EXTRA
3095static void wpa_cli_action_cb(char *msg, size_t len)
3096{
3097 wpa_cli_action_process(msg);
3098}
3099#endif /* CONFIG_ANSI_C_EXTRA */
3100
3101
3102static void wpa_cli_reconnect(void)
3103{
3104 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003105 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3106 return;
3107
3108 if (interactive) {
3109 edit_clear_line();
3110 printf("\rConnection to wpa_supplicant re-established\n");
3111 edit_redraw();
3112 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003113}
3114
3115
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003116static void cli_event(const char *str)
3117{
3118 const char *start, *s;
3119
3120 start = os_strchr(str, '>');
3121 if (start == NULL)
3122 return;
3123
3124 start++;
3125
3126 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3127 s = os_strchr(start, ' ');
3128 if (s == NULL)
3129 return;
3130 s = os_strchr(s + 1, ' ');
3131 if (s == NULL)
3132 return;
3133 cli_txt_list_add(&bsses, s + 1);
3134 return;
3135 }
3136
3137 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3138 s = os_strchr(start, ' ');
3139 if (s == NULL)
3140 return;
3141 s = os_strchr(s + 1, ' ');
3142 if (s == NULL)
3143 return;
3144 cli_txt_list_del_addr(&bsses, s + 1);
3145 return;
3146 }
3147
3148#ifdef CONFIG_P2P
3149 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3150 s = os_strstr(start, " p2p_dev_addr=");
3151 if (s == NULL)
3152 return;
3153 cli_txt_list_add_addr(&p2p_peers, s + 14);
3154 return;
3155 }
3156
3157 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3158 s = os_strstr(start, " p2p_dev_addr=");
3159 if (s == NULL)
3160 return;
3161 cli_txt_list_del_addr(&p2p_peers, s + 14);
3162 return;
3163 }
3164
3165 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3166 s = os_strchr(start, ' ');
3167 if (s == NULL)
3168 return;
3169 cli_txt_list_add_word(&p2p_groups, s + 1);
3170 return;
3171 }
3172
3173 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3174 s = os_strchr(start, ' ');
3175 if (s == NULL)
3176 return;
3177 cli_txt_list_del_word(&p2p_groups, s + 1);
3178 return;
3179 }
3180#endif /* CONFIG_P2P */
3181}
3182
3183
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003184static int check_terminating(const char *msg)
3185{
3186 const char *pos = msg;
3187
3188 if (*pos == '<') {
3189 /* skip priority */
3190 pos = os_strchr(pos, '>');
3191 if (pos)
3192 pos++;
3193 else
3194 pos = msg;
3195 }
3196
3197 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3198 edit_clear_line();
3199 printf("\rConnection to wpa_supplicant lost - trying to "
3200 "reconnect\n");
3201 edit_redraw();
3202 wpa_cli_attached = 0;
3203 wpa_cli_close_connection();
3204 return 1;
3205 }
3206
3207 return 0;
3208}
3209
3210
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003211static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3212{
3213 if (ctrl_conn == NULL) {
3214 wpa_cli_reconnect();
3215 return;
3216 }
3217 while (wpa_ctrl_pending(ctrl) > 0) {
3218 char buf[256];
3219 size_t len = sizeof(buf) - 1;
3220 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3221 buf[len] = '\0';
3222 if (action_monitor)
3223 wpa_cli_action_process(buf);
3224 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003225 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003226 if (wpa_cli_show_event(buf)) {
3227 edit_clear_line();
3228 printf("\r%s\n", buf);
3229 edit_redraw();
3230 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003231
3232 if (interactive && check_terminating(buf) > 0)
3233 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003234 }
3235 } else {
3236 printf("Could not read pending message.\n");
3237 break;
3238 }
3239 }
3240
3241 if (wpa_ctrl_pending(ctrl) < 0) {
3242 printf("Connection to wpa_supplicant lost - trying to "
3243 "reconnect\n");
3244 wpa_cli_reconnect();
3245 }
3246}
3247
3248#define max_args 10
3249
3250static int tokenize_cmd(char *cmd, char *argv[])
3251{
3252 char *pos;
3253 int argc = 0;
3254
3255 pos = cmd;
3256 for (;;) {
3257 while (*pos == ' ')
3258 pos++;
3259 if (*pos == '\0')
3260 break;
3261 argv[argc] = pos;
3262 argc++;
3263 if (argc == max_args)
3264 break;
3265 if (*pos == '"') {
3266 char *pos2 = os_strrchr(pos, '"');
3267 if (pos2)
3268 pos = pos2 + 1;
3269 }
3270 while (*pos != '\0' && *pos != ' ')
3271 pos++;
3272 if (*pos == ' ')
3273 *pos++ = '\0';
3274 }
3275
3276 return argc;
3277}
3278
3279
3280static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3281{
3282 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3283 printf("Connection to wpa_supplicant lost - trying to "
3284 "reconnect\n");
3285 wpa_cli_close_connection();
3286 }
3287 if (!ctrl_conn)
3288 wpa_cli_reconnect();
3289 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3290}
3291
3292
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003293static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3294{
3295 wpa_cli_recv_pending(mon_conn, 0);
3296}
3297
3298
3299static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3300{
3301 char *argv[max_args];
3302 int argc;
3303 argc = tokenize_cmd(cmd, argv);
3304 if (argc)
3305 wpa_request(ctrl_conn, argc, argv);
3306}
3307
3308
3309static void wpa_cli_edit_eof_cb(void *ctx)
3310{
3311 eloop_terminate();
3312}
3313
3314
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003315static int warning_displayed = 0;
3316static char *hfile = NULL;
3317static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003318
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003319static void start_edit(void)
3320{
3321 char *home;
3322 char *ps = NULL;
3323
3324#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3325 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3326#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003327
3328 home = getenv("HOME");
3329 if (home) {
3330 const char *fname = ".wpa_cli_history";
3331 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3332 hfile = os_malloc(hfile_len);
3333 if (hfile)
3334 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3335 }
3336
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003337 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3338 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3339 eloop_terminate();
3340 return;
3341 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003342
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003343 edit_started = 1;
3344 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3345}
3346
3347
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003348static void update_bssid_list(struct wpa_ctrl *ctrl)
3349{
3350 char buf[4096];
3351 size_t len = sizeof(buf);
3352 int ret;
3353 char *cmd = "BSS RANGE=ALL MASK=0x2";
3354 char *pos, *end;
3355
3356 if (ctrl == NULL)
3357 return;
3358 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3359 if (ret < 0)
3360 return;
3361 buf[len] = '\0';
3362
3363 pos = buf;
3364 while (pos) {
3365 pos = os_strstr(pos, "bssid=");
3366 if (pos == NULL)
3367 break;
3368 pos += 6;
3369 end = os_strchr(pos, '\n');
3370 if (end == NULL)
3371 break;
3372 *end = '\0';
3373 cli_txt_list_add(&bsses, pos);
3374 pos = end + 1;
3375 }
3376}
3377
3378
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003379static void try_connection(void *eloop_ctx, void *timeout_ctx)
3380{
3381 if (ctrl_ifname == NULL)
3382 ctrl_ifname = wpa_cli_get_default_ifname();
3383
3384 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3385 if (!warning_displayed) {
3386 printf("Could not connect to wpa_supplicant: "
3387 "%s - re-trying\n", ctrl_ifname);
3388 warning_displayed = 1;
3389 }
3390 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3391 return;
3392 }
3393
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003394 update_bssid_list(ctrl_conn);
3395
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003396 if (warning_displayed)
3397 printf("Connection established.\n");
3398
3399 start_edit();
3400}
3401
3402
3403static void wpa_cli_interactive(void)
3404{
3405 printf("\nInteractive mode\n\n");
3406
3407 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003408 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003409 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003410
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003411 cli_txt_list_flush(&p2p_peers);
3412 cli_txt_list_flush(&p2p_groups);
3413 cli_txt_list_flush(&bsses);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003414 if (edit_started)
3415 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003416 os_free(hfile);
3417 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3418 wpa_cli_close_connection();
3419}
3420
3421
3422static void wpa_cli_action(struct wpa_ctrl *ctrl)
3423{
3424#ifdef CONFIG_ANSI_C_EXTRA
3425 /* TODO: ANSI C version(?) */
3426 printf("Action processing not supported in ANSI C build.\n");
3427#else /* CONFIG_ANSI_C_EXTRA */
3428 fd_set rfds;
3429 int fd, res;
3430 struct timeval tv;
3431 char buf[256]; /* note: large enough to fit in unsolicited messages */
3432 size_t len;
3433
3434 fd = wpa_ctrl_get_fd(ctrl);
3435
3436 while (!wpa_cli_quit) {
3437 FD_ZERO(&rfds);
3438 FD_SET(fd, &rfds);
3439 tv.tv_sec = ping_interval;
3440 tv.tv_usec = 0;
3441 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3442 if (res < 0 && errno != EINTR) {
3443 perror("select");
3444 break;
3445 }
3446
3447 if (FD_ISSET(fd, &rfds))
3448 wpa_cli_recv_pending(ctrl, 1);
3449 else {
3450 /* verify that connection is still working */
3451 len = sizeof(buf) - 1;
3452 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3453 wpa_cli_action_cb) < 0 ||
3454 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3455 printf("wpa_supplicant did not reply to PING "
3456 "command - exiting\n");
3457 break;
3458 }
3459 }
3460 }
3461#endif /* CONFIG_ANSI_C_EXTRA */
3462}
3463
3464
3465static void wpa_cli_cleanup(void)
3466{
3467 wpa_cli_close_connection();
3468 if (pid_file)
3469 os_daemonize_terminate(pid_file);
3470
3471 os_program_deinit();
3472}
3473
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003474
3475static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003476{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003477 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003478}
3479
3480
3481static char * wpa_cli_get_default_ifname(void)
3482{
3483 char *ifname = NULL;
3484
3485#ifdef CONFIG_CTRL_IFACE_UNIX
3486 struct dirent *dent;
3487 DIR *dir = opendir(ctrl_iface_dir);
3488 if (!dir) {
3489#ifdef ANDROID
3490 char ifprop[PROPERTY_VALUE_MAX];
3491 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3492 ifname = os_strdup(ifprop);
3493 printf("Using interface '%s'\n", ifname);
3494 return ifname;
3495 }
3496#endif /* ANDROID */
3497 return NULL;
3498 }
3499 while ((dent = readdir(dir))) {
3500#ifdef _DIRENT_HAVE_D_TYPE
3501 /*
3502 * Skip the file if it is not a socket. Also accept
3503 * DT_UNKNOWN (0) in case the C library or underlying
3504 * file system does not support d_type.
3505 */
3506 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3507 continue;
3508#endif /* _DIRENT_HAVE_D_TYPE */
3509 if (os_strcmp(dent->d_name, ".") == 0 ||
3510 os_strcmp(dent->d_name, "..") == 0)
3511 continue;
3512 printf("Selected interface '%s'\n", dent->d_name);
3513 ifname = os_strdup(dent->d_name);
3514 break;
3515 }
3516 closedir(dir);
3517#endif /* CONFIG_CTRL_IFACE_UNIX */
3518
3519#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003520 char buf[2048], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003521 size_t len;
3522 struct wpa_ctrl *ctrl;
3523 int ret;
3524
3525 ctrl = wpa_ctrl_open(NULL);
3526 if (ctrl == NULL)
3527 return NULL;
3528
3529 len = sizeof(buf) - 1;
3530 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3531 if (ret >= 0) {
3532 buf[len] = '\0';
3533 pos = os_strchr(buf, '\n');
3534 if (pos)
3535 *pos = '\0';
3536 ifname = os_strdup(buf);
3537 }
3538 wpa_ctrl_close(ctrl);
3539#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3540
3541 return ifname;
3542}
3543
3544
3545int main(int argc, char *argv[])
3546{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003547 int c;
3548 int daemonize = 0;
3549 int ret = 0;
3550 const char *global = NULL;
3551
3552 if (os_program_init())
3553 return -1;
3554
3555 for (;;) {
3556 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3557 if (c < 0)
3558 break;
3559 switch (c) {
3560 case 'a':
3561 action_file = optarg;
3562 break;
3563 case 'B':
3564 daemonize = 1;
3565 break;
3566 case 'g':
3567 global = optarg;
3568 break;
3569 case 'G':
3570 ping_interval = atoi(optarg);
3571 break;
3572 case 'h':
3573 usage();
3574 return 0;
3575 case 'v':
3576 printf("%s\n", wpa_cli_version);
3577 return 0;
3578 case 'i':
3579 os_free(ctrl_ifname);
3580 ctrl_ifname = os_strdup(optarg);
3581 break;
3582 case 'p':
3583 ctrl_iface_dir = optarg;
3584 break;
3585 case 'P':
3586 pid_file = optarg;
3587 break;
3588 default:
3589 usage();
3590 return -1;
3591 }
3592 }
3593
3594 interactive = (argc == optind) && (action_file == NULL);
3595
3596 if (interactive)
3597 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3598
3599 if (eloop_init())
3600 return -1;
3601
3602 if (global) {
3603#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3604 ctrl_conn = wpa_ctrl_open(NULL);
3605#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3606 ctrl_conn = wpa_ctrl_open(global);
3607#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3608 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003609 fprintf(stderr, "Failed to connect to wpa_supplicant "
3610 "global interface: %s error: %s\n",
3611 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003612 return -1;
3613 }
3614 }
3615
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003616 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003617
3618 if (ctrl_ifname == NULL)
3619 ctrl_ifname = wpa_cli_get_default_ifname();
3620
3621 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003622 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003623 } else {
3624 if (!global &&
3625 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003626 fprintf(stderr, "Failed to connect to non-global "
3627 "ctrl_ifname: %s error: %s\n",
3628 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003629 return -1;
3630 }
3631
3632 if (action_file) {
3633 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3634 wpa_cli_attached = 1;
3635 } else {
3636 printf("Warning: Failed to attach to "
3637 "wpa_supplicant.\n");
3638 return -1;
3639 }
3640 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003641
3642 if (daemonize && os_daemonize(pid_file))
3643 return -1;
3644
3645 if (action_file)
3646 wpa_cli_action(ctrl_conn);
3647 else
3648 ret = wpa_request(ctrl_conn, argc - optind,
3649 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003650 }
3651
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003652 os_free(ctrl_ifname);
3653 eloop_destroy();
3654 wpa_cli_cleanup();
3655
3656 return ret;
3657}
3658
3659#else /* CONFIG_CTRL_IFACE */
3660int main(int argc, char *argv[])
3661{
3662 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3663 return -1;
3664}
3665#endif /* CONFIG_CTRL_IFACE */