blob: 3986b9be02325b4668ac6df4ef613f8a67a8a632 [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 Shmidtc5ec7f52012-03-06 16:33:24 -080031"Copyright (c) 2004-2012, 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);
179 buf = os_malloc(end - txt + 1);
180 if (buf == NULL)
181 return;
182 os_memcpy(buf, txt, end - txt);
183 buf[end - txt] = '\0';
184 cli_txt_list_del(txt_list, buf);
185 os_free(buf);
186}
187#endif /* CONFIG_P2P */
188
189
190static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
191{
192 struct cli_txt_entry *e;
193 e = cli_txt_list_get(txt_list, txt);
194 if (e)
195 return 0;
196 e = os_zalloc(sizeof(*e));
197 if (e == NULL)
198 return -1;
199 e->txt = os_strdup(txt);
200 if (e->txt == NULL) {
201 os_free(e);
202 return -1;
203 }
204 dl_list_add(txt_list, &e->list);
205 return 0;
206}
207
208
209#ifdef CONFIG_P2P
210static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
211{
212 u8 addr[ETH_ALEN];
213 char buf[18];
214 if (hwaddr_aton(txt, addr) < 0)
215 return -1;
216 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
217 return cli_txt_list_add(txt_list, buf);
218}
219
220
221static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
222{
223 const char *end;
224 char *buf;
225 int ret;
226 end = os_strchr(txt, ' ');
227 if (end == NULL)
228 end = txt + os_strlen(txt);
229 buf = os_malloc(end - txt + 1);
230 if (buf == NULL)
231 return -1;
232 os_memcpy(buf, txt, end - txt);
233 buf[end - txt] = '\0';
234 ret = cli_txt_list_add(txt_list, buf);
235 os_free(buf);
236 return ret;
237}
238#endif /* CONFIG_P2P */
239
240
241static char ** cli_txt_list_array(struct dl_list *txt_list)
242{
243 unsigned int i, count = dl_list_len(txt_list);
244 char **res;
245 struct cli_txt_entry *e;
246
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700247 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800248 if (res == NULL)
249 return NULL;
250
251 i = 0;
252 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
253 res[i] = os_strdup(e->txt);
254 if (res[i] == NULL)
255 break;
256 i++;
257 }
258
259 return res;
260}
261
262
263static int get_cmd_arg_num(const char *str, int pos)
264{
265 int arg = 0, i;
266
267 for (i = 0; i <= pos; i++) {
268 if (str[i] != ' ') {
269 arg++;
270 while (i <= pos && str[i] != ' ')
271 i++;
272 }
273 }
274
275 if (arg > 0)
276 arg--;
277 return arg;
278}
279
280
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700281static int str_starts(const char *src, const char *match)
282{
283 return os_strncmp(src, match, os_strlen(match)) == 0;
284}
285
286
287static int wpa_cli_show_event(const char *event)
288{
289 const char *start;
290
291 start = os_strchr(event, '>');
292 if (start == NULL)
293 return 1;
294
295 start++;
296 /*
297 * Skip BSS added/removed events since they can be relatively frequent
298 * and are likely of not much use for an interactive user.
299 */
300 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
301 str_starts(start, WPA_EVENT_BSS_REMOVED))
302 return 0;
303
304 return 1;
305}
306
307
308static int wpa_cli_open_connection(const char *ifname, int attach)
309{
310#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
311 ctrl_conn = wpa_ctrl_open(ifname);
312 if (ctrl_conn == NULL)
313 return -1;
314
315 if (attach && interactive)
316 mon_conn = wpa_ctrl_open(ifname);
317 else
318 mon_conn = NULL;
319#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
320 char *cfile = NULL;
321 int flen, res;
322
323 if (ifname == NULL)
324 return -1;
325
326#ifdef ANDROID
327 if (access(ctrl_iface_dir, F_OK) < 0) {
328 cfile = os_strdup(ifname);
329 if (cfile == NULL)
330 return -1;
331 }
332#endif /* ANDROID */
333
334 if (cfile == NULL) {
335 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
336 cfile = os_malloc(flen);
337 if (cfile == NULL)
338 return -1;
339 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
340 ifname);
341 if (res < 0 || res >= flen) {
342 os_free(cfile);
343 return -1;
344 }
345 }
346
347 ctrl_conn = wpa_ctrl_open(cfile);
348 if (ctrl_conn == NULL) {
349 os_free(cfile);
350 return -1;
351 }
352
353 if (attach && interactive)
354 mon_conn = wpa_ctrl_open(cfile);
355 else
356 mon_conn = NULL;
357 os_free(cfile);
358#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
359
360 if (mon_conn) {
361 if (wpa_ctrl_attach(mon_conn) == 0) {
362 wpa_cli_attached = 1;
363 if (interactive)
364 eloop_register_read_sock(
365 wpa_ctrl_get_fd(mon_conn),
366 wpa_cli_mon_receive, NULL, NULL);
367 } else {
368 printf("Warning: Failed to attach to "
369 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700370 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700371 return -1;
372 }
373 }
374
375 return 0;
376}
377
378
379static void wpa_cli_close_connection(void)
380{
381 if (ctrl_conn == NULL)
382 return;
383
384 if (wpa_cli_attached) {
385 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
386 wpa_cli_attached = 0;
387 }
388 wpa_ctrl_close(ctrl_conn);
389 ctrl_conn = NULL;
390 if (mon_conn) {
391 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
392 wpa_ctrl_close(mon_conn);
393 mon_conn = NULL;
394 }
395}
396
397
398static void wpa_cli_msg_cb(char *msg, size_t len)
399{
400 printf("%s\n", msg);
401}
402
403
404static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
405{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800406#ifdef ANDROID
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700407 char buf[4096];
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800408#else
409 char buf[2048];
410#endif
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -0700411#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
412 char _cmd[256];
413#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700414 size_t len;
415 int ret;
416
417 if (ctrl_conn == NULL) {
418 printf("Not connected to wpa_supplicant - command dropped.\n");
419 return -1;
420 }
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -0700421#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
422 if (redirect_interface) {
423 char *arg;
424 arg = os_strchr(cmd, ' ');
425 if (arg) {
426 *arg++ = '\0';
427 ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s %s", cmd, redirect_interface, arg);
428 }
429 else {
430 ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s", cmd, redirect_interface);
431 }
432 cmd = _cmd;
433 os_free(redirect_interface);
434 redirect_interface = NULL;
435 }
436#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700437 len = sizeof(buf) - 1;
438 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
439 wpa_cli_msg_cb);
440 if (ret == -2) {
441 printf("'%s' command timed out.\n", cmd);
442 return -2;
443 } else if (ret < 0) {
444 printf("'%s' command failed.\n", cmd);
445 return -1;
446 }
447 if (print) {
448 buf[len] = '\0';
449 printf("%s", buf);
450 if (interactive && len > 0 && buf[len - 1] != '\n')
451 printf("\n");
452 }
453 return 0;
454}
455
456
457static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
458{
459 return _wpa_ctrl_command(ctrl, cmd, 1);
460}
461
462
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700463static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
464 char *argv[])
465{
466 int i, res;
467 char *pos, *end;
468
469 pos = buf;
470 end = buf + buflen;
471
472 res = os_snprintf(pos, end - pos, "%s", cmd);
473 if (res < 0 || res >= end - pos)
474 goto fail;
475 pos += res;
476
477 for (i = 0; i < argc; i++) {
478 res = os_snprintf(pos, end - pos, " %s", argv[i]);
479 if (res < 0 || res >= end - pos)
480 goto fail;
481 pos += res;
482 }
483
484 buf[buflen - 1] = '\0';
485 return 0;
486
487fail:
488 printf("Too long command\n");
489 return -1;
490}
491
492
493static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
494 int argc, char *argv[])
495{
496 char buf[256];
497 if (argc < min_args) {
498 printf("Invalid %s command - at least %d argument%s "
499 "required.\n", cmd, min_args,
500 min_args > 1 ? "s are" : " is");
501 return -1;
502 }
503 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
504 return -1;
505 return wpa_ctrl_command(ctrl, buf);
506}
507
508
509static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
510{
511 return wpa_ctrl_command(ctrl, "IFNAME");
512}
513
514
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
516{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800517 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
518 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
519 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
520 return wpa_ctrl_command(ctrl, "STATUS-WPS");
521 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700522}
523
524
525static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
526{
527 return wpa_ctrl_command(ctrl, "PING");
528}
529
530
531static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
532{
533 return wpa_ctrl_command(ctrl, "RELOG");
534}
535
536
537static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
538{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700539 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700540}
541
542
543static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
544{
545 return wpa_ctrl_command(ctrl, "MIB");
546}
547
548
549static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
550{
551 return wpa_ctrl_command(ctrl, "PMKSA");
552}
553
554
555static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
556{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700557 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700558 return 0;
559}
560
561
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700562static char ** wpa_cli_complete_help(const char *str, int pos)
563{
564 int arg = get_cmd_arg_num(str, pos);
565 char **res = NULL;
566
567 switch (arg) {
568 case 1:
569 res = wpa_list_cmd_list();
570 break;
571 }
572
573 return res;
574}
575
576
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700577static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
578{
579 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
580 return 0;
581}
582
583
584static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
585{
586 wpa_cli_quit = 1;
587 if (interactive)
588 eloop_terminate();
589 return 0;
590}
591
592
593static void wpa_cli_show_variables(void)
594{
595 printf("set variables:\n"
596 " EAPOL::heldPeriod (EAPOL state machine held period, "
597 "in seconds)\n"
598 " EAPOL::authPeriod (EAPOL state machine authentication "
599 "period, in seconds)\n"
600 " EAPOL::startPeriod (EAPOL state machine start period, in "
601 "seconds)\n"
602 " EAPOL::maxStart (EAPOL state machine maximum start "
603 "attempts)\n");
604 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
605 "seconds)\n"
606 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
607 " threshold\n\tpercentage)\n"
608 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
609 "security\n\tassociation in seconds)\n");
610}
611
612
613static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
614{
615 char cmd[256];
616 int res;
617
618 if (argc == 0) {
619 wpa_cli_show_variables();
620 return 0;
621 }
622
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800623 if (argc != 1 && argc != 2) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700624 printf("Invalid SET command: needs two arguments (variable "
625 "name and value)\n");
626 return -1;
627 }
628
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800629 if (argc == 1)
630 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
631 else
632 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
633 argv[0], argv[1]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700634 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
635 printf("Too long SET command.\n");
636 return -1;
637 }
638 return wpa_ctrl_command(ctrl, cmd);
639}
640
641
642static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
643{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700644 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700645}
646
647
648static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
649{
650 return wpa_ctrl_command(ctrl, "LOGOFF");
651}
652
653
654static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
655{
656 return wpa_ctrl_command(ctrl, "LOGON");
657}
658
659
660static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
661 char *argv[])
662{
663 return wpa_ctrl_command(ctrl, "REASSOCIATE");
664}
665
666
667static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
668 char *argv[])
669{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700670 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700671}
672
673
674static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
675{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700676 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700677}
678
679
680static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
681 char *argv[])
682{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700683 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684}
685
686
687static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
688 char *argv[])
689{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700690 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700691}
692
693
694static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
695 char *argv[])
696{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700697 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700698}
699
700
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700701static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
702{
703 char cmd[256];
704 int res;
705
706 if (argc < 1)
707 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
708 else
709 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
710 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
711 printf("Too long BSS_FLUSH command.\n");
712 return -1;
713 }
714 return wpa_ctrl_command(ctrl, cmd);
715}
716
717
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700718static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
719 char *argv[])
720{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700721 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700722}
723
724
725static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
726{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700727 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700728}
729
730
731static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
732{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700733 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700734}
735
736
737static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
738{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700739 if (argc == 0) {
740 printf("Invalid WPS_PIN command: need one or two arguments:\n"
741 "- BSSID: use 'any' to select any\n"
742 "- PIN: optional, used only with devices that have no "
743 "display\n");
744 return -1;
745 }
746
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700747 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700748}
749
750
751static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
752 char *argv[])
753{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700754 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700755}
756
757
758static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
759 char *argv[])
760{
761 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
762}
763
764
765#ifdef CONFIG_WPS_OOB
766static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
767{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700768 if (argc != 3 && argc != 4) {
769 printf("Invalid WPS_OOB command: need three or four "
770 "arguments:\n"
771 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
772 "- PATH: path of OOB device like '/mnt'\n"
773 "- METHOD: OOB method 'pin-e' or 'pin-r', "
774 "'cred'\n"
775 "- DEV_NAME: (only for NFC) device name like "
776 "'pn531'\n");
777 return -1;
778 }
779
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700780 return wpa_cli_cmd(ctrl, "WPS_OOB", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700781}
782#endif /* CONFIG_WPS_OOB */
783
784
Dmitry Shmidt04949592012-07-19 12:16:46 -0700785#ifdef CONFIG_WPS_NFC
786
787static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
788{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700789 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700790}
791
792
793static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
794 char *argv[])
795{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700796 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700797}
798
799
800static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
801 char *argv[])
802{
803 int ret;
804 char *buf;
805 size_t buflen;
806
807 if (argc != 1) {
808 printf("Invalid 'wps_nfc_tag_read' command - one argument "
809 "is required.\n");
810 return -1;
811 }
812
813 buflen = 18 + os_strlen(argv[0]);
814 buf = os_malloc(buflen);
815 if (buf == NULL)
816 return -1;
817 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
818
819 ret = wpa_ctrl_command(ctrl, buf);
820 os_free(buf);
821
822 return ret;
823}
824
825#endif /* CONFIG_WPS_NFC */
826
827
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700828static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
829{
830 char cmd[256];
831 int res;
832
833 if (argc == 2)
834 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
835 argv[0], argv[1]);
836 else if (argc == 5 || argc == 6) {
837 char ssid_hex[2 * 32 + 1];
838 char key_hex[2 * 64 + 1];
839 int i;
840
841 ssid_hex[0] = '\0';
842 for (i = 0; i < 32; i++) {
843 if (argv[2][i] == '\0')
844 break;
845 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
846 }
847
848 key_hex[0] = '\0';
849 if (argc == 6) {
850 for (i = 0; i < 64; i++) {
851 if (argv[5][i] == '\0')
852 break;
853 os_snprintf(&key_hex[i * 2], 3, "%02x",
854 argv[5][i]);
855 }
856 }
857
858 res = os_snprintf(cmd, sizeof(cmd),
859 "WPS_REG %s %s %s %s %s %s",
860 argv[0], argv[1], ssid_hex, argv[3], argv[4],
861 key_hex);
862 } else {
863 printf("Invalid WPS_REG command: need two arguments:\n"
864 "- BSSID of the target AP\n"
865 "- AP PIN\n");
866 printf("Alternatively, six arguments can be used to "
867 "reconfigure the AP:\n"
868 "- BSSID of the target AP\n"
869 "- AP PIN\n"
870 "- new SSID\n"
871 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
872 "- new encr (NONE, WEP, TKIP, CCMP)\n"
873 "- new key\n");
874 return -1;
875 }
876
877 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
878 printf("Too long WPS_REG command.\n");
879 return -1;
880 }
881 return wpa_ctrl_command(ctrl, cmd);
882}
883
884
885static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
886 char *argv[])
887{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700888 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700889}
890
891
892static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
893 char *argv[])
894{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700895 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700896}
897
898
899static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
900 char *argv[])
901{
902 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
903
904}
905
906
907static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
908 char *argv[])
909{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700910 if (argc < 2) {
911 printf("Invalid WPS_ER_PIN command: need at least two "
912 "arguments:\n"
913 "- UUID: use 'any' to select any\n"
914 "- PIN: Enrollee PIN\n"
915 "optional: - Enrollee MAC address\n");
916 return -1;
917 }
918
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700919 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700920}
921
922
923static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
924 char *argv[])
925{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700926 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700927}
928
929
930static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
931 char *argv[])
932{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700933 if (argc != 2) {
934 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
935 "- UUID: specify which AP to use\n"
936 "- PIN: AP PIN\n");
937 return -1;
938 }
939
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700940 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700941}
942
943
944static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
945 char *argv[])
946{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700947 if (argc != 2) {
948 printf("Invalid WPS_ER_SET_CONFIG command: need two "
949 "arguments:\n"
950 "- UUID: specify which AP to use\n"
951 "- Network configuration id\n");
952 return -1;
953 }
954
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700955 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700956}
957
958
959static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
960 char *argv[])
961{
962 char cmd[256];
963 int res;
964
965 if (argc == 5 || argc == 6) {
966 char ssid_hex[2 * 32 + 1];
967 char key_hex[2 * 64 + 1];
968 int i;
969
970 ssid_hex[0] = '\0';
971 for (i = 0; i < 32; i++) {
972 if (argv[2][i] == '\0')
973 break;
974 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
975 }
976
977 key_hex[0] = '\0';
978 if (argc == 6) {
979 for (i = 0; i < 64; i++) {
980 if (argv[5][i] == '\0')
981 break;
982 os_snprintf(&key_hex[i * 2], 3, "%02x",
983 argv[5][i]);
984 }
985 }
986
987 res = os_snprintf(cmd, sizeof(cmd),
988 "WPS_ER_CONFIG %s %s %s %s %s %s",
989 argv[0], argv[1], ssid_hex, argv[3], argv[4],
990 key_hex);
991 } else {
992 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
993 "- AP UUID\n"
994 "- AP PIN\n"
995 "- new SSID\n"
996 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
997 "- new encr (NONE, WEP, TKIP, CCMP)\n"
998 "- new key\n");
999 return -1;
1000 }
1001
1002 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1003 printf("Too long WPS_ER_CONFIG command.\n");
1004 return -1;
1005 }
1006 return wpa_ctrl_command(ctrl, cmd);
1007}
1008
1009
Dmitry Shmidt04949592012-07-19 12:16:46 -07001010#ifdef CONFIG_WPS_NFC
1011static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1012 char *argv[])
1013{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001014 if (argc != 2) {
1015 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1016 "arguments:\n"
1017 "- WPS/NDEF: token format\n"
1018 "- UUID: specify which AP to use\n");
1019 return -1;
1020 }
1021
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001022 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001023}
1024#endif /* CONFIG_WPS_NFC */
1025
1026
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001027static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1028{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001029 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030}
1031
1032
1033static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1034{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001035 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001036}
1037
1038
1039static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1040{
1041 char cmd[256], *pos, *end;
1042 int i, ret;
1043
1044 if (argc < 2) {
1045 printf("Invalid IDENTITY command: needs two arguments "
1046 "(network id and identity)\n");
1047 return -1;
1048 }
1049
1050 end = cmd + sizeof(cmd);
1051 pos = cmd;
1052 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1053 argv[0], argv[1]);
1054 if (ret < 0 || ret >= end - pos) {
1055 printf("Too long IDENTITY command.\n");
1056 return -1;
1057 }
1058 pos += ret;
1059 for (i = 2; i < argc; i++) {
1060 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1061 if (ret < 0 || ret >= end - pos) {
1062 printf("Too long IDENTITY command.\n");
1063 return -1;
1064 }
1065 pos += ret;
1066 }
1067
1068 return wpa_ctrl_command(ctrl, cmd);
1069}
1070
1071
1072static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1073{
1074 char cmd[256], *pos, *end;
1075 int i, ret;
1076
1077 if (argc < 2) {
1078 printf("Invalid PASSWORD command: needs two arguments "
1079 "(network id and password)\n");
1080 return -1;
1081 }
1082
1083 end = cmd + sizeof(cmd);
1084 pos = cmd;
1085 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1086 argv[0], argv[1]);
1087 if (ret < 0 || ret >= end - pos) {
1088 printf("Too long PASSWORD command.\n");
1089 return -1;
1090 }
1091 pos += ret;
1092 for (i = 2; i < argc; i++) {
1093 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1094 if (ret < 0 || ret >= end - pos) {
1095 printf("Too long PASSWORD command.\n");
1096 return -1;
1097 }
1098 pos += ret;
1099 }
1100
1101 return wpa_ctrl_command(ctrl, cmd);
1102}
1103
1104
1105static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1106 char *argv[])
1107{
1108 char cmd[256], *pos, *end;
1109 int i, ret;
1110
1111 if (argc < 2) {
1112 printf("Invalid NEW_PASSWORD command: needs two arguments "
1113 "(network id and password)\n");
1114 return -1;
1115 }
1116
1117 end = cmd + sizeof(cmd);
1118 pos = cmd;
1119 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1120 argv[0], argv[1]);
1121 if (ret < 0 || ret >= end - pos) {
1122 printf("Too long NEW_PASSWORD command.\n");
1123 return -1;
1124 }
1125 pos += ret;
1126 for (i = 2; i < argc; i++) {
1127 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1128 if (ret < 0 || ret >= end - pos) {
1129 printf("Too long NEW_PASSWORD command.\n");
1130 return -1;
1131 }
1132 pos += ret;
1133 }
1134
1135 return wpa_ctrl_command(ctrl, cmd);
1136}
1137
1138
1139static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1140{
1141 char cmd[256], *pos, *end;
1142 int i, ret;
1143
1144 if (argc < 2) {
1145 printf("Invalid PIN command: needs two arguments "
1146 "(network id and pin)\n");
1147 return -1;
1148 }
1149
1150 end = cmd + sizeof(cmd);
1151 pos = cmd;
1152 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1153 argv[0], argv[1]);
1154 if (ret < 0 || ret >= end - pos) {
1155 printf("Too long PIN command.\n");
1156 return -1;
1157 }
1158 pos += ret;
1159 for (i = 2; i < argc; i++) {
1160 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1161 if (ret < 0 || ret >= end - pos) {
1162 printf("Too long PIN command.\n");
1163 return -1;
1164 }
1165 pos += ret;
1166 }
1167 return wpa_ctrl_command(ctrl, cmd);
1168}
1169
1170
1171static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1172{
1173 char cmd[256], *pos, *end;
1174 int i, ret;
1175
1176 if (argc < 2) {
1177 printf("Invalid OTP command: needs two arguments (network "
1178 "id and password)\n");
1179 return -1;
1180 }
1181
1182 end = cmd + sizeof(cmd);
1183 pos = cmd;
1184 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1185 argv[0], argv[1]);
1186 if (ret < 0 || ret >= end - pos) {
1187 printf("Too long OTP command.\n");
1188 return -1;
1189 }
1190 pos += ret;
1191 for (i = 2; i < argc; i++) {
1192 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1193 if (ret < 0 || ret >= end - pos) {
1194 printf("Too long OTP command.\n");
1195 return -1;
1196 }
1197 pos += ret;
1198 }
1199
1200 return wpa_ctrl_command(ctrl, cmd);
1201}
1202
1203
1204static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1205 char *argv[])
1206{
1207 char cmd[256], *pos, *end;
1208 int i, ret;
1209
1210 if (argc < 2) {
1211 printf("Invalid PASSPHRASE command: needs two arguments "
1212 "(network id and passphrase)\n");
1213 return -1;
1214 }
1215
1216 end = cmd + sizeof(cmd);
1217 pos = cmd;
1218 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1219 argv[0], argv[1]);
1220 if (ret < 0 || ret >= end - pos) {
1221 printf("Too long PASSPHRASE command.\n");
1222 return -1;
1223 }
1224 pos += ret;
1225 for (i = 2; i < argc; i++) {
1226 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1227 if (ret < 0 || ret >= end - pos) {
1228 printf("Too long PASSPHRASE command.\n");
1229 return -1;
1230 }
1231 pos += ret;
1232 }
1233
1234 return wpa_ctrl_command(ctrl, cmd);
1235}
1236
1237
1238static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1239{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001240 if (argc < 2) {
1241 printf("Invalid BSSID command: needs two arguments (network "
1242 "id and BSSID)\n");
1243 return -1;
1244 }
1245
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001246 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001247}
1248
1249
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001250static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1251{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001252 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001253}
1254
1255
1256static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1257{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001258 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001259}
1260
1261
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001262static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1263 char *argv[])
1264{
1265 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1266}
1267
1268
1269static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1270 char *argv[])
1271{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001272 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001273}
1274
1275
1276static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1277 char *argv[])
1278{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001279 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001280}
1281
1282
1283static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1284 char *argv[])
1285{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001286 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001287}
1288
1289
1290static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1291 char *argv[])
1292{
1293 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1294}
1295
1296
1297static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1298 char *argv[])
1299{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001300 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001301}
1302
1303
1304static void wpa_cli_show_network_variables(void)
1305{
1306 printf("set_network variables:\n"
1307 " ssid (network name, SSID)\n"
1308 " psk (WPA passphrase or pre-shared key)\n"
1309 " key_mgmt (key management protocol)\n"
1310 " identity (EAP identity)\n"
1311 " password (EAP password)\n"
1312 " ...\n"
1313 "\n"
1314 "Note: Values are entered in the same format as the "
1315 "configuration file is using,\n"
1316 "i.e., strings values need to be inside double quotation "
1317 "marks.\n"
1318 "For example: set_network 1 ssid \"network name\"\n"
1319 "\n"
1320 "Please see wpa_supplicant.conf documentation for full list "
1321 "of\navailable variables.\n");
1322}
1323
1324
1325static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1326 char *argv[])
1327{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001328 if (argc == 0) {
1329 wpa_cli_show_network_variables();
1330 return 0;
1331 }
1332
1333 if (argc != 3) {
1334 printf("Invalid SET_NETWORK command: needs three arguments\n"
1335 "(network id, variable name, and value)\n");
1336 return -1;
1337 }
1338
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001339 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001340}
1341
1342
1343static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1344 char *argv[])
1345{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001346 if (argc == 0) {
1347 wpa_cli_show_network_variables();
1348 return 0;
1349 }
1350
1351 if (argc != 2) {
1352 printf("Invalid GET_NETWORK command: needs two arguments\n"
1353 "(network id and variable name)\n");
1354 return -1;
1355 }
1356
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001357 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001358}
1359
1360
Dmitry Shmidt04949592012-07-19 12:16:46 -07001361static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1362 char *argv[])
1363{
1364 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1365}
1366
1367
1368static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1369{
1370 return wpa_ctrl_command(ctrl, "ADD_CRED");
1371}
1372
1373
1374static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1375 char *argv[])
1376{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001377 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001378}
1379
1380
1381static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1382{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001383 if (argc != 3) {
1384 printf("Invalid SET_CRED command: needs three arguments\n"
1385 "(cred id, variable name, and value)\n");
1386 return -1;
1387 }
1388
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001389 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001390}
1391
1392
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001393static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1394 char *argv[])
1395{
1396 return wpa_ctrl_command(ctrl, "DISCONNECT");
1397}
1398
1399
1400static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1401 char *argv[])
1402{
1403 return wpa_ctrl_command(ctrl, "RECONNECT");
1404}
1405
1406
1407static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1408 char *argv[])
1409{
1410 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1411}
1412
1413
1414static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1415{
1416 return wpa_ctrl_command(ctrl, "SCAN");
1417}
1418
1419
1420static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1421 char *argv[])
1422{
1423 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1424}
1425
1426
1427static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1428{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001429 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001430}
1431
1432
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001433static char ** wpa_cli_complete_bss(const char *str, int pos)
1434{
1435 int arg = get_cmd_arg_num(str, pos);
1436 char **res = NULL;
1437
1438 switch (arg) {
1439 case 1:
1440 res = cli_txt_list_array(&bsses);
1441 break;
1442 }
1443
1444 return res;
1445}
1446
1447
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001448static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1449 char *argv[])
1450{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001451 if (argc < 1 || argc > 2) {
1452 printf("Invalid GET_CAPABILITY command: need either one or "
1453 "two arguments\n");
1454 return -1;
1455 }
1456
1457 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1458 printf("Invalid GET_CAPABILITY command: second argument, "
1459 "if any, must be 'strict'\n");
1460 return -1;
1461 }
1462
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001463 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001464}
1465
1466
1467static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1468{
1469 printf("Available interfaces:\n");
1470 return wpa_ctrl_command(ctrl, "INTERFACES");
1471}
1472
1473
1474static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1475{
1476 if (argc < 1) {
1477 wpa_cli_list_interfaces(ctrl);
1478 return 0;
1479 }
1480
1481 wpa_cli_close_connection();
1482 os_free(ctrl_ifname);
1483 ctrl_ifname = os_strdup(argv[0]);
1484
1485 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1486 printf("Connected to interface '%s.\n", ctrl_ifname);
1487 } else {
1488 printf("Could not connect to interface '%s' - re-trying\n",
1489 ctrl_ifname);
1490 }
1491 return 0;
1492}
1493
1494
1495static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1496 char *argv[])
1497{
1498 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1499}
1500
1501
1502static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1503 char *argv[])
1504{
1505 return wpa_ctrl_command(ctrl, "TERMINATE");
1506}
1507
1508
1509static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1510 char *argv[])
1511{
1512 char cmd[256];
1513 int res;
1514
1515 if (argc < 1) {
1516 printf("Invalid INTERFACE_ADD command: needs at least one "
1517 "argument (interface name)\n"
1518 "All arguments: ifname confname driver ctrl_interface "
1519 "driver_param bridge_name\n");
1520 return -1;
1521 }
1522
1523 /*
1524 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1525 * <driver_param>TAB<bridge_name>
1526 */
1527 res = os_snprintf(cmd, sizeof(cmd),
1528 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1529 argv[0],
1530 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1531 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1532 argc > 5 ? argv[5] : "");
1533 if (res < 0 || (size_t) res >= sizeof(cmd))
1534 return -1;
1535 cmd[sizeof(cmd) - 1] = '\0';
1536 return wpa_ctrl_command(ctrl, cmd);
1537}
1538
1539
1540static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1541 char *argv[])
1542{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001543 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001544}
1545
1546
1547static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1548 char *argv[])
1549{
1550 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1551}
1552
1553
1554#ifdef CONFIG_AP
1555static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1556{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001557 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001558}
1559
1560
1561static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1562 char *addr, size_t addr_len)
1563{
1564 char buf[4096], *pos;
1565 size_t len;
1566 int ret;
1567
1568 if (ctrl_conn == NULL) {
1569 printf("Not connected to hostapd - command dropped.\n");
1570 return -1;
1571 }
1572 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001573 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001574 wpa_cli_msg_cb);
1575 if (ret == -2) {
1576 printf("'%s' command timed out.\n", cmd);
1577 return -2;
1578 } else if (ret < 0) {
1579 printf("'%s' command failed.\n", cmd);
1580 return -1;
1581 }
1582
1583 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001584 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001585 return -1;
1586 printf("%s", buf);
1587
1588 pos = buf;
1589 while (*pos != '\0' && *pos != '\n')
1590 pos++;
1591 *pos = '\0';
1592 os_strlcpy(addr, buf, addr_len);
1593 return 0;
1594}
1595
1596
1597static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1598{
1599 char addr[32], cmd[64];
1600
1601 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1602 return 0;
1603 do {
1604 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1605 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1606
1607 return -1;
1608}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001609
1610
1611static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1612 char *argv[])
1613{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001614 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001615}
1616
1617
1618static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1619 char *argv[])
1620{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001621 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001622}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001623#endif /* CONFIG_AP */
1624
1625
1626static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1627{
1628 return wpa_ctrl_command(ctrl, "SUSPEND");
1629}
1630
1631
1632static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1633{
1634 return wpa_ctrl_command(ctrl, "RESUME");
1635}
1636
1637
1638static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1639{
1640 return wpa_ctrl_command(ctrl, "DROP_SA");
1641}
1642
1643
1644static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1645{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001646 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001647}
1648
1649
1650#ifdef CONFIG_P2P
1651
1652static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1653{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001654 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1655}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001656
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001657
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001658static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1659{
1660 char **res = NULL;
1661 int arg = get_cmd_arg_num(str, pos);
1662
1663 res = os_calloc(6, sizeof(char *));
1664 if (res == NULL)
1665 return NULL;
1666 res[0] = os_strdup("type=social");
1667 if (res[0] == NULL) {
1668 os_free(res);
1669 return NULL;
1670 }
1671 res[1] = os_strdup("type=progressive");
1672 if (res[1] == NULL)
1673 return res;
1674 res[2] = os_strdup("delay=");
1675 if (res[2] == NULL)
1676 return res;
1677 res[3] = os_strdup("dev_id=");
1678 if (res[3] == NULL)
1679 return res;
1680 if (arg == 1)
1681 res[4] = os_strdup("[timeout]");
1682
1683 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001684}
1685
1686
1687static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1688 char *argv[])
1689{
1690 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1691}
1692
1693
1694static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1695 char *argv[])
1696{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001697 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001698}
1699
1700
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001701static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1702{
1703 int arg = get_cmd_arg_num(str, pos);
1704 char **res = NULL;
1705
1706 switch (arg) {
1707 case 1:
1708 res = cli_txt_list_array(&p2p_peers);
1709 break;
1710 }
1711
1712 return res;
1713}
1714
1715
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1717 char *argv[])
1718{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001719 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001720}
1721
1722
1723static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1724 char *argv[])
1725{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001726 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001727}
1728
1729
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001730static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1731{
1732 int arg = get_cmd_arg_num(str, pos);
1733 char **res = NULL;
1734
1735 switch (arg) {
1736 case 1:
1737 res = cli_txt_list_array(&p2p_groups);
1738 break;
1739 }
1740
1741 return res;
1742}
1743
1744
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1746 char *argv[])
1747{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001748 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001749}
1750
1751
1752static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1753 char *argv[])
1754{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001755 if (argc != 2 && argc != 3) {
1756 printf("Invalid P2P_PROV_DISC command: needs at least "
1757 "two arguments, address and config method\n"
1758 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001759 return -1;
1760 }
1761
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001762 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001763}
1764
1765
1766static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1767 char *argv[])
1768{
1769 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1770}
1771
1772
1773static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1774 char *argv[])
1775{
1776 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001777
1778 if (argc != 2 && argc != 4) {
1779 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1780 "arguments (address and TLVs) or four arguments "
1781 "(address, \"upnp\", version, search target "
1782 "(SSDP ST:)\n");
1783 return -1;
1784 }
1785
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001786 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001788 return wpa_ctrl_command(ctrl, cmd);
1789}
1790
1791
1792static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1793 int argc, char *argv[])
1794{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001795 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001796}
1797
1798
1799static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1800 char *argv[])
1801{
1802 char cmd[4096];
1803 int res;
1804
1805 if (argc != 4) {
1806 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1807 "arguments (freq, address, dialog token, and TLVs)\n");
1808 return -1;
1809 }
1810
1811 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1812 argv[0], argv[1], argv[2], argv[3]);
1813 if (res < 0 || (size_t) res >= sizeof(cmd))
1814 return -1;
1815 cmd[sizeof(cmd) - 1] = '\0';
1816 return wpa_ctrl_command(ctrl, cmd);
1817}
1818
1819
1820static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1821 char *argv[])
1822{
1823 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1824}
1825
1826
1827static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1828 int argc, char *argv[])
1829{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001830 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001831}
1832
1833
1834static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1835 char *argv[])
1836{
1837 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1838}
1839
1840
1841static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1842 char *argv[])
1843{
1844 char cmd[4096];
1845 int res;
1846
1847 if (argc != 3 && argc != 4) {
1848 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1849 "arguments\n");
1850 return -1;
1851 }
1852
1853 if (argc == 4)
1854 res = os_snprintf(cmd, sizeof(cmd),
1855 "P2P_SERVICE_ADD %s %s %s %s",
1856 argv[0], argv[1], argv[2], argv[3]);
1857 else
1858 res = os_snprintf(cmd, sizeof(cmd),
1859 "P2P_SERVICE_ADD %s %s %s",
1860 argv[0], argv[1], argv[2]);
1861 if (res < 0 || (size_t) res >= sizeof(cmd))
1862 return -1;
1863 cmd[sizeof(cmd) - 1] = '\0';
1864 return wpa_ctrl_command(ctrl, cmd);
1865}
1866
1867
1868static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1869 char *argv[])
1870{
1871 char cmd[4096];
1872 int res;
1873
1874 if (argc != 2 && argc != 3) {
1875 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1876 "arguments\n");
1877 return -1;
1878 }
1879
1880 if (argc == 3)
1881 res = os_snprintf(cmd, sizeof(cmd),
1882 "P2P_SERVICE_DEL %s %s %s",
1883 argv[0], argv[1], argv[2]);
1884 else
1885 res = os_snprintf(cmd, sizeof(cmd),
1886 "P2P_SERVICE_DEL %s %s",
1887 argv[0], argv[1]);
1888 if (res < 0 || (size_t) res >= sizeof(cmd))
1889 return -1;
1890 cmd[sizeof(cmd) - 1] = '\0';
1891 return wpa_ctrl_command(ctrl, cmd);
1892}
1893
1894
1895static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1896 int argc, char *argv[])
1897{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001898 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001899}
1900
1901
1902static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1903 int argc, char *argv[])
1904{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001905 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001906}
1907
1908
1909static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1910{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001911 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001912}
1913
1914
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001915static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1916{
1917 int arg = get_cmd_arg_num(str, pos);
1918 char **res = NULL;
1919
1920 switch (arg) {
1921 case 1:
1922 res = cli_txt_list_array(&p2p_peers);
1923 break;
1924 }
1925
1926 return res;
1927}
1928
1929
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001930static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1931 char *addr, size_t addr_len,
1932 int discovered)
1933{
1934 char buf[4096], *pos;
1935 size_t len;
1936 int ret;
1937
1938 if (ctrl_conn == NULL)
1939 return -1;
1940 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001941 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001942 wpa_cli_msg_cb);
1943 if (ret == -2) {
1944 printf("'%s' command timed out.\n", cmd);
1945 return -2;
1946 } else if (ret < 0) {
1947 printf("'%s' command failed.\n", cmd);
1948 return -1;
1949 }
1950
1951 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001952 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001953 return -1;
1954
1955 pos = buf;
1956 while (*pos != '\0' && *pos != '\n')
1957 pos++;
1958 *pos++ = '\0';
1959 os_strlcpy(addr, buf, addr_len);
1960 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
1961 printf("%s\n", addr);
1962 return 0;
1963}
1964
1965
1966static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
1967{
1968 char addr[32], cmd[64];
1969 int discovered;
1970
1971 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
1972
1973 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
1974 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001975 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001976 do {
1977 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
1978 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
1979 discovered) == 0);
1980
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001981 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001982}
1983
1984
1985static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
1986{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001987 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001988}
1989
1990
1991static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
1992{
1993 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
1994}
1995
1996
1997static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
1998 char *argv[])
1999{
2000 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2001}
2002
2003
2004static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2005 char *argv[])
2006{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002007 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002008}
2009
2010
2011static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2012 char *argv[])
2013{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002014 if (argc != 0 && argc != 2 && argc != 4) {
2015 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2016 "(preferred duration, interval; in microsecods).\n"
2017 "Optional second pair can be used to provide "
2018 "acceptable values.\n");
2019 return -1;
2020 }
2021
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002022 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002023}
2024
2025
2026static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2027 char *argv[])
2028{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002029 if (argc != 0 && argc != 2) {
2030 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2031 "(availability period, availability interval; in "
2032 "millisecods).\n"
2033 "Extended Listen Timing can be cancelled with this "
2034 "command when used without parameters.\n");
2035 return -1;
2036 }
2037
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002038 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2039}
2040
2041#endif /* CONFIG_P2P */
2042
2043#ifdef CONFIG_WIFI_DISPLAY
2044
2045static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2046 char *argv[])
2047{
2048 char cmd[100];
2049 int res;
2050
2051 if (argc != 1 && argc != 2) {
2052 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2053 "arguments (subelem, hexdump)\n");
2054 return -1;
2055 }
2056
2057 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2058 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002059 if (res < 0 || (size_t) res >= sizeof(cmd))
2060 return -1;
2061 cmd[sizeof(cmd) - 1] = '\0';
2062 return wpa_ctrl_command(ctrl, cmd);
2063}
2064
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002065
2066static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2067 char *argv[])
2068{
2069 char cmd[100];
2070 int res;
2071
2072 if (argc != 1) {
2073 printf("Invalid WFD_SUBELEM_GET command: needs one "
2074 "argument (subelem)\n");
2075 return -1;
2076 }
2077
2078 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2079 argv[0]);
2080 if (res < 0 || (size_t) res >= sizeof(cmd))
2081 return -1;
2082 cmd[sizeof(cmd) - 1] = '\0';
2083 return wpa_ctrl_command(ctrl, cmd);
2084}
2085#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002086
2087
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002088#ifdef CONFIG_INTERWORKING
2089static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2090 char *argv[])
2091{
2092 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2093}
2094
2095
2096static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2097 char *argv[])
2098{
2099 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2100}
2101
2102
2103static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2104 char *argv[])
2105{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002106 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002107}
2108
2109
2110static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2111 char *argv[])
2112{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002113 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002114}
2115
2116
2117static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2118{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002119 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2120}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002121
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002122
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002123static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2124 char *argv[])
2125{
2126 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2127}
2128
2129
2130static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2131 char *argv[])
2132{
2133 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002134}
2135#endif /* CONFIG_INTERWORKING */
2136
2137
Dmitry Shmidt04949592012-07-19 12:16:46 -07002138#ifdef CONFIG_HS20
2139
2140static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2141 char *argv[])
2142{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002143 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002144}
2145
2146
2147static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2148 char *argv[])
2149{
2150 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002151
2152 if (argc == 0) {
2153 printf("Command needs one or two arguments (dst mac addr and "
2154 "optional home realm)\n");
2155 return -1;
2156 }
2157
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002158 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2159 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002160 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002161
2162 return wpa_ctrl_command(ctrl, cmd);
2163}
2164
2165#endif /* CONFIG_HS20 */
2166
2167
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002168static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2169 char *argv[])
2170{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002171 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002172}
2173
2174
2175static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2176 char *argv[])
2177{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002178 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002179}
2180
2181
2182static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2183 char *argv[])
2184{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002185 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002186}
2187
2188
2189static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2190 char *argv[])
2191{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002192 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002193}
2194
2195
2196static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2197 char *argv[])
2198{
2199 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2200}
2201
2202
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002203static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2204 char *argv[])
2205{
2206 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2207}
2208
2209
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002210static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2211 char *argv[])
2212{
2213 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2214}
2215
Dmitry Shmidt04949592012-07-19 12:16:46 -07002216
2217#ifdef CONFIG_AUTOSCAN
2218
2219static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2220{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002221 if (argc == 0)
2222 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2223
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002224 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002225}
2226
2227#endif /* CONFIG_AUTOSCAN */
2228
2229
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002230static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2231{
2232 if (argc == 0)
2233 return -1;
2234 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2235}
2236
2237
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002238#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002239static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2240{
2241 char cmd[256];
2242 int i;
2243 int len;
2244
2245 if (argc < 1) {
2246 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2247 return -1;
2248 }
2249
2250 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2251 for (i=1; i < argc; i++)
2252 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2253 cmd[sizeof(cmd) - 1] = '\0';
2254 printf("%s: %s\n", __func__, cmd);
2255 return wpa_ctrl_command(ctrl, cmd);
2256}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002257#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002258
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002259
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002260enum wpa_cli_cmd_flags {
2261 cli_cmd_flag_none = 0x00,
2262 cli_cmd_flag_sensitive = 0x01
2263};
2264
2265struct wpa_cli_cmd {
2266 const char *cmd;
2267 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002268 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002269 enum wpa_cli_cmd_flags flags;
2270 const char *usage;
2271};
2272
2273static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002274 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002275 cli_cmd_flag_none,
2276 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002277 { "ifname", wpa_cli_cmd_ifname, NULL,
2278 cli_cmd_flag_none,
2279 "= get current interface name" },
2280 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002281 cli_cmd_flag_none,
2282 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002283 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002284 cli_cmd_flag_none,
2285 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002286 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002287 cli_cmd_flag_none,
2288 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002289 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002290 cli_cmd_flag_none,
2291 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002292 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002293 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002294 "[command] = show usage help" },
2295 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002296 cli_cmd_flag_none,
2297 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002298 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002299 cli_cmd_flag_none,
2300 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002301 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002302 cli_cmd_flag_none,
2303 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002304 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002305 cli_cmd_flag_none,
2306 "= exit wpa_cli" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002307 { "set", wpa_cli_cmd_set, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002308 cli_cmd_flag_none,
2309 "= set variables (shows list of variables when run without "
2310 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002311 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002312 cli_cmd_flag_none,
2313 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002314 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002315 cli_cmd_flag_none,
2316 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002317 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002318 cli_cmd_flag_none,
2319 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002320 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002321 cli_cmd_flag_none,
2322 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002323 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002324 cli_cmd_flag_none,
2325 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002326 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002327 cli_cmd_flag_none,
2328 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002329 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002330 cli_cmd_flag_none,
2331 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002332 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333 cli_cmd_flag_sensitive,
2334 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002335 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002336 cli_cmd_flag_sensitive,
2337 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002338 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002339 cli_cmd_flag_sensitive,
2340 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002341 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002342 cli_cmd_flag_sensitive,
2343 "<network id> <password> = configure one-time-password for an SSID"
2344 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002345 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002346 cli_cmd_flag_sensitive,
2347 "<network id> <passphrase> = configure private key passphrase\n"
2348 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002349 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002350 cli_cmd_flag_none,
2351 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002352 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002353 cli_cmd_flag_none,
2354 "<BSSID> = add a BSSID to the blacklist\n"
2355 "blacklist clear = clear the blacklist\n"
2356 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002357 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002358 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002359 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002360 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002361 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002362 cli_cmd_flag_none,
2363 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002364 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002365 cli_cmd_flag_none,
2366 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002367 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002368 cli_cmd_flag_none,
2369 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002370 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002371 cli_cmd_flag_none,
2372 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002373 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002374 cli_cmd_flag_none,
2375 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002376 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002377 cli_cmd_flag_none,
2378 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002379 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002380 cli_cmd_flag_sensitive,
2381 "<network id> <variable> <value> = set network variables (shows\n"
2382 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002383 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002384 cli_cmd_flag_none,
2385 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002386 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002387 cli_cmd_flag_none,
2388 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002389 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002390 cli_cmd_flag_none,
2391 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002392 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002393 cli_cmd_flag_none,
2394 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002395 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002396 cli_cmd_flag_sensitive,
2397 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002398 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002399 cli_cmd_flag_none,
2400 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002401 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002402 cli_cmd_flag_none,
2403 "= disconnect and wait for reassociate/reconnect command before\n"
2404 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002405 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002406 cli_cmd_flag_none,
2407 "= like reassociate, but only takes effect if already disconnected"
2408 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002409 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002410 cli_cmd_flag_none,
2411 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002412 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002413 cli_cmd_flag_none,
2414 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002415 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002416 cli_cmd_flag_none,
2417 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002418 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002419 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002420 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels> "
2421 "= get capabilies" },
2422 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002423 cli_cmd_flag_none,
2424 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002425 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002426 cli_cmd_flag_none,
2427 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002428 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002429 cli_cmd_flag_none,
2430 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2431 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2432 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002433 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002434 cli_cmd_flag_none,
2435 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002436 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002437 cli_cmd_flag_none,
2438 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002439 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002440 cli_cmd_flag_none,
2441 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002442 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002443 cli_cmd_flag_none,
2444 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002445 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002446 cli_cmd_flag_none,
2447 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002448 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002449 cli_cmd_flag_none,
2450 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002451 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002452 cli_cmd_flag_none,
2453 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002454 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002455 cli_cmd_flag_none,
2456 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002457 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002458 cli_cmd_flag_none,
2459 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002460 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002461 cli_cmd_flag_none,
2462 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002463 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002464 cli_cmd_flag_sensitive,
2465 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2466 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002467 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 cli_cmd_flag_sensitive,
2469 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002470 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002471 "Cancels the pending WPS operation" },
2472#ifdef CONFIG_WPS_OOB
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002473 { "wps_oob", wpa_cli_cmd_wps_oob, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002474 cli_cmd_flag_sensitive,
2475 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
2476#endif /* CONFIG_WPS_OOB */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002477#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002478 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002479 cli_cmd_flag_none,
2480 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002481 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002482 cli_cmd_flag_none,
2483 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002484 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002485 cli_cmd_flag_sensitive,
2486 "<hexdump of payload> = report read NFC tag with WPS data" },
2487#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002488 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489 cli_cmd_flag_sensitive,
2490 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002491 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 cli_cmd_flag_sensitive,
2493 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002494 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002495 cli_cmd_flag_none,
2496 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002497 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002498 cli_cmd_flag_none,
2499 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002500 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002501 cli_cmd_flag_sensitive,
2502 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002503 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002504 cli_cmd_flag_none,
2505 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002506 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507 cli_cmd_flag_sensitive,
2508 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002509 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002510 cli_cmd_flag_none,
2511 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002512 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 cli_cmd_flag_sensitive,
2514 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002515#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002516 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002517 cli_cmd_flag_none,
2518 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2519#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002520 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521 cli_cmd_flag_none,
2522 "<addr> = request RSN authentication with <addr> in IBSS" },
2523#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002524 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002525 cli_cmd_flag_none,
2526 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002527 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002528 cli_cmd_flag_none,
2529 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002530 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002531 cli_cmd_flag_none,
2532 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002533 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002534 cli_cmd_flag_none,
2535 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002536#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002537 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002538 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002539 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002540 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002541 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002543 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002544 cli_cmd_flag_none,
2545 "<addr> = roam to the specified BSS" },
2546#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002547 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2548 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002549 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002550 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002551 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002552 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2553 cli_cmd_flag_none,
2554 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2555 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002556 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002557 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2558 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002559 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002560 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2561 "[ht40] = add a new P2P group (local end as GO)" },
2562 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2563 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002564 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002565 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002566 cli_cmd_flag_none,
2567 "= get the passphrase for a group (GO only)" },
2568 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002569 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002570 "<addr> <TLVs> = schedule service discovery request" },
2571 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002572 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002573 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002574 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002575 cli_cmd_flag_none,
2576 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002577 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002578 cli_cmd_flag_none,
2579 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002580 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 cli_cmd_flag_none,
2582 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002583 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002584 cli_cmd_flag_none,
2585 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002586 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587 cli_cmd_flag_none,
2588 "<bonjour|upnp> <query|version> <response|service> = add a local "
2589 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002590 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002591 cli_cmd_flag_none,
2592 "<bonjour|upnp> <query|version> [|service] = remove a local "
2593 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002594 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002595 cli_cmd_flag_none,
2596 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002597 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002598 cli_cmd_flag_none,
2599 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002600 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002601 "[discovered] = list known (optionally, only fully discovered) P2P "
2602 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002603 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2604 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002605 "<address> = show information about known P2P peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002606 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002607 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002608 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002610 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002612 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2613 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002614 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002615 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2616 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002617 "[<duration> <interval>] [<duration> <interval>] = request GO "
2618 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002619 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2620 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002621 "[<period> <interval>] = set extended listen timing" },
2622#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002623#ifdef CONFIG_WIFI_DISPLAY
2624 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2625 cli_cmd_flag_none,
2626 "<subelem> [contents] = set Wi-Fi Display subelement" },
2627 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2628 cli_cmd_flag_none,
2629 "<subelem> = get Wi-Fi Display subelement" },
2630#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002631#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002632 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002633 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002634 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2635 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002636 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002637 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002638 cli_cmd_flag_none,
2639 "[auto] = perform Interworking network selection" },
2640 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002641 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002642 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002643 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2644 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002645 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002646 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2647 cli_cmd_flag_none,
2648 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2649 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2650 wpa_cli_complete_bss, cli_cmd_flag_none,
2651 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002652#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002653#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002654 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2655 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002656 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2657 },
2658 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002659 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002660 "<addr> <home realm> = get HS20 nai home realm list" },
2661#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002662 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2663 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002664 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002665 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002666 cli_cmd_flag_none,
2667 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002668 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002669 cli_cmd_flag_none,
2670 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002671 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002672 cli_cmd_flag_none,
2673 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002674 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002675 cli_cmd_flag_none,
2676 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002677 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002678 cli_cmd_flag_none,
2679 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002680 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2681 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002682 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002683#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002684 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002685 "[params] = Set or unset (if none) autoscan parameters" },
2686#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002687 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2688 "<params..> = Sent unprocessed command" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002689#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002690 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002691 cli_cmd_flag_none,
2692 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002693#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002694 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002695};
2696
2697
2698/*
2699 * Prints command usage, lines are padded with the specified string.
2700 */
2701static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2702{
2703 char c;
2704 size_t n;
2705
2706 printf("%s%s ", pad, cmd->cmd);
2707 for (n = 0; (c = cmd->usage[n]); n++) {
2708 printf("%c", c);
2709 if (c == '\n')
2710 printf("%s", pad);
2711 }
2712 printf("\n");
2713}
2714
2715
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002716static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002717{
2718 int n;
2719 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002720 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2721 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2722 print_cmd_help(&wpa_cli_commands[n], " ");
2723 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002724}
2725
2726
2727static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2728{
2729 const char *c, *delim;
2730 int n;
2731 size_t len;
2732
2733 delim = os_strchr(cmd, ' ');
2734 if (delim)
2735 len = delim - cmd;
2736 else
2737 len = os_strlen(cmd);
2738
2739 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2740 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2741 return (wpa_cli_commands[n].flags &
2742 cli_cmd_flag_sensitive);
2743 }
2744 return 0;
2745}
2746
2747
2748static char ** wpa_list_cmd_list(void)
2749{
2750 char **res;
2751 int i, count;
2752
2753 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002754 res = os_calloc(count, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002755 if (res == NULL)
2756 return NULL;
2757
2758 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2759 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2760 if (res[i] == NULL)
2761 break;
2762 }
2763
2764 return res;
2765}
2766
2767
2768static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2769 int pos)
2770{
2771 int i;
2772
2773 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2774 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002775 if (wpa_cli_commands[i].completion)
2776 return wpa_cli_commands[i].completion(str,
2777 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 edit_clear_line();
2779 printf("\r%s\n", wpa_cli_commands[i].usage);
2780 edit_redraw();
2781 break;
2782 }
2783 }
2784
2785 return NULL;
2786}
2787
2788
2789static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2790{
2791 char **res;
2792 const char *end;
2793 char *cmd;
2794
2795 end = os_strchr(str, ' ');
2796 if (end == NULL || str + pos < end)
2797 return wpa_list_cmd_list();
2798
2799 cmd = os_malloc(pos + 1);
2800 if (cmd == NULL)
2801 return NULL;
2802 os_memcpy(cmd, str, pos);
2803 cmd[end - str] = '\0';
2804 res = wpa_cli_cmd_completion(cmd, str, pos);
2805 os_free(cmd);
2806 return res;
2807}
2808
2809
2810static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2811{
2812 struct wpa_cli_cmd *cmd, *match = NULL;
2813 int count;
2814 int ret = 0;
2815
2816 count = 0;
2817 cmd = wpa_cli_commands;
2818 while (cmd->cmd) {
2819 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2820 {
2821 match = cmd;
2822 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2823 /* we have an exact match */
2824 count = 1;
2825 break;
2826 }
2827 count++;
2828 }
2829 cmd++;
2830 }
2831
2832 if (count > 1) {
2833 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2834 cmd = wpa_cli_commands;
2835 while (cmd->cmd) {
2836 if (os_strncasecmp(cmd->cmd, argv[0],
2837 os_strlen(argv[0])) == 0) {
2838 printf(" %s", cmd->cmd);
2839 }
2840 cmd++;
2841 }
2842 printf("\n");
2843 ret = 1;
2844 } else if (count == 0) {
2845 printf("Unknown command '%s'\n", argv[0]);
2846 ret = 1;
2847 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07002848#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
2849 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
2850 redirect_interface = os_strdup(argv[1]);
2851 ret = match->handler(ctrl, argc - 2, &argv[2]);
2852 }
2853 else
2854#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002855 ret = match->handler(ctrl, argc - 1, &argv[1]);
2856 }
2857
2858 return ret;
2859}
2860
2861
2862static int str_match(const char *a, const char *b)
2863{
2864 return os_strncmp(a, b, os_strlen(b)) == 0;
2865}
2866
2867
2868static int wpa_cli_exec(const char *program, const char *arg1,
2869 const char *arg2)
2870{
2871 char *cmd;
2872 size_t len;
2873 int res;
2874 int ret = 0;
2875
2876 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2877 cmd = os_malloc(len);
2878 if (cmd == NULL)
2879 return -1;
2880 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2881 if (res < 0 || (size_t) res >= len) {
2882 os_free(cmd);
2883 return -1;
2884 }
2885 cmd[len - 1] = '\0';
2886#ifndef _WIN32_WCE
2887 if (system(cmd) < 0)
2888 ret = -1;
2889#endif /* _WIN32_WCE */
2890 os_free(cmd);
2891
2892 return ret;
2893}
2894
2895
2896static void wpa_cli_action_process(const char *msg)
2897{
2898 const char *pos;
2899 char *copy = NULL, *id, *pos2;
2900
2901 pos = msg;
2902 if (*pos == '<') {
2903 /* skip priority */
2904 pos = os_strchr(pos, '>');
2905 if (pos)
2906 pos++;
2907 else
2908 pos = msg;
2909 }
2910
2911 if (str_match(pos, WPA_EVENT_CONNECTED)) {
2912 int new_id = -1;
2913 os_unsetenv("WPA_ID");
2914 os_unsetenv("WPA_ID_STR");
2915 os_unsetenv("WPA_CTRL_DIR");
2916
2917 pos = os_strstr(pos, "[id=");
2918 if (pos)
2919 copy = os_strdup(pos + 4);
2920
2921 if (copy) {
2922 pos2 = id = copy;
2923 while (*pos2 && *pos2 != ' ')
2924 pos2++;
2925 *pos2++ = '\0';
2926 new_id = atoi(id);
2927 os_setenv("WPA_ID", id, 1);
2928 while (*pos2 && *pos2 != '=')
2929 pos2++;
2930 if (*pos2 == '=')
2931 pos2++;
2932 id = pos2;
2933 while (*pos2 && *pos2 != ']')
2934 pos2++;
2935 *pos2 = '\0';
2936 os_setenv("WPA_ID_STR", id, 1);
2937 os_free(copy);
2938 }
2939
2940 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
2941
2942 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
2943 wpa_cli_connected = 1;
2944 wpa_cli_last_id = new_id;
2945 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
2946 }
2947 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
2948 if (wpa_cli_connected) {
2949 wpa_cli_connected = 0;
2950 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
2951 }
2952 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
2953 wpa_cli_exec(action_file, ctrl_ifname, pos);
2954 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
2955 wpa_cli_exec(action_file, ctrl_ifname, pos);
2956 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
2957 wpa_cli_exec(action_file, ctrl_ifname, pos);
2958 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
2959 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002960 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
2961 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002962 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
2963 wpa_cli_exec(action_file, ctrl_ifname, pos);
2964 } else if (str_match(pos, WPS_EVENT_FAIL)) {
2965 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002966 } else if (str_match(pos, AP_STA_CONNECTED)) {
2967 wpa_cli_exec(action_file, ctrl_ifname, pos);
2968 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
2969 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002970 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
2971 printf("wpa_supplicant is terminating - stop monitoring\n");
2972 wpa_cli_quit = 1;
2973 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002974}
2975
2976
2977#ifndef CONFIG_ANSI_C_EXTRA
2978static void wpa_cli_action_cb(char *msg, size_t len)
2979{
2980 wpa_cli_action_process(msg);
2981}
2982#endif /* CONFIG_ANSI_C_EXTRA */
2983
2984
2985static void wpa_cli_reconnect(void)
2986{
2987 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002988 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
2989 return;
2990
2991 if (interactive) {
2992 edit_clear_line();
2993 printf("\rConnection to wpa_supplicant re-established\n");
2994 edit_redraw();
2995 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002996}
2997
2998
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002999static void cli_event(const char *str)
3000{
3001 const char *start, *s;
3002
3003 start = os_strchr(str, '>');
3004 if (start == NULL)
3005 return;
3006
3007 start++;
3008
3009 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3010 s = os_strchr(start, ' ');
3011 if (s == NULL)
3012 return;
3013 s = os_strchr(s + 1, ' ');
3014 if (s == NULL)
3015 return;
3016 cli_txt_list_add(&bsses, s + 1);
3017 return;
3018 }
3019
3020 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3021 s = os_strchr(start, ' ');
3022 if (s == NULL)
3023 return;
3024 s = os_strchr(s + 1, ' ');
3025 if (s == NULL)
3026 return;
3027 cli_txt_list_del_addr(&bsses, s + 1);
3028 return;
3029 }
3030
3031#ifdef CONFIG_P2P
3032 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3033 s = os_strstr(start, " p2p_dev_addr=");
3034 if (s == NULL)
3035 return;
3036 cli_txt_list_add_addr(&p2p_peers, s + 14);
3037 return;
3038 }
3039
3040 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3041 s = os_strstr(start, " p2p_dev_addr=");
3042 if (s == NULL)
3043 return;
3044 cli_txt_list_del_addr(&p2p_peers, s + 14);
3045 return;
3046 }
3047
3048 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3049 s = os_strchr(start, ' ');
3050 if (s == NULL)
3051 return;
3052 cli_txt_list_add_word(&p2p_groups, s + 1);
3053 return;
3054 }
3055
3056 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3057 s = os_strchr(start, ' ');
3058 if (s == NULL)
3059 return;
3060 cli_txt_list_del_word(&p2p_groups, s + 1);
3061 return;
3062 }
3063#endif /* CONFIG_P2P */
3064}
3065
3066
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003067static int check_terminating(const char *msg)
3068{
3069 const char *pos = msg;
3070
3071 if (*pos == '<') {
3072 /* skip priority */
3073 pos = os_strchr(pos, '>');
3074 if (pos)
3075 pos++;
3076 else
3077 pos = msg;
3078 }
3079
3080 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3081 edit_clear_line();
3082 printf("\rConnection to wpa_supplicant lost - trying to "
3083 "reconnect\n");
3084 edit_redraw();
3085 wpa_cli_attached = 0;
3086 wpa_cli_close_connection();
3087 return 1;
3088 }
3089
3090 return 0;
3091}
3092
3093
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003094static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3095{
3096 if (ctrl_conn == NULL) {
3097 wpa_cli_reconnect();
3098 return;
3099 }
3100 while (wpa_ctrl_pending(ctrl) > 0) {
3101 char buf[256];
3102 size_t len = sizeof(buf) - 1;
3103 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3104 buf[len] = '\0';
3105 if (action_monitor)
3106 wpa_cli_action_process(buf);
3107 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003108 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003109 if (wpa_cli_show_event(buf)) {
3110 edit_clear_line();
3111 printf("\r%s\n", buf);
3112 edit_redraw();
3113 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003114
3115 if (interactive && check_terminating(buf) > 0)
3116 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003117 }
3118 } else {
3119 printf("Could not read pending message.\n");
3120 break;
3121 }
3122 }
3123
3124 if (wpa_ctrl_pending(ctrl) < 0) {
3125 printf("Connection to wpa_supplicant lost - trying to "
3126 "reconnect\n");
3127 wpa_cli_reconnect();
3128 }
3129}
3130
3131#define max_args 10
3132
3133static int tokenize_cmd(char *cmd, char *argv[])
3134{
3135 char *pos;
3136 int argc = 0;
3137
3138 pos = cmd;
3139 for (;;) {
3140 while (*pos == ' ')
3141 pos++;
3142 if (*pos == '\0')
3143 break;
3144 argv[argc] = pos;
3145 argc++;
3146 if (argc == max_args)
3147 break;
3148 if (*pos == '"') {
3149 char *pos2 = os_strrchr(pos, '"');
3150 if (pos2)
3151 pos = pos2 + 1;
3152 }
3153 while (*pos != '\0' && *pos != ' ')
3154 pos++;
3155 if (*pos == ' ')
3156 *pos++ = '\0';
3157 }
3158
3159 return argc;
3160}
3161
3162
3163static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3164{
3165 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3166 printf("Connection to wpa_supplicant lost - trying to "
3167 "reconnect\n");
3168 wpa_cli_close_connection();
3169 }
3170 if (!ctrl_conn)
3171 wpa_cli_reconnect();
3172 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3173}
3174
3175
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003176static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3177{
3178 wpa_cli_recv_pending(mon_conn, 0);
3179}
3180
3181
3182static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3183{
3184 char *argv[max_args];
3185 int argc;
3186 argc = tokenize_cmd(cmd, argv);
3187 if (argc)
3188 wpa_request(ctrl_conn, argc, argv);
3189}
3190
3191
3192static void wpa_cli_edit_eof_cb(void *ctx)
3193{
3194 eloop_terminate();
3195}
3196
3197
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003198static int warning_displayed = 0;
3199static char *hfile = NULL;
3200static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003201
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003202static void start_edit(void)
3203{
3204 char *home;
3205 char *ps = NULL;
3206
3207#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3208 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3209#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003210
3211 home = getenv("HOME");
3212 if (home) {
3213 const char *fname = ".wpa_cli_history";
3214 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3215 hfile = os_malloc(hfile_len);
3216 if (hfile)
3217 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3218 }
3219
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003220 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3221 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3222 eloop_terminate();
3223 return;
3224 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003225
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003226 edit_started = 1;
3227 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3228}
3229
3230
3231static void try_connection(void *eloop_ctx, void *timeout_ctx)
3232{
3233 if (ctrl_ifname == NULL)
3234 ctrl_ifname = wpa_cli_get_default_ifname();
3235
3236 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3237 if (!warning_displayed) {
3238 printf("Could not connect to wpa_supplicant: "
3239 "%s - re-trying\n", ctrl_ifname);
3240 warning_displayed = 1;
3241 }
3242 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3243 return;
3244 }
3245
3246 if (warning_displayed)
3247 printf("Connection established.\n");
3248
3249 start_edit();
3250}
3251
3252
3253static void wpa_cli_interactive(void)
3254{
3255 printf("\nInteractive mode\n\n");
3256
3257 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003258 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003259 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003260
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003261 cli_txt_list_flush(&p2p_peers);
3262 cli_txt_list_flush(&p2p_groups);
3263 cli_txt_list_flush(&bsses);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003264 if (edit_started)
3265 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003266 os_free(hfile);
3267 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3268 wpa_cli_close_connection();
3269}
3270
3271
3272static void wpa_cli_action(struct wpa_ctrl *ctrl)
3273{
3274#ifdef CONFIG_ANSI_C_EXTRA
3275 /* TODO: ANSI C version(?) */
3276 printf("Action processing not supported in ANSI C build.\n");
3277#else /* CONFIG_ANSI_C_EXTRA */
3278 fd_set rfds;
3279 int fd, res;
3280 struct timeval tv;
3281 char buf[256]; /* note: large enough to fit in unsolicited messages */
3282 size_t len;
3283
3284 fd = wpa_ctrl_get_fd(ctrl);
3285
3286 while (!wpa_cli_quit) {
3287 FD_ZERO(&rfds);
3288 FD_SET(fd, &rfds);
3289 tv.tv_sec = ping_interval;
3290 tv.tv_usec = 0;
3291 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3292 if (res < 0 && errno != EINTR) {
3293 perror("select");
3294 break;
3295 }
3296
3297 if (FD_ISSET(fd, &rfds))
3298 wpa_cli_recv_pending(ctrl, 1);
3299 else {
3300 /* verify that connection is still working */
3301 len = sizeof(buf) - 1;
3302 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3303 wpa_cli_action_cb) < 0 ||
3304 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3305 printf("wpa_supplicant did not reply to PING "
3306 "command - exiting\n");
3307 break;
3308 }
3309 }
3310 }
3311#endif /* CONFIG_ANSI_C_EXTRA */
3312}
3313
3314
3315static void wpa_cli_cleanup(void)
3316{
3317 wpa_cli_close_connection();
3318 if (pid_file)
3319 os_daemonize_terminate(pid_file);
3320
3321 os_program_deinit();
3322}
3323
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003324
3325static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003326{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003327 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003328}
3329
3330
3331static char * wpa_cli_get_default_ifname(void)
3332{
3333 char *ifname = NULL;
3334
3335#ifdef CONFIG_CTRL_IFACE_UNIX
3336 struct dirent *dent;
3337 DIR *dir = opendir(ctrl_iface_dir);
3338 if (!dir) {
3339#ifdef ANDROID
3340 char ifprop[PROPERTY_VALUE_MAX];
3341 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3342 ifname = os_strdup(ifprop);
3343 printf("Using interface '%s'\n", ifname);
3344 return ifname;
3345 }
3346#endif /* ANDROID */
3347 return NULL;
3348 }
3349 while ((dent = readdir(dir))) {
3350#ifdef _DIRENT_HAVE_D_TYPE
3351 /*
3352 * Skip the file if it is not a socket. Also accept
3353 * DT_UNKNOWN (0) in case the C library or underlying
3354 * file system does not support d_type.
3355 */
3356 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3357 continue;
3358#endif /* _DIRENT_HAVE_D_TYPE */
3359 if (os_strcmp(dent->d_name, ".") == 0 ||
3360 os_strcmp(dent->d_name, "..") == 0)
3361 continue;
3362 printf("Selected interface '%s'\n", dent->d_name);
3363 ifname = os_strdup(dent->d_name);
3364 break;
3365 }
3366 closedir(dir);
3367#endif /* CONFIG_CTRL_IFACE_UNIX */
3368
3369#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003370#ifdef ANDROID
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -07003371 char buf[4096], *pos;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003372#else
3373 char buf[2048], *pos;
3374#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003375 size_t len;
3376 struct wpa_ctrl *ctrl;
3377 int ret;
3378
3379 ctrl = wpa_ctrl_open(NULL);
3380 if (ctrl == NULL)
3381 return NULL;
3382
3383 len = sizeof(buf) - 1;
3384 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3385 if (ret >= 0) {
3386 buf[len] = '\0';
3387 pos = os_strchr(buf, '\n');
3388 if (pos)
3389 *pos = '\0';
3390 ifname = os_strdup(buf);
3391 }
3392 wpa_ctrl_close(ctrl);
3393#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3394
3395 return ifname;
3396}
3397
3398
3399int main(int argc, char *argv[])
3400{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003401 int c;
3402 int daemonize = 0;
3403 int ret = 0;
3404 const char *global = NULL;
3405
3406 if (os_program_init())
3407 return -1;
3408
3409 for (;;) {
3410 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3411 if (c < 0)
3412 break;
3413 switch (c) {
3414 case 'a':
3415 action_file = optarg;
3416 break;
3417 case 'B':
3418 daemonize = 1;
3419 break;
3420 case 'g':
3421 global = optarg;
3422 break;
3423 case 'G':
3424 ping_interval = atoi(optarg);
3425 break;
3426 case 'h':
3427 usage();
3428 return 0;
3429 case 'v':
3430 printf("%s\n", wpa_cli_version);
3431 return 0;
3432 case 'i':
3433 os_free(ctrl_ifname);
3434 ctrl_ifname = os_strdup(optarg);
3435 break;
3436 case 'p':
3437 ctrl_iface_dir = optarg;
3438 break;
3439 case 'P':
3440 pid_file = optarg;
3441 break;
3442 default:
3443 usage();
3444 return -1;
3445 }
3446 }
3447
3448 interactive = (argc == optind) && (action_file == NULL);
3449
3450 if (interactive)
3451 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3452
3453 if (eloop_init())
3454 return -1;
3455
3456 if (global) {
3457#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3458 ctrl_conn = wpa_ctrl_open(NULL);
3459#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3460 ctrl_conn = wpa_ctrl_open(global);
3461#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3462 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003463 fprintf(stderr, "Failed to connect to wpa_supplicant "
3464 "global interface: %s error: %s\n",
3465 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003466 return -1;
3467 }
3468 }
3469
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003470 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003471
3472 if (ctrl_ifname == NULL)
3473 ctrl_ifname = wpa_cli_get_default_ifname();
3474
3475 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003476 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003477 } else {
3478 if (!global &&
3479 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003480 fprintf(stderr, "Failed to connect to non-global "
3481 "ctrl_ifname: %s error: %s\n",
3482 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003483 return -1;
3484 }
3485
3486 if (action_file) {
3487 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3488 wpa_cli_attached = 1;
3489 } else {
3490 printf("Warning: Failed to attach to "
3491 "wpa_supplicant.\n");
3492 return -1;
3493 }
3494 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003495
3496 if (daemonize && os_daemonize(pid_file))
3497 return -1;
3498
3499 if (action_file)
3500 wpa_cli_action(ctrl_conn);
3501 else
3502 ret = wpa_request(ctrl_conn, argc - optind,
3503 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003504 }
3505
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003506 os_free(ctrl_ifname);
3507 eloop_destroy();
3508 wpa_cli_cleanup();
3509
3510 return ret;
3511}
3512
3513#else /* CONFIG_CTRL_IFACE */
3514int main(int argc, char *argv[])
3515{
3516 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3517 return -1;
3518}
3519#endif /* CONFIG_CTRL_IFACE */