blob: 966ee83410c7bb225cc2e34ba3b365443f34b605 [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
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002318
2319static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2320{
2321 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2322}
2323
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002324#endif /* CONFIG_WNM */
2325
2326
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002327static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2328{
2329 if (argc == 0)
2330 return -1;
2331 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2332}
2333
2334
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002335#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002336static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2337{
2338 char cmd[256];
2339 int i;
2340 int len;
2341
2342 if (argc < 1) {
2343 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2344 return -1;
2345 }
2346
2347 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2348 for (i=1; i < argc; i++)
2349 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2350 cmd[sizeof(cmd) - 1] = '\0';
2351 printf("%s: %s\n", __func__, cmd);
2352 return wpa_ctrl_command(ctrl, cmd);
2353}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002354#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002355
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002356
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002357static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2358{
2359 return wpa_ctrl_command(ctrl, "FLUSH");
2360}
2361
2362
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002363enum wpa_cli_cmd_flags {
2364 cli_cmd_flag_none = 0x00,
2365 cli_cmd_flag_sensitive = 0x01
2366};
2367
2368struct wpa_cli_cmd {
2369 const char *cmd;
2370 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002371 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002372 enum wpa_cli_cmd_flags flags;
2373 const char *usage;
2374};
2375
2376static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002377 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002378 cli_cmd_flag_none,
2379 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002380 { "ifname", wpa_cli_cmd_ifname, NULL,
2381 cli_cmd_flag_none,
2382 "= get current interface name" },
2383 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002384 cli_cmd_flag_none,
2385 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002386 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002387 cli_cmd_flag_none,
2388 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002389 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002390 cli_cmd_flag_none,
2391 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002392 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002393 cli_cmd_flag_none,
2394 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002395 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002396 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002397 "[command] = show usage help" },
2398 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002399 cli_cmd_flag_none,
2400 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002401 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002402 cli_cmd_flag_none,
2403 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002404 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002405 cli_cmd_flag_none,
2406 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002407 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002408 cli_cmd_flag_none,
2409 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002410 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002411 cli_cmd_flag_none,
2412 "= set variables (shows list of variables when run without "
2413 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002414 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002415 cli_cmd_flag_none,
2416 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002417 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002418 cli_cmd_flag_none,
2419 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002420 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002421 cli_cmd_flag_none,
2422 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002423 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002424 cli_cmd_flag_none,
2425 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002426 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002427 cli_cmd_flag_none,
2428 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002429 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002430 cli_cmd_flag_none,
2431 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002432 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 cli_cmd_flag_none,
2434 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002435 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002436 cli_cmd_flag_sensitive,
2437 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002438 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002439 cli_cmd_flag_sensitive,
2440 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002441 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002442 cli_cmd_flag_sensitive,
2443 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002444 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002445 cli_cmd_flag_sensitive,
2446 "<network id> <password> = configure one-time-password for an SSID"
2447 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002448 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002449 cli_cmd_flag_sensitive,
2450 "<network id> <passphrase> = configure private key passphrase\n"
2451 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002452 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002453 cli_cmd_flag_none,
2454 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002455 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002456 cli_cmd_flag_none,
2457 "<BSSID> = add a BSSID to the blacklist\n"
2458 "blacklist clear = clear the blacklist\n"
2459 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002460 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002461 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002462 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002463 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002464 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002465 cli_cmd_flag_none,
2466 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002467 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 cli_cmd_flag_none,
2469 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002470 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002471 cli_cmd_flag_none,
2472 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002473 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002474 cli_cmd_flag_none,
2475 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002476 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002477 cli_cmd_flag_none,
2478 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002479 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002480 cli_cmd_flag_none,
2481 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002482 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002483 cli_cmd_flag_sensitive,
2484 "<network id> <variable> <value> = set network variables (shows\n"
2485 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002486 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002487 cli_cmd_flag_none,
2488 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002489 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002490 cli_cmd_flag_none,
2491 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002492 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002493 cli_cmd_flag_none,
2494 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002495 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002496 cli_cmd_flag_none,
2497 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002498 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002499 cli_cmd_flag_sensitive,
2500 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002501 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 cli_cmd_flag_none,
2503 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002504 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002505 cli_cmd_flag_none,
2506 "= disconnect and wait for reassociate/reconnect command before\n"
2507 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002508 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002509 cli_cmd_flag_none,
2510 "= like reassociate, but only takes effect if already disconnected"
2511 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002512 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 cli_cmd_flag_none,
2514 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002515 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002516 cli_cmd_flag_none,
2517 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002518 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002519 cli_cmd_flag_none,
2520 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002521 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002522 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002523 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002524 "= get capabilies" },
2525 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 cli_cmd_flag_none,
2527 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002528 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002529 cli_cmd_flag_none,
2530 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002531 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002532 cli_cmd_flag_none,
2533 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2534 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2535 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002536 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002537 cli_cmd_flag_none,
2538 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002539 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002540 cli_cmd_flag_none,
2541 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002542 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002543 cli_cmd_flag_none,
2544 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002545 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002546 cli_cmd_flag_none,
2547 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002548 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002549 cli_cmd_flag_none,
2550 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002551 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002552 cli_cmd_flag_none,
2553 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002554 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002555 cli_cmd_flag_none,
2556 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002557 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558 cli_cmd_flag_none,
2559 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002560 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561 cli_cmd_flag_none,
2562 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002563 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002564 cli_cmd_flag_none,
2565 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002566 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567 cli_cmd_flag_sensitive,
2568 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2569 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002570 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002571 cli_cmd_flag_sensitive,
2572 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002573 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002574 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002575#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002576 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002577 cli_cmd_flag_none,
2578 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002579 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2580 cli_cmd_flag_none,
2581 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002582 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002583 cli_cmd_flag_none,
2584 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002585 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002586 cli_cmd_flag_sensitive,
2587 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002588 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2589 cli_cmd_flag_none,
2590 "<NDEF> <WPS> = create NFC handover request" },
2591 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2592 cli_cmd_flag_none,
2593 "<NDEF> <WPS> = create NFC handover select" },
2594 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2595 cli_cmd_flag_none,
2596 "<hexdump of payload> = report received NFC handover request" },
2597 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2598 cli_cmd_flag_none,
2599 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002600 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2601 cli_cmd_flag_none,
2602 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2603 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002604#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002605 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002606 cli_cmd_flag_sensitive,
2607 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002608 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 cli_cmd_flag_sensitive,
2610 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002611 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002612 cli_cmd_flag_none,
2613 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002614 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002615 cli_cmd_flag_none,
2616 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002617 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002618 cli_cmd_flag_sensitive,
2619 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002620 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002621 cli_cmd_flag_none,
2622 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002623 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 cli_cmd_flag_sensitive,
2625 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002626 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002627 cli_cmd_flag_none,
2628 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002629 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002630 cli_cmd_flag_sensitive,
2631 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002632#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002633 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002634 cli_cmd_flag_none,
2635 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2636#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002637 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638 cli_cmd_flag_none,
2639 "<addr> = request RSN authentication with <addr> in IBSS" },
2640#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002641 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002642 cli_cmd_flag_none,
2643 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002644 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 cli_cmd_flag_none,
2646 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002647 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002648 cli_cmd_flag_none,
2649 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002650 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002651 cli_cmd_flag_none,
2652 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002653#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002654 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002655 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002656 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002657 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002658 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002659 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002660 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 cli_cmd_flag_none,
2662 "<addr> = roam to the specified BSS" },
2663#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002664 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2665 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002666 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002667 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002668 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002669 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2670 cli_cmd_flag_none,
2671 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2672 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002673 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002674 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2675 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002676 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002677 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2678 "[ht40] = add a new P2P group (local end as GO)" },
2679 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2680 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002681 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002682 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002683 cli_cmd_flag_none,
2684 "= get the passphrase for a group (GO only)" },
2685 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002686 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002687 "<addr> <TLVs> = schedule service discovery request" },
2688 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002689 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002690 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002691 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002692 cli_cmd_flag_none,
2693 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002694 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002695 cli_cmd_flag_none,
2696 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002697 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698 cli_cmd_flag_none,
2699 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002700 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002701 cli_cmd_flag_none,
2702 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002703 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002704 cli_cmd_flag_none,
2705 "<bonjour|upnp> <query|version> <response|service> = add a local "
2706 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002707 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002708 cli_cmd_flag_none,
2709 "<bonjour|upnp> <query|version> [|service] = remove a local "
2710 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002711 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002712 cli_cmd_flag_none,
2713 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002714 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002715 cli_cmd_flag_none,
2716 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002717 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002718 "[discovered] = list known (optionally, only fully discovered) P2P "
2719 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002720 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2721 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722 "<address> = show information about known P2P peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002723 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002724 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002725 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002726 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002727 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002728 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002729 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2730 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002731 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002732 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2733 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002734 "[<duration> <interval>] [<duration> <interval>] = request GO "
2735 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002736 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2737 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002738 "[<period> <interval>] = set extended listen timing" },
2739#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002740#ifdef CONFIG_WIFI_DISPLAY
2741 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2742 cli_cmd_flag_none,
2743 "<subelem> [contents] = set Wi-Fi Display subelement" },
2744 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2745 cli_cmd_flag_none,
2746 "<subelem> = get Wi-Fi Display subelement" },
2747#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002748#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002749 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002750 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002751 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2752 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002753 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002754 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002755 cli_cmd_flag_none,
2756 "[auto] = perform Interworking network selection" },
2757 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002758 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002759 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002760 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2761 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002762 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002763 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2764 cli_cmd_flag_none,
2765 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2766 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2767 wpa_cli_complete_bss, cli_cmd_flag_none,
2768 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002769#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002770#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002771 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2772 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002773 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2774 },
2775 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002776 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002777 "<addr> <home realm> = get HS20 nai home realm list" },
2778#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002779 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2780 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002781 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002782 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783 cli_cmd_flag_none,
2784 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002785 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002786 cli_cmd_flag_none,
2787 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002788 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002789 cli_cmd_flag_none,
2790 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002791 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002792 cli_cmd_flag_none,
2793 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002794 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002795 cli_cmd_flag_none,
2796 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002797 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2798 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002799 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002800#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002801 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002802 "[params] = Set or unset (if none) autoscan parameters" },
2803#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002804#ifdef CONFIG_WNM
2805 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2806 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002807 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2808 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002809#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002810 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2811 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002812 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2813 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002814#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002815 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002816 cli_cmd_flag_none,
2817 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002818#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002819 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002820};
2821
2822
2823/*
2824 * Prints command usage, lines are padded with the specified string.
2825 */
2826static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2827{
2828 char c;
2829 size_t n;
2830
2831 printf("%s%s ", pad, cmd->cmd);
2832 for (n = 0; (c = cmd->usage[n]); n++) {
2833 printf("%c", c);
2834 if (c == '\n')
2835 printf("%s", pad);
2836 }
2837 printf("\n");
2838}
2839
2840
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002841static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002842{
2843 int n;
2844 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002845 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2846 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2847 print_cmd_help(&wpa_cli_commands[n], " ");
2848 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002849}
2850
2851
2852static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2853{
2854 const char *c, *delim;
2855 int n;
2856 size_t len;
2857
2858 delim = os_strchr(cmd, ' ');
2859 if (delim)
2860 len = delim - cmd;
2861 else
2862 len = os_strlen(cmd);
2863
2864 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2865 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2866 return (wpa_cli_commands[n].flags &
2867 cli_cmd_flag_sensitive);
2868 }
2869 return 0;
2870}
2871
2872
2873static char ** wpa_list_cmd_list(void)
2874{
2875 char **res;
2876 int i, count;
2877
2878 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002879 res = os_calloc(count, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002880 if (res == NULL)
2881 return NULL;
2882
2883 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2884 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2885 if (res[i] == NULL)
2886 break;
2887 }
2888
2889 return res;
2890}
2891
2892
2893static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2894 int pos)
2895{
2896 int i;
2897
2898 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2899 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002900 if (wpa_cli_commands[i].completion)
2901 return wpa_cli_commands[i].completion(str,
2902 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002903 edit_clear_line();
2904 printf("\r%s\n", wpa_cli_commands[i].usage);
2905 edit_redraw();
2906 break;
2907 }
2908 }
2909
2910 return NULL;
2911}
2912
2913
2914static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2915{
2916 char **res;
2917 const char *end;
2918 char *cmd;
2919
2920 end = os_strchr(str, ' ');
2921 if (end == NULL || str + pos < end)
2922 return wpa_list_cmd_list();
2923
2924 cmd = os_malloc(pos + 1);
2925 if (cmd == NULL)
2926 return NULL;
2927 os_memcpy(cmd, str, pos);
2928 cmd[end - str] = '\0';
2929 res = wpa_cli_cmd_completion(cmd, str, pos);
2930 os_free(cmd);
2931 return res;
2932}
2933
2934
2935static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2936{
2937 struct wpa_cli_cmd *cmd, *match = NULL;
2938 int count;
2939 int ret = 0;
2940
2941 count = 0;
2942 cmd = wpa_cli_commands;
2943 while (cmd->cmd) {
2944 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2945 {
2946 match = cmd;
2947 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2948 /* we have an exact match */
2949 count = 1;
2950 break;
2951 }
2952 count++;
2953 }
2954 cmd++;
2955 }
2956
2957 if (count > 1) {
2958 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2959 cmd = wpa_cli_commands;
2960 while (cmd->cmd) {
2961 if (os_strncasecmp(cmd->cmd, argv[0],
2962 os_strlen(argv[0])) == 0) {
2963 printf(" %s", cmd->cmd);
2964 }
2965 cmd++;
2966 }
2967 printf("\n");
2968 ret = 1;
2969 } else if (count == 0) {
2970 printf("Unknown command '%s'\n", argv[0]);
2971 ret = 1;
2972 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07002973#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
2974 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
2975 redirect_interface = os_strdup(argv[1]);
2976 ret = match->handler(ctrl, argc - 2, &argv[2]);
2977 }
2978 else
2979#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002980 ret = match->handler(ctrl, argc - 1, &argv[1]);
2981 }
2982
2983 return ret;
2984}
2985
2986
2987static int str_match(const char *a, const char *b)
2988{
2989 return os_strncmp(a, b, os_strlen(b)) == 0;
2990}
2991
2992
2993static int wpa_cli_exec(const char *program, const char *arg1,
2994 const char *arg2)
2995{
2996 char *cmd;
2997 size_t len;
2998 int res;
2999 int ret = 0;
3000
3001 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3002 cmd = os_malloc(len);
3003 if (cmd == NULL)
3004 return -1;
3005 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3006 if (res < 0 || (size_t) res >= len) {
3007 os_free(cmd);
3008 return -1;
3009 }
3010 cmd[len - 1] = '\0';
3011#ifndef _WIN32_WCE
3012 if (system(cmd) < 0)
3013 ret = -1;
3014#endif /* _WIN32_WCE */
3015 os_free(cmd);
3016
3017 return ret;
3018}
3019
3020
3021static void wpa_cli_action_process(const char *msg)
3022{
3023 const char *pos;
3024 char *copy = NULL, *id, *pos2;
3025
3026 pos = msg;
3027 if (*pos == '<') {
3028 /* skip priority */
3029 pos = os_strchr(pos, '>');
3030 if (pos)
3031 pos++;
3032 else
3033 pos = msg;
3034 }
3035
3036 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3037 int new_id = -1;
3038 os_unsetenv("WPA_ID");
3039 os_unsetenv("WPA_ID_STR");
3040 os_unsetenv("WPA_CTRL_DIR");
3041
3042 pos = os_strstr(pos, "[id=");
3043 if (pos)
3044 copy = os_strdup(pos + 4);
3045
3046 if (copy) {
3047 pos2 = id = copy;
3048 while (*pos2 && *pos2 != ' ')
3049 pos2++;
3050 *pos2++ = '\0';
3051 new_id = atoi(id);
3052 os_setenv("WPA_ID", id, 1);
3053 while (*pos2 && *pos2 != '=')
3054 pos2++;
3055 if (*pos2 == '=')
3056 pos2++;
3057 id = pos2;
3058 while (*pos2 && *pos2 != ']')
3059 pos2++;
3060 *pos2 = '\0';
3061 os_setenv("WPA_ID_STR", id, 1);
3062 os_free(copy);
3063 }
3064
3065 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3066
3067 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3068 wpa_cli_connected = 1;
3069 wpa_cli_last_id = new_id;
3070 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3071 }
3072 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3073 if (wpa_cli_connected) {
3074 wpa_cli_connected = 0;
3075 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3076 }
3077 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3078 wpa_cli_exec(action_file, ctrl_ifname, pos);
3079 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3080 wpa_cli_exec(action_file, ctrl_ifname, pos);
3081 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3082 wpa_cli_exec(action_file, ctrl_ifname, pos);
3083 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3084 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003085 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3086 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003087 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3088 wpa_cli_exec(action_file, ctrl_ifname, pos);
3089 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3090 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003091 } else if (str_match(pos, AP_STA_CONNECTED)) {
3092 wpa_cli_exec(action_file, ctrl_ifname, pos);
3093 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3094 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003095 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3096 printf("wpa_supplicant is terminating - stop monitoring\n");
3097 wpa_cli_quit = 1;
3098 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003099}
3100
3101
3102#ifndef CONFIG_ANSI_C_EXTRA
3103static void wpa_cli_action_cb(char *msg, size_t len)
3104{
3105 wpa_cli_action_process(msg);
3106}
3107#endif /* CONFIG_ANSI_C_EXTRA */
3108
3109
3110static void wpa_cli_reconnect(void)
3111{
3112 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003113 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3114 return;
3115
3116 if (interactive) {
3117 edit_clear_line();
3118 printf("\rConnection to wpa_supplicant re-established\n");
3119 edit_redraw();
3120 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003121}
3122
3123
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003124static void cli_event(const char *str)
3125{
3126 const char *start, *s;
3127
3128 start = os_strchr(str, '>');
3129 if (start == NULL)
3130 return;
3131
3132 start++;
3133
3134 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3135 s = os_strchr(start, ' ');
3136 if (s == NULL)
3137 return;
3138 s = os_strchr(s + 1, ' ');
3139 if (s == NULL)
3140 return;
3141 cli_txt_list_add(&bsses, s + 1);
3142 return;
3143 }
3144
3145 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3146 s = os_strchr(start, ' ');
3147 if (s == NULL)
3148 return;
3149 s = os_strchr(s + 1, ' ');
3150 if (s == NULL)
3151 return;
3152 cli_txt_list_del_addr(&bsses, s + 1);
3153 return;
3154 }
3155
3156#ifdef CONFIG_P2P
3157 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3158 s = os_strstr(start, " p2p_dev_addr=");
3159 if (s == NULL)
3160 return;
3161 cli_txt_list_add_addr(&p2p_peers, s + 14);
3162 return;
3163 }
3164
3165 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3166 s = os_strstr(start, " p2p_dev_addr=");
3167 if (s == NULL)
3168 return;
3169 cli_txt_list_del_addr(&p2p_peers, s + 14);
3170 return;
3171 }
3172
3173 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3174 s = os_strchr(start, ' ');
3175 if (s == NULL)
3176 return;
3177 cli_txt_list_add_word(&p2p_groups, s + 1);
3178 return;
3179 }
3180
3181 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3182 s = os_strchr(start, ' ');
3183 if (s == NULL)
3184 return;
3185 cli_txt_list_del_word(&p2p_groups, s + 1);
3186 return;
3187 }
3188#endif /* CONFIG_P2P */
3189}
3190
3191
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003192static int check_terminating(const char *msg)
3193{
3194 const char *pos = msg;
3195
3196 if (*pos == '<') {
3197 /* skip priority */
3198 pos = os_strchr(pos, '>');
3199 if (pos)
3200 pos++;
3201 else
3202 pos = msg;
3203 }
3204
3205 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3206 edit_clear_line();
3207 printf("\rConnection to wpa_supplicant lost - trying to "
3208 "reconnect\n");
3209 edit_redraw();
3210 wpa_cli_attached = 0;
3211 wpa_cli_close_connection();
3212 return 1;
3213 }
3214
3215 return 0;
3216}
3217
3218
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003219static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3220{
3221 if (ctrl_conn == NULL) {
3222 wpa_cli_reconnect();
3223 return;
3224 }
3225 while (wpa_ctrl_pending(ctrl) > 0) {
3226 char buf[256];
3227 size_t len = sizeof(buf) - 1;
3228 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3229 buf[len] = '\0';
3230 if (action_monitor)
3231 wpa_cli_action_process(buf);
3232 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003233 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003234 if (wpa_cli_show_event(buf)) {
3235 edit_clear_line();
3236 printf("\r%s\n", buf);
3237 edit_redraw();
3238 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003239
3240 if (interactive && check_terminating(buf) > 0)
3241 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003242 }
3243 } else {
3244 printf("Could not read pending message.\n");
3245 break;
3246 }
3247 }
3248
3249 if (wpa_ctrl_pending(ctrl) < 0) {
3250 printf("Connection to wpa_supplicant lost - trying to "
3251 "reconnect\n");
3252 wpa_cli_reconnect();
3253 }
3254}
3255
3256#define max_args 10
3257
3258static int tokenize_cmd(char *cmd, char *argv[])
3259{
3260 char *pos;
3261 int argc = 0;
3262
3263 pos = cmd;
3264 for (;;) {
3265 while (*pos == ' ')
3266 pos++;
3267 if (*pos == '\0')
3268 break;
3269 argv[argc] = pos;
3270 argc++;
3271 if (argc == max_args)
3272 break;
3273 if (*pos == '"') {
3274 char *pos2 = os_strrchr(pos, '"');
3275 if (pos2)
3276 pos = pos2 + 1;
3277 }
3278 while (*pos != '\0' && *pos != ' ')
3279 pos++;
3280 if (*pos == ' ')
3281 *pos++ = '\0';
3282 }
3283
3284 return argc;
3285}
3286
3287
3288static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3289{
3290 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3291 printf("Connection to wpa_supplicant lost - trying to "
3292 "reconnect\n");
3293 wpa_cli_close_connection();
3294 }
3295 if (!ctrl_conn)
3296 wpa_cli_reconnect();
3297 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3298}
3299
3300
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003301static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3302{
3303 wpa_cli_recv_pending(mon_conn, 0);
3304}
3305
3306
3307static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3308{
3309 char *argv[max_args];
3310 int argc;
3311 argc = tokenize_cmd(cmd, argv);
3312 if (argc)
3313 wpa_request(ctrl_conn, argc, argv);
3314}
3315
3316
3317static void wpa_cli_edit_eof_cb(void *ctx)
3318{
3319 eloop_terminate();
3320}
3321
3322
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003323static int warning_displayed = 0;
3324static char *hfile = NULL;
3325static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003326
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003327static void start_edit(void)
3328{
3329 char *home;
3330 char *ps = NULL;
3331
3332#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3333 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3334#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003335
3336 home = getenv("HOME");
3337 if (home) {
3338 const char *fname = ".wpa_cli_history";
3339 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3340 hfile = os_malloc(hfile_len);
3341 if (hfile)
3342 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3343 }
3344
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003345 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3346 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3347 eloop_terminate();
3348 return;
3349 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003350
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003351 edit_started = 1;
3352 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3353}
3354
3355
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003356static void update_bssid_list(struct wpa_ctrl *ctrl)
3357{
3358 char buf[4096];
3359 size_t len = sizeof(buf);
3360 int ret;
3361 char *cmd = "BSS RANGE=ALL MASK=0x2";
3362 char *pos, *end;
3363
3364 if (ctrl == NULL)
3365 return;
3366 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3367 if (ret < 0)
3368 return;
3369 buf[len] = '\0';
3370
3371 pos = buf;
3372 while (pos) {
3373 pos = os_strstr(pos, "bssid=");
3374 if (pos == NULL)
3375 break;
3376 pos += 6;
3377 end = os_strchr(pos, '\n');
3378 if (end == NULL)
3379 break;
3380 *end = '\0';
3381 cli_txt_list_add(&bsses, pos);
3382 pos = end + 1;
3383 }
3384}
3385
3386
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003387static void try_connection(void *eloop_ctx, void *timeout_ctx)
3388{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003389 if (ctrl_conn)
3390 goto done;
3391
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003392 if (ctrl_ifname == NULL)
3393 ctrl_ifname = wpa_cli_get_default_ifname();
3394
3395 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3396 if (!warning_displayed) {
3397 printf("Could not connect to wpa_supplicant: "
3398 "%s - re-trying\n", ctrl_ifname);
3399 warning_displayed = 1;
3400 }
3401 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3402 return;
3403 }
3404
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003405 update_bssid_list(ctrl_conn);
3406
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003407 if (warning_displayed)
3408 printf("Connection established.\n");
3409
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003410done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003411 start_edit();
3412}
3413
3414
3415static void wpa_cli_interactive(void)
3416{
3417 printf("\nInteractive mode\n\n");
3418
3419 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003420 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003421 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003422
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003423 cli_txt_list_flush(&p2p_peers);
3424 cli_txt_list_flush(&p2p_groups);
3425 cli_txt_list_flush(&bsses);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003426 if (edit_started)
3427 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003428 os_free(hfile);
3429 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3430 wpa_cli_close_connection();
3431}
3432
3433
3434static void wpa_cli_action(struct wpa_ctrl *ctrl)
3435{
3436#ifdef CONFIG_ANSI_C_EXTRA
3437 /* TODO: ANSI C version(?) */
3438 printf("Action processing not supported in ANSI C build.\n");
3439#else /* CONFIG_ANSI_C_EXTRA */
3440 fd_set rfds;
3441 int fd, res;
3442 struct timeval tv;
3443 char buf[256]; /* note: large enough to fit in unsolicited messages */
3444 size_t len;
3445
3446 fd = wpa_ctrl_get_fd(ctrl);
3447
3448 while (!wpa_cli_quit) {
3449 FD_ZERO(&rfds);
3450 FD_SET(fd, &rfds);
3451 tv.tv_sec = ping_interval;
3452 tv.tv_usec = 0;
3453 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3454 if (res < 0 && errno != EINTR) {
3455 perror("select");
3456 break;
3457 }
3458
3459 if (FD_ISSET(fd, &rfds))
3460 wpa_cli_recv_pending(ctrl, 1);
3461 else {
3462 /* verify that connection is still working */
3463 len = sizeof(buf) - 1;
3464 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3465 wpa_cli_action_cb) < 0 ||
3466 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3467 printf("wpa_supplicant did not reply to PING "
3468 "command - exiting\n");
3469 break;
3470 }
3471 }
3472 }
3473#endif /* CONFIG_ANSI_C_EXTRA */
3474}
3475
3476
3477static void wpa_cli_cleanup(void)
3478{
3479 wpa_cli_close_connection();
3480 if (pid_file)
3481 os_daemonize_terminate(pid_file);
3482
3483 os_program_deinit();
3484}
3485
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003486
3487static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003488{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003489 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003490}
3491
3492
3493static char * wpa_cli_get_default_ifname(void)
3494{
3495 char *ifname = NULL;
3496
3497#ifdef CONFIG_CTRL_IFACE_UNIX
3498 struct dirent *dent;
3499 DIR *dir = opendir(ctrl_iface_dir);
3500 if (!dir) {
3501#ifdef ANDROID
3502 char ifprop[PROPERTY_VALUE_MAX];
3503 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3504 ifname = os_strdup(ifprop);
3505 printf("Using interface '%s'\n", ifname);
3506 return ifname;
3507 }
3508#endif /* ANDROID */
3509 return NULL;
3510 }
3511 while ((dent = readdir(dir))) {
3512#ifdef _DIRENT_HAVE_D_TYPE
3513 /*
3514 * Skip the file if it is not a socket. Also accept
3515 * DT_UNKNOWN (0) in case the C library or underlying
3516 * file system does not support d_type.
3517 */
3518 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3519 continue;
3520#endif /* _DIRENT_HAVE_D_TYPE */
3521 if (os_strcmp(dent->d_name, ".") == 0 ||
3522 os_strcmp(dent->d_name, "..") == 0)
3523 continue;
3524 printf("Selected interface '%s'\n", dent->d_name);
3525 ifname = os_strdup(dent->d_name);
3526 break;
3527 }
3528 closedir(dir);
3529#endif /* CONFIG_CTRL_IFACE_UNIX */
3530
3531#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003532 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003533 size_t len;
3534 struct wpa_ctrl *ctrl;
3535 int ret;
3536
3537 ctrl = wpa_ctrl_open(NULL);
3538 if (ctrl == NULL)
3539 return NULL;
3540
3541 len = sizeof(buf) - 1;
3542 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3543 if (ret >= 0) {
3544 buf[len] = '\0';
3545 pos = os_strchr(buf, '\n');
3546 if (pos)
3547 *pos = '\0';
3548 ifname = os_strdup(buf);
3549 }
3550 wpa_ctrl_close(ctrl);
3551#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3552
3553 return ifname;
3554}
3555
3556
3557int main(int argc, char *argv[])
3558{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003559 int c;
3560 int daemonize = 0;
3561 int ret = 0;
3562 const char *global = NULL;
3563
3564 if (os_program_init())
3565 return -1;
3566
3567 for (;;) {
3568 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3569 if (c < 0)
3570 break;
3571 switch (c) {
3572 case 'a':
3573 action_file = optarg;
3574 break;
3575 case 'B':
3576 daemonize = 1;
3577 break;
3578 case 'g':
3579 global = optarg;
3580 break;
3581 case 'G':
3582 ping_interval = atoi(optarg);
3583 break;
3584 case 'h':
3585 usage();
3586 return 0;
3587 case 'v':
3588 printf("%s\n", wpa_cli_version);
3589 return 0;
3590 case 'i':
3591 os_free(ctrl_ifname);
3592 ctrl_ifname = os_strdup(optarg);
3593 break;
3594 case 'p':
3595 ctrl_iface_dir = optarg;
3596 break;
3597 case 'P':
3598 pid_file = optarg;
3599 break;
3600 default:
3601 usage();
3602 return -1;
3603 }
3604 }
3605
3606 interactive = (argc == optind) && (action_file == NULL);
3607
3608 if (interactive)
3609 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3610
3611 if (eloop_init())
3612 return -1;
3613
3614 if (global) {
3615#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3616 ctrl_conn = wpa_ctrl_open(NULL);
3617#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3618 ctrl_conn = wpa_ctrl_open(global);
3619#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3620 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003621 fprintf(stderr, "Failed to connect to wpa_supplicant "
3622 "global interface: %s error: %s\n",
3623 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003624 return -1;
3625 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003626
3627 if (interactive) {
3628 mon_conn = wpa_ctrl_open(global);
3629 if (mon_conn) {
3630 if (wpa_ctrl_attach(mon_conn) == 0) {
3631 wpa_cli_attached = 1;
3632 eloop_register_read_sock(
3633 wpa_ctrl_get_fd(mon_conn),
3634 wpa_cli_mon_receive,
3635 NULL, NULL);
3636 } else {
3637 printf("Failed to open monitor "
3638 "connection through global "
3639 "control interface\n");
3640 }
3641 }
3642 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003643 }
3644
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003645 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003646
3647 if (ctrl_ifname == NULL)
3648 ctrl_ifname = wpa_cli_get_default_ifname();
3649
3650 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003651 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003652 } else {
3653 if (!global &&
3654 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003655 fprintf(stderr, "Failed to connect to non-global "
3656 "ctrl_ifname: %s error: %s\n",
3657 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003658 return -1;
3659 }
3660
3661 if (action_file) {
3662 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3663 wpa_cli_attached = 1;
3664 } else {
3665 printf("Warning: Failed to attach to "
3666 "wpa_supplicant.\n");
3667 return -1;
3668 }
3669 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003670
3671 if (daemonize && os_daemonize(pid_file))
3672 return -1;
3673
3674 if (action_file)
3675 wpa_cli_action(ctrl_conn);
3676 else
3677 ret = wpa_request(ctrl_conn, argc - optind,
3678 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003679 }
3680
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003681 os_free(ctrl_ifname);
3682 eloop_destroy();
3683 wpa_cli_cleanup();
3684
3685 return ret;
3686}
3687
3688#else /* CONFIG_CTRL_IFACE */
3689int main(int argc, char *argv[])
3690{
3691 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3692 return -1;
3693}
3694#endif /* CONFIG_CTRL_IFACE */