blob: 4e7c81ce762c7a4cbb12102f1e297b131adccb90 [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
Dmitry Shmidt04949592012-07-19 12:16:46 -0700765#ifdef CONFIG_WPS_NFC
766
767static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
768{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700769 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700770}
771
772
773static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
774 char *argv[])
775{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700776 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700777}
778
779
780static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
781 char *argv[])
782{
783 int ret;
784 char *buf;
785 size_t buflen;
786
787 if (argc != 1) {
788 printf("Invalid 'wps_nfc_tag_read' command - one argument "
789 "is required.\n");
790 return -1;
791 }
792
793 buflen = 18 + os_strlen(argv[0]);
794 buf = os_malloc(buflen);
795 if (buf == NULL)
796 return -1;
797 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
798
799 ret = wpa_ctrl_command(ctrl, buf);
800 os_free(buf);
801
802 return ret;
803}
804
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800805
806static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
807 char *argv[])
808{
809 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
810}
811
812
813static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
814 char *argv[])
815{
816 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
817}
818
819
820static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
821 char *argv[])
822{
823 int ret;
824 char *buf;
825 size_t buflen;
826
827 if (argc != 1) {
828 printf("Invalid 'nfc_rx_handover_req' command - one argument "
829 "is required.\n");
830 return -1;
831 }
832
833 buflen = 21 + os_strlen(argv[0]);
834 buf = os_malloc(buflen);
835 if (buf == NULL)
836 return -1;
837 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
838
839 ret = wpa_ctrl_command(ctrl, buf);
840 os_free(buf);
841
842 return ret;
843}
844
845
846static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
847 char *argv[])
848{
849 int ret;
850 char *buf;
851 size_t buflen;
852
853 if (argc != 1) {
854 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
855 "is required.\n");
856 return -1;
857 }
858
859 buflen = 21 + os_strlen(argv[0]);
860 buf = os_malloc(buflen);
861 if (buf == NULL)
862 return -1;
863 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
864
865 ret = wpa_ctrl_command(ctrl, buf);
866 os_free(buf);
867
868 return ret;
869}
870
Dmitry Shmidt04949592012-07-19 12:16:46 -0700871#endif /* CONFIG_WPS_NFC */
872
873
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700874static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
875{
876 char cmd[256];
877 int res;
878
879 if (argc == 2)
880 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
881 argv[0], argv[1]);
882 else if (argc == 5 || argc == 6) {
883 char ssid_hex[2 * 32 + 1];
884 char key_hex[2 * 64 + 1];
885 int i;
886
887 ssid_hex[0] = '\0';
888 for (i = 0; i < 32; i++) {
889 if (argv[2][i] == '\0')
890 break;
891 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
892 }
893
894 key_hex[0] = '\0';
895 if (argc == 6) {
896 for (i = 0; i < 64; i++) {
897 if (argv[5][i] == '\0')
898 break;
899 os_snprintf(&key_hex[i * 2], 3, "%02x",
900 argv[5][i]);
901 }
902 }
903
904 res = os_snprintf(cmd, sizeof(cmd),
905 "WPS_REG %s %s %s %s %s %s",
906 argv[0], argv[1], ssid_hex, argv[3], argv[4],
907 key_hex);
908 } else {
909 printf("Invalid WPS_REG command: need two arguments:\n"
910 "- BSSID of the target AP\n"
911 "- AP PIN\n");
912 printf("Alternatively, six arguments can be used to "
913 "reconfigure the AP:\n"
914 "- BSSID of the target AP\n"
915 "- AP PIN\n"
916 "- new SSID\n"
917 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
918 "- new encr (NONE, WEP, TKIP, CCMP)\n"
919 "- new key\n");
920 return -1;
921 }
922
923 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
924 printf("Too long WPS_REG command.\n");
925 return -1;
926 }
927 return wpa_ctrl_command(ctrl, cmd);
928}
929
930
931static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
932 char *argv[])
933{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700934 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700935}
936
937
938static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
939 char *argv[])
940{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700941 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700942}
943
944
945static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
946 char *argv[])
947{
948 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
949
950}
951
952
953static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
954 char *argv[])
955{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700956 if (argc < 2) {
957 printf("Invalid WPS_ER_PIN command: need at least two "
958 "arguments:\n"
959 "- UUID: use 'any' to select any\n"
960 "- PIN: Enrollee PIN\n"
961 "optional: - Enrollee MAC address\n");
962 return -1;
963 }
964
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700965 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700966}
967
968
969static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
970 char *argv[])
971{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700972 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700973}
974
975
976static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
977 char *argv[])
978{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979 if (argc != 2) {
980 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
981 "- UUID: specify which AP to use\n"
982 "- PIN: AP PIN\n");
983 return -1;
984 }
985
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700986 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700987}
988
989
990static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
991 char *argv[])
992{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993 if (argc != 2) {
994 printf("Invalid WPS_ER_SET_CONFIG command: need two "
995 "arguments:\n"
996 "- UUID: specify which AP to use\n"
997 "- Network configuration id\n");
998 return -1;
999 }
1000
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001001 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002}
1003
1004
1005static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1006 char *argv[])
1007{
1008 char cmd[256];
1009 int res;
1010
1011 if (argc == 5 || argc == 6) {
1012 char ssid_hex[2 * 32 + 1];
1013 char key_hex[2 * 64 + 1];
1014 int i;
1015
1016 ssid_hex[0] = '\0';
1017 for (i = 0; i < 32; i++) {
1018 if (argv[2][i] == '\0')
1019 break;
1020 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1021 }
1022
1023 key_hex[0] = '\0';
1024 if (argc == 6) {
1025 for (i = 0; i < 64; i++) {
1026 if (argv[5][i] == '\0')
1027 break;
1028 os_snprintf(&key_hex[i * 2], 3, "%02x",
1029 argv[5][i]);
1030 }
1031 }
1032
1033 res = os_snprintf(cmd, sizeof(cmd),
1034 "WPS_ER_CONFIG %s %s %s %s %s %s",
1035 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1036 key_hex);
1037 } else {
1038 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1039 "- AP UUID\n"
1040 "- AP PIN\n"
1041 "- new SSID\n"
1042 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1043 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1044 "- new key\n");
1045 return -1;
1046 }
1047
1048 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1049 printf("Too long WPS_ER_CONFIG command.\n");
1050 return -1;
1051 }
1052 return wpa_ctrl_command(ctrl, cmd);
1053}
1054
1055
Dmitry Shmidt04949592012-07-19 12:16:46 -07001056#ifdef CONFIG_WPS_NFC
1057static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1058 char *argv[])
1059{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001060 if (argc != 2) {
1061 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1062 "arguments:\n"
1063 "- WPS/NDEF: token format\n"
1064 "- UUID: specify which AP to use\n");
1065 return -1;
1066 }
1067
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001068 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001069}
1070#endif /* CONFIG_WPS_NFC */
1071
1072
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001073static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1074{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001075 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001076}
1077
1078
1079static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1080{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001081 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001082}
1083
1084
1085static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1086{
1087 char cmd[256], *pos, *end;
1088 int i, ret;
1089
1090 if (argc < 2) {
1091 printf("Invalid IDENTITY command: needs two arguments "
1092 "(network id and identity)\n");
1093 return -1;
1094 }
1095
1096 end = cmd + sizeof(cmd);
1097 pos = cmd;
1098 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1099 argv[0], argv[1]);
1100 if (ret < 0 || ret >= end - pos) {
1101 printf("Too long IDENTITY command.\n");
1102 return -1;
1103 }
1104 pos += ret;
1105 for (i = 2; i < argc; i++) {
1106 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1107 if (ret < 0 || ret >= end - pos) {
1108 printf("Too long IDENTITY command.\n");
1109 return -1;
1110 }
1111 pos += ret;
1112 }
1113
1114 return wpa_ctrl_command(ctrl, cmd);
1115}
1116
1117
1118static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1119{
1120 char cmd[256], *pos, *end;
1121 int i, ret;
1122
1123 if (argc < 2) {
1124 printf("Invalid PASSWORD command: needs two arguments "
1125 "(network id and password)\n");
1126 return -1;
1127 }
1128
1129 end = cmd + sizeof(cmd);
1130 pos = cmd;
1131 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1132 argv[0], argv[1]);
1133 if (ret < 0 || ret >= end - pos) {
1134 printf("Too long PASSWORD command.\n");
1135 return -1;
1136 }
1137 pos += ret;
1138 for (i = 2; i < argc; i++) {
1139 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1140 if (ret < 0 || ret >= end - pos) {
1141 printf("Too long PASSWORD command.\n");
1142 return -1;
1143 }
1144 pos += ret;
1145 }
1146
1147 return wpa_ctrl_command(ctrl, cmd);
1148}
1149
1150
1151static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1152 char *argv[])
1153{
1154 char cmd[256], *pos, *end;
1155 int i, ret;
1156
1157 if (argc < 2) {
1158 printf("Invalid NEW_PASSWORD command: needs two arguments "
1159 "(network id and password)\n");
1160 return -1;
1161 }
1162
1163 end = cmd + sizeof(cmd);
1164 pos = cmd;
1165 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1166 argv[0], argv[1]);
1167 if (ret < 0 || ret >= end - pos) {
1168 printf("Too long NEW_PASSWORD command.\n");
1169 return -1;
1170 }
1171 pos += ret;
1172 for (i = 2; i < argc; i++) {
1173 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1174 if (ret < 0 || ret >= end - pos) {
1175 printf("Too long NEW_PASSWORD command.\n");
1176 return -1;
1177 }
1178 pos += ret;
1179 }
1180
1181 return wpa_ctrl_command(ctrl, cmd);
1182}
1183
1184
1185static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1186{
1187 char cmd[256], *pos, *end;
1188 int i, ret;
1189
1190 if (argc < 2) {
1191 printf("Invalid PIN command: needs two arguments "
1192 "(network id and pin)\n");
1193 return -1;
1194 }
1195
1196 end = cmd + sizeof(cmd);
1197 pos = cmd;
1198 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1199 argv[0], argv[1]);
1200 if (ret < 0 || ret >= end - pos) {
1201 printf("Too long PIN command.\n");
1202 return -1;
1203 }
1204 pos += ret;
1205 for (i = 2; i < argc; i++) {
1206 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1207 if (ret < 0 || ret >= end - pos) {
1208 printf("Too long PIN command.\n");
1209 return -1;
1210 }
1211 pos += ret;
1212 }
1213 return wpa_ctrl_command(ctrl, cmd);
1214}
1215
1216
1217static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1218{
1219 char cmd[256], *pos, *end;
1220 int i, ret;
1221
1222 if (argc < 2) {
1223 printf("Invalid OTP command: needs two arguments (network "
1224 "id and password)\n");
1225 return -1;
1226 }
1227
1228 end = cmd + sizeof(cmd);
1229 pos = cmd;
1230 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1231 argv[0], argv[1]);
1232 if (ret < 0 || ret >= end - pos) {
1233 printf("Too long OTP command.\n");
1234 return -1;
1235 }
1236 pos += ret;
1237 for (i = 2; i < argc; i++) {
1238 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1239 if (ret < 0 || ret >= end - pos) {
1240 printf("Too long OTP command.\n");
1241 return -1;
1242 }
1243 pos += ret;
1244 }
1245
1246 return wpa_ctrl_command(ctrl, cmd);
1247}
1248
1249
1250static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1251 char *argv[])
1252{
1253 char cmd[256], *pos, *end;
1254 int i, ret;
1255
1256 if (argc < 2) {
1257 printf("Invalid PASSPHRASE command: needs two arguments "
1258 "(network id and passphrase)\n");
1259 return -1;
1260 }
1261
1262 end = cmd + sizeof(cmd);
1263 pos = cmd;
1264 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1265 argv[0], argv[1]);
1266 if (ret < 0 || ret >= end - pos) {
1267 printf("Too long PASSPHRASE command.\n");
1268 return -1;
1269 }
1270 pos += ret;
1271 for (i = 2; i < argc; i++) {
1272 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1273 if (ret < 0 || ret >= end - pos) {
1274 printf("Too long PASSPHRASE command.\n");
1275 return -1;
1276 }
1277 pos += ret;
1278 }
1279
1280 return wpa_ctrl_command(ctrl, cmd);
1281}
1282
1283
1284static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1285{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001286 if (argc < 2) {
1287 printf("Invalid BSSID command: needs two arguments (network "
1288 "id and BSSID)\n");
1289 return -1;
1290 }
1291
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001292 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001293}
1294
1295
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001296static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1297{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001298 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001299}
1300
1301
1302static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1303{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001304 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001305}
1306
1307
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001308static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1309 char *argv[])
1310{
1311 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1312}
1313
1314
1315static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1316 char *argv[])
1317{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001318 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001319}
1320
1321
1322static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1323 char *argv[])
1324{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001325 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001326}
1327
1328
1329static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1330 char *argv[])
1331{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001332 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001333}
1334
1335
1336static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1337 char *argv[])
1338{
1339 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1340}
1341
1342
1343static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1344 char *argv[])
1345{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001346 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001347}
1348
1349
1350static void wpa_cli_show_network_variables(void)
1351{
1352 printf("set_network variables:\n"
1353 " ssid (network name, SSID)\n"
1354 " psk (WPA passphrase or pre-shared key)\n"
1355 " key_mgmt (key management protocol)\n"
1356 " identity (EAP identity)\n"
1357 " password (EAP password)\n"
1358 " ...\n"
1359 "\n"
1360 "Note: Values are entered in the same format as the "
1361 "configuration file is using,\n"
1362 "i.e., strings values need to be inside double quotation "
1363 "marks.\n"
1364 "For example: set_network 1 ssid \"network name\"\n"
1365 "\n"
1366 "Please see wpa_supplicant.conf documentation for full list "
1367 "of\navailable variables.\n");
1368}
1369
1370
1371static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1372 char *argv[])
1373{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001374 if (argc == 0) {
1375 wpa_cli_show_network_variables();
1376 return 0;
1377 }
1378
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001379 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001380 printf("Invalid SET_NETWORK command: needs three arguments\n"
1381 "(network id, variable name, and value)\n");
1382 return -1;
1383 }
1384
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001385 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001386}
1387
1388
1389static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1390 char *argv[])
1391{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392 if (argc == 0) {
1393 wpa_cli_show_network_variables();
1394 return 0;
1395 }
1396
1397 if (argc != 2) {
1398 printf("Invalid GET_NETWORK command: needs two arguments\n"
1399 "(network id and variable name)\n");
1400 return -1;
1401 }
1402
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001403 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001404}
1405
1406
Dmitry Shmidt04949592012-07-19 12:16:46 -07001407static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1408 char *argv[])
1409{
1410 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1411}
1412
1413
1414static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1415{
1416 return wpa_ctrl_command(ctrl, "ADD_CRED");
1417}
1418
1419
1420static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1421 char *argv[])
1422{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001423 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001424}
1425
1426
1427static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1428{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001429 if (argc != 3) {
1430 printf("Invalid SET_CRED command: needs three arguments\n"
1431 "(cred id, variable name, and value)\n");
1432 return -1;
1433 }
1434
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001435 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001436}
1437
1438
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001439static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1440 char *argv[])
1441{
1442 return wpa_ctrl_command(ctrl, "DISCONNECT");
1443}
1444
1445
1446static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1447 char *argv[])
1448{
1449 return wpa_ctrl_command(ctrl, "RECONNECT");
1450}
1451
1452
1453static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1454 char *argv[])
1455{
1456 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1457}
1458
1459
1460static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1461{
1462 return wpa_ctrl_command(ctrl, "SCAN");
1463}
1464
1465
1466static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1467 char *argv[])
1468{
1469 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1470}
1471
1472
1473static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1474{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001475 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001476}
1477
1478
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001479static char ** wpa_cli_complete_bss(const char *str, int pos)
1480{
1481 int arg = get_cmd_arg_num(str, pos);
1482 char **res = NULL;
1483
1484 switch (arg) {
1485 case 1:
1486 res = cli_txt_list_array(&bsses);
1487 break;
1488 }
1489
1490 return res;
1491}
1492
1493
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001494static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1495 char *argv[])
1496{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001497 if (argc < 1 || argc > 2) {
1498 printf("Invalid GET_CAPABILITY command: need either one or "
1499 "two arguments\n");
1500 return -1;
1501 }
1502
1503 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1504 printf("Invalid GET_CAPABILITY command: second argument, "
1505 "if any, must be 'strict'\n");
1506 return -1;
1507 }
1508
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001509 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001510}
1511
1512
1513static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1514{
1515 printf("Available interfaces:\n");
1516 return wpa_ctrl_command(ctrl, "INTERFACES");
1517}
1518
1519
1520static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1521{
1522 if (argc < 1) {
1523 wpa_cli_list_interfaces(ctrl);
1524 return 0;
1525 }
1526
1527 wpa_cli_close_connection();
1528 os_free(ctrl_ifname);
1529 ctrl_ifname = os_strdup(argv[0]);
1530
1531 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1532 printf("Connected to interface '%s.\n", ctrl_ifname);
1533 } else {
1534 printf("Could not connect to interface '%s' - re-trying\n",
1535 ctrl_ifname);
1536 }
1537 return 0;
1538}
1539
1540
1541static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1542 char *argv[])
1543{
1544 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1545}
1546
1547
1548static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1549 char *argv[])
1550{
1551 return wpa_ctrl_command(ctrl, "TERMINATE");
1552}
1553
1554
1555static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1556 char *argv[])
1557{
1558 char cmd[256];
1559 int res;
1560
1561 if (argc < 1) {
1562 printf("Invalid INTERFACE_ADD command: needs at least one "
1563 "argument (interface name)\n"
1564 "All arguments: ifname confname driver ctrl_interface "
1565 "driver_param bridge_name\n");
1566 return -1;
1567 }
1568
1569 /*
1570 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1571 * <driver_param>TAB<bridge_name>
1572 */
1573 res = os_snprintf(cmd, sizeof(cmd),
1574 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1575 argv[0],
1576 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1577 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1578 argc > 5 ? argv[5] : "");
1579 if (res < 0 || (size_t) res >= sizeof(cmd))
1580 return -1;
1581 cmd[sizeof(cmd) - 1] = '\0';
1582 return wpa_ctrl_command(ctrl, cmd);
1583}
1584
1585
1586static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1587 char *argv[])
1588{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001589 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001590}
1591
1592
1593static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1594 char *argv[])
1595{
1596 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1597}
1598
1599
1600#ifdef CONFIG_AP
1601static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1602{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001603 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001604}
1605
1606
1607static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1608 char *addr, size_t addr_len)
1609{
1610 char buf[4096], *pos;
1611 size_t len;
1612 int ret;
1613
1614 if (ctrl_conn == NULL) {
1615 printf("Not connected to hostapd - command dropped.\n");
1616 return -1;
1617 }
1618 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001619 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001620 wpa_cli_msg_cb);
1621 if (ret == -2) {
1622 printf("'%s' command timed out.\n", cmd);
1623 return -2;
1624 } else if (ret < 0) {
1625 printf("'%s' command failed.\n", cmd);
1626 return -1;
1627 }
1628
1629 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001630 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001631 return -1;
1632 printf("%s", buf);
1633
1634 pos = buf;
1635 while (*pos != '\0' && *pos != '\n')
1636 pos++;
1637 *pos = '\0';
1638 os_strlcpy(addr, buf, addr_len);
1639 return 0;
1640}
1641
1642
1643static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1644{
1645 char addr[32], cmd[64];
1646
1647 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1648 return 0;
1649 do {
1650 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1651 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1652
1653 return -1;
1654}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001655
1656
1657static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1658 char *argv[])
1659{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001660 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001661}
1662
1663
1664static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1665 char *argv[])
1666{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001667 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001668}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001669#endif /* CONFIG_AP */
1670
1671
1672static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1673{
1674 return wpa_ctrl_command(ctrl, "SUSPEND");
1675}
1676
1677
1678static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1679{
1680 return wpa_ctrl_command(ctrl, "RESUME");
1681}
1682
1683
1684static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1685{
1686 return wpa_ctrl_command(ctrl, "DROP_SA");
1687}
1688
1689
1690static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1691{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001692 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001693}
1694
1695
1696#ifdef CONFIG_P2P
1697
1698static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1699{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001700 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1701}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001702
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001703
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001704static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1705{
1706 char **res = NULL;
1707 int arg = get_cmd_arg_num(str, pos);
1708
1709 res = os_calloc(6, sizeof(char *));
1710 if (res == NULL)
1711 return NULL;
1712 res[0] = os_strdup("type=social");
1713 if (res[0] == NULL) {
1714 os_free(res);
1715 return NULL;
1716 }
1717 res[1] = os_strdup("type=progressive");
1718 if (res[1] == NULL)
1719 return res;
1720 res[2] = os_strdup("delay=");
1721 if (res[2] == NULL)
1722 return res;
1723 res[3] = os_strdup("dev_id=");
1724 if (res[3] == NULL)
1725 return res;
1726 if (arg == 1)
1727 res[4] = os_strdup("[timeout]");
1728
1729 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001730}
1731
1732
1733static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1734 char *argv[])
1735{
1736 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1737}
1738
1739
1740static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1741 char *argv[])
1742{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001743 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001744}
1745
1746
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001747static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1748{
1749 int arg = get_cmd_arg_num(str, pos);
1750 char **res = NULL;
1751
1752 switch (arg) {
1753 case 1:
1754 res = cli_txt_list_array(&p2p_peers);
1755 break;
1756 }
1757
1758 return res;
1759}
1760
1761
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001762static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1763 char *argv[])
1764{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001765 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001766}
1767
1768
1769static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1770 char *argv[])
1771{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001772 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001773}
1774
1775
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001776static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1777{
1778 int arg = get_cmd_arg_num(str, pos);
1779 char **res = NULL;
1780
1781 switch (arg) {
1782 case 1:
1783 res = cli_txt_list_array(&p2p_groups);
1784 break;
1785 }
1786
1787 return res;
1788}
1789
1790
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001791static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1792 char *argv[])
1793{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001794 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001795}
1796
1797
1798static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1799 char *argv[])
1800{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001801 if (argc != 2 && argc != 3) {
1802 printf("Invalid P2P_PROV_DISC command: needs at least "
1803 "two arguments, address and config method\n"
1804 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001805 return -1;
1806 }
1807
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001808 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001809}
1810
1811
1812static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1813 char *argv[])
1814{
1815 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1816}
1817
1818
1819static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1820 char *argv[])
1821{
1822 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001823
1824 if (argc != 2 && argc != 4) {
1825 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1826 "arguments (address and TLVs) or four arguments "
1827 "(address, \"upnp\", version, search target "
1828 "(SSDP ST:)\n");
1829 return -1;
1830 }
1831
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001832 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001833 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834 return wpa_ctrl_command(ctrl, cmd);
1835}
1836
1837
1838static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1839 int argc, char *argv[])
1840{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001841 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001842}
1843
1844
1845static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1846 char *argv[])
1847{
1848 char cmd[4096];
1849 int res;
1850
1851 if (argc != 4) {
1852 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1853 "arguments (freq, address, dialog token, and TLVs)\n");
1854 return -1;
1855 }
1856
1857 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1858 argv[0], argv[1], argv[2], argv[3]);
1859 if (res < 0 || (size_t) res >= sizeof(cmd))
1860 return -1;
1861 cmd[sizeof(cmd) - 1] = '\0';
1862 return wpa_ctrl_command(ctrl, cmd);
1863}
1864
1865
1866static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1867 char *argv[])
1868{
1869 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1870}
1871
1872
1873static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1874 int argc, char *argv[])
1875{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001876 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001877}
1878
1879
1880static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1881 char *argv[])
1882{
1883 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1884}
1885
1886
1887static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1888 char *argv[])
1889{
1890 char cmd[4096];
1891 int res;
1892
1893 if (argc != 3 && argc != 4) {
1894 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1895 "arguments\n");
1896 return -1;
1897 }
1898
1899 if (argc == 4)
1900 res = os_snprintf(cmd, sizeof(cmd),
1901 "P2P_SERVICE_ADD %s %s %s %s",
1902 argv[0], argv[1], argv[2], argv[3]);
1903 else
1904 res = os_snprintf(cmd, sizeof(cmd),
1905 "P2P_SERVICE_ADD %s %s %s",
1906 argv[0], argv[1], argv[2]);
1907 if (res < 0 || (size_t) res >= sizeof(cmd))
1908 return -1;
1909 cmd[sizeof(cmd) - 1] = '\0';
1910 return wpa_ctrl_command(ctrl, cmd);
1911}
1912
1913
1914static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1915 char *argv[])
1916{
1917 char cmd[4096];
1918 int res;
1919
1920 if (argc != 2 && argc != 3) {
1921 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1922 "arguments\n");
1923 return -1;
1924 }
1925
1926 if (argc == 3)
1927 res = os_snprintf(cmd, sizeof(cmd),
1928 "P2P_SERVICE_DEL %s %s %s",
1929 argv[0], argv[1], argv[2]);
1930 else
1931 res = os_snprintf(cmd, sizeof(cmd),
1932 "P2P_SERVICE_DEL %s %s",
1933 argv[0], argv[1]);
1934 if (res < 0 || (size_t) res >= sizeof(cmd))
1935 return -1;
1936 cmd[sizeof(cmd) - 1] = '\0';
1937 return wpa_ctrl_command(ctrl, cmd);
1938}
1939
1940
1941static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1942 int argc, char *argv[])
1943{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001944 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001945}
1946
1947
1948static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1949 int argc, char *argv[])
1950{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001951 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001952}
1953
1954
1955static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1956{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001957 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001958}
1959
1960
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001961static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1962{
1963 int arg = get_cmd_arg_num(str, pos);
1964 char **res = NULL;
1965
1966 switch (arg) {
1967 case 1:
1968 res = cli_txt_list_array(&p2p_peers);
1969 break;
1970 }
1971
1972 return res;
1973}
1974
1975
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001976static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1977 char *addr, size_t addr_len,
1978 int discovered)
1979{
1980 char buf[4096], *pos;
1981 size_t len;
1982 int ret;
1983
1984 if (ctrl_conn == NULL)
1985 return -1;
1986 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001987 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001988 wpa_cli_msg_cb);
1989 if (ret == -2) {
1990 printf("'%s' command timed out.\n", cmd);
1991 return -2;
1992 } else if (ret < 0) {
1993 printf("'%s' command failed.\n", cmd);
1994 return -1;
1995 }
1996
1997 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001998 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001999 return -1;
2000
2001 pos = buf;
2002 while (*pos != '\0' && *pos != '\n')
2003 pos++;
2004 *pos++ = '\0';
2005 os_strlcpy(addr, buf, addr_len);
2006 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2007 printf("%s\n", addr);
2008 return 0;
2009}
2010
2011
2012static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2013{
2014 char addr[32], cmd[64];
2015 int discovered;
2016
2017 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2018
2019 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2020 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002021 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022 do {
2023 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2024 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2025 discovered) == 0);
2026
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002027 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002028}
2029
2030
2031static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2032{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002033 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002034}
2035
2036
2037static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2038{
2039 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2040}
2041
2042
2043static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2044 char *argv[])
2045{
2046 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2047}
2048
2049
2050static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2051 char *argv[])
2052{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002053 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054}
2055
2056
2057static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2058 char *argv[])
2059{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002060 if (argc != 0 && argc != 2 && argc != 4) {
2061 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2062 "(preferred duration, interval; in microsecods).\n"
2063 "Optional second pair can be used to provide "
2064 "acceptable values.\n");
2065 return -1;
2066 }
2067
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002068 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002069}
2070
2071
2072static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2073 char *argv[])
2074{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002075 if (argc != 0 && argc != 2) {
2076 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2077 "(availability period, availability interval; in "
2078 "millisecods).\n"
2079 "Extended Listen Timing can be cancelled with this "
2080 "command when used without parameters.\n");
2081 return -1;
2082 }
2083
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002084 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2085}
2086
2087#endif /* CONFIG_P2P */
2088
2089#ifdef CONFIG_WIFI_DISPLAY
2090
2091static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2092 char *argv[])
2093{
2094 char cmd[100];
2095 int res;
2096
2097 if (argc != 1 && argc != 2) {
2098 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2099 "arguments (subelem, hexdump)\n");
2100 return -1;
2101 }
2102
2103 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2104 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002105 if (res < 0 || (size_t) res >= sizeof(cmd))
2106 return -1;
2107 cmd[sizeof(cmd) - 1] = '\0';
2108 return wpa_ctrl_command(ctrl, cmd);
2109}
2110
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002111
2112static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2113 char *argv[])
2114{
2115 char cmd[100];
2116 int res;
2117
2118 if (argc != 1) {
2119 printf("Invalid WFD_SUBELEM_GET command: needs one "
2120 "argument (subelem)\n");
2121 return -1;
2122 }
2123
2124 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2125 argv[0]);
2126 if (res < 0 || (size_t) res >= sizeof(cmd))
2127 return -1;
2128 cmd[sizeof(cmd) - 1] = '\0';
2129 return wpa_ctrl_command(ctrl, cmd);
2130}
2131#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002132
2133
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002134#ifdef CONFIG_INTERWORKING
2135static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2136 char *argv[])
2137{
2138 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2139}
2140
2141
2142static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2143 char *argv[])
2144{
2145 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2146}
2147
2148
2149static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2150 char *argv[])
2151{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002152 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002153}
2154
2155
2156static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2157 char *argv[])
2158{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002159 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002160}
2161
2162
2163static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2164{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002165 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2166}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002167
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002168
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002169static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2170 char *argv[])
2171{
2172 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2173}
2174
2175
2176static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2177 char *argv[])
2178{
2179 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002180}
2181#endif /* CONFIG_INTERWORKING */
2182
2183
Dmitry Shmidt04949592012-07-19 12:16:46 -07002184#ifdef CONFIG_HS20
2185
2186static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2187 char *argv[])
2188{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002189 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002190}
2191
2192
2193static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2194 char *argv[])
2195{
2196 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002197
2198 if (argc == 0) {
2199 printf("Command needs one or two arguments (dst mac addr and "
2200 "optional home realm)\n");
2201 return -1;
2202 }
2203
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002204 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2205 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002206 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002207
2208 return wpa_ctrl_command(ctrl, cmd);
2209}
2210
2211#endif /* CONFIG_HS20 */
2212
2213
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002214static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2215 char *argv[])
2216{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002217 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002218}
2219
2220
2221static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2222 char *argv[])
2223{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002224 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002225}
2226
2227
2228static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2229 char *argv[])
2230{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002231 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002232}
2233
2234
2235static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2236 char *argv[])
2237{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002238 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002239}
2240
2241
2242static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2243 char *argv[])
2244{
2245 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2246}
2247
2248
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002249static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2250 char *argv[])
2251{
2252 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2253}
2254
2255
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002256static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2257 char *argv[])
2258{
2259 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2260}
2261
Dmitry Shmidt04949592012-07-19 12:16:46 -07002262
2263#ifdef CONFIG_AUTOSCAN
2264
2265static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2266{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002267 if (argc == 0)
2268 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2269
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002270 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002271}
2272
2273#endif /* CONFIG_AUTOSCAN */
2274
2275
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002276static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2277{
2278 if (argc == 0)
2279 return -1;
2280 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2281}
2282
2283
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002284#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002285static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2286{
2287 char cmd[256];
2288 int i;
2289 int len;
2290
2291 if (argc < 1) {
2292 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2293 return -1;
2294 }
2295
2296 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2297 for (i=1; i < argc; i++)
2298 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2299 cmd[sizeof(cmd) - 1] = '\0';
2300 printf("%s: %s\n", __func__, cmd);
2301 return wpa_ctrl_command(ctrl, cmd);
2302}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002303#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002304
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002305
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002306enum wpa_cli_cmd_flags {
2307 cli_cmd_flag_none = 0x00,
2308 cli_cmd_flag_sensitive = 0x01
2309};
2310
2311struct wpa_cli_cmd {
2312 const char *cmd;
2313 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002314 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002315 enum wpa_cli_cmd_flags flags;
2316 const char *usage;
2317};
2318
2319static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002320 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002321 cli_cmd_flag_none,
2322 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002323 { "ifname", wpa_cli_cmd_ifname, NULL,
2324 cli_cmd_flag_none,
2325 "= get current interface name" },
2326 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002327 cli_cmd_flag_none,
2328 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002329 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002330 cli_cmd_flag_none,
2331 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002332 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333 cli_cmd_flag_none,
2334 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002335 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002336 cli_cmd_flag_none,
2337 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002338 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002339 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002340 "[command] = show usage help" },
2341 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002342 cli_cmd_flag_none,
2343 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002344 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002345 cli_cmd_flag_none,
2346 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002347 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002348 cli_cmd_flag_none,
2349 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002350 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002351 cli_cmd_flag_none,
2352 "= exit wpa_cli" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002353 { "set", wpa_cli_cmd_set, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002354 cli_cmd_flag_none,
2355 "= set variables (shows list of variables when run without "
2356 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002357 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002358 cli_cmd_flag_none,
2359 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002360 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002361 cli_cmd_flag_none,
2362 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002363 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002364 cli_cmd_flag_none,
2365 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002366 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002367 cli_cmd_flag_none,
2368 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002369 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002370 cli_cmd_flag_none,
2371 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002372 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002373 cli_cmd_flag_none,
2374 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002375 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002376 cli_cmd_flag_none,
2377 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002378 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002379 cli_cmd_flag_sensitive,
2380 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002381 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002382 cli_cmd_flag_sensitive,
2383 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002384 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002385 cli_cmd_flag_sensitive,
2386 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002387 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002388 cli_cmd_flag_sensitive,
2389 "<network id> <password> = configure one-time-password for an SSID"
2390 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002391 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002392 cli_cmd_flag_sensitive,
2393 "<network id> <passphrase> = configure private key passphrase\n"
2394 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002395 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002396 cli_cmd_flag_none,
2397 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002398 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002399 cli_cmd_flag_none,
2400 "<BSSID> = add a BSSID to the blacklist\n"
2401 "blacklist clear = clear the blacklist\n"
2402 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002403 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002404 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002405 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002406 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002407 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002408 cli_cmd_flag_none,
2409 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002410 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002411 cli_cmd_flag_none,
2412 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002413 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002414 cli_cmd_flag_none,
2415 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002416 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002417 cli_cmd_flag_none,
2418 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002419 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002420 cli_cmd_flag_none,
2421 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002422 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002423 cli_cmd_flag_none,
2424 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002425 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002426 cli_cmd_flag_sensitive,
2427 "<network id> <variable> <value> = set network variables (shows\n"
2428 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002429 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002430 cli_cmd_flag_none,
2431 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002432 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002433 cli_cmd_flag_none,
2434 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002435 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002436 cli_cmd_flag_none,
2437 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002438 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002439 cli_cmd_flag_none,
2440 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002441 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002442 cli_cmd_flag_sensitive,
2443 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002444 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002445 cli_cmd_flag_none,
2446 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002447 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002448 cli_cmd_flag_none,
2449 "= disconnect and wait for reassociate/reconnect command before\n"
2450 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002451 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002452 cli_cmd_flag_none,
2453 "= like reassociate, but only takes effect if already disconnected"
2454 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002455 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002456 cli_cmd_flag_none,
2457 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002458 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002459 cli_cmd_flag_none,
2460 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002461 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002462 cli_cmd_flag_none,
2463 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002464 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002465 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002466 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels> "
2467 "= get capabilies" },
2468 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002469 cli_cmd_flag_none,
2470 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002471 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002472 cli_cmd_flag_none,
2473 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002474 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002475 cli_cmd_flag_none,
2476 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2477 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2478 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002479 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002480 cli_cmd_flag_none,
2481 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002482 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002483 cli_cmd_flag_none,
2484 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002485 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002486 cli_cmd_flag_none,
2487 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002488 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489 cli_cmd_flag_none,
2490 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002491 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 cli_cmd_flag_none,
2493 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002494 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002495 cli_cmd_flag_none,
2496 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002497 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002498 cli_cmd_flag_none,
2499 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002500 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002501 cli_cmd_flag_none,
2502 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002503 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002504 cli_cmd_flag_none,
2505 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002506 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507 cli_cmd_flag_none,
2508 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002509 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002510 cli_cmd_flag_sensitive,
2511 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2512 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002513 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514 cli_cmd_flag_sensitive,
2515 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002516 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002518#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002519 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002520 cli_cmd_flag_none,
2521 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002522 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002523 cli_cmd_flag_none,
2524 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002525 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002526 cli_cmd_flag_sensitive,
2527 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002528 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2529 cli_cmd_flag_none,
2530 "<NDEF> <WPS> = create NFC handover request" },
2531 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2532 cli_cmd_flag_none,
2533 "<NDEF> <WPS> = create NFC handover select" },
2534 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2535 cli_cmd_flag_none,
2536 "<hexdump of payload> = report received NFC handover request" },
2537 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2538 cli_cmd_flag_none,
2539 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002540#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002541 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542 cli_cmd_flag_sensitive,
2543 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002544 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002545 cli_cmd_flag_sensitive,
2546 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002547 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002548 cli_cmd_flag_none,
2549 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002550 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002551 cli_cmd_flag_none,
2552 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002553 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002554 cli_cmd_flag_sensitive,
2555 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002556 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002557 cli_cmd_flag_none,
2558 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002559 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560 cli_cmd_flag_sensitive,
2561 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002562 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002563 cli_cmd_flag_none,
2564 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002565 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002566 cli_cmd_flag_sensitive,
2567 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002568#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002569 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002570 cli_cmd_flag_none,
2571 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2572#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002573 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002574 cli_cmd_flag_none,
2575 "<addr> = request RSN authentication with <addr> in IBSS" },
2576#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002577 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002578 cli_cmd_flag_none,
2579 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002580 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 cli_cmd_flag_none,
2582 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002583 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002584 cli_cmd_flag_none,
2585 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002586 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002587 cli_cmd_flag_none,
2588 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002589#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002590 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002591 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002592 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002593 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002594 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002595 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002596 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002597 cli_cmd_flag_none,
2598 "<addr> = roam to the specified BSS" },
2599#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002600 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2601 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002602 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002603 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002604 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002605 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2606 cli_cmd_flag_none,
2607 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2608 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002610 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2611 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002612 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002613 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2614 "[ht40] = add a new P2P group (local end as GO)" },
2615 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2616 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002617 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002618 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002619 cli_cmd_flag_none,
2620 "= get the passphrase for a group (GO only)" },
2621 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002622 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002623 "<addr> <TLVs> = schedule service discovery request" },
2624 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002625 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002626 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002627 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628 cli_cmd_flag_none,
2629 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002630 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002631 cli_cmd_flag_none,
2632 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002633 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002634 cli_cmd_flag_none,
2635 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002636 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002637 cli_cmd_flag_none,
2638 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002639 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002640 cli_cmd_flag_none,
2641 "<bonjour|upnp> <query|version> <response|service> = add a local "
2642 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002643 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002644 cli_cmd_flag_none,
2645 "<bonjour|upnp> <query|version> [|service] = remove a local "
2646 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002647 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648 cli_cmd_flag_none,
2649 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002650 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651 cli_cmd_flag_none,
2652 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002653 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002654 "[discovered] = list known (optionally, only fully discovered) P2P "
2655 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002656 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2657 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002658 "<address> = show information about known P2P peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002659 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002660 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002661 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002662 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002663 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002664 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002665 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2666 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002667 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002668 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2669 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002670 "[<duration> <interval>] [<duration> <interval>] = request GO "
2671 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002672 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2673 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002674 "[<period> <interval>] = set extended listen timing" },
2675#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002676#ifdef CONFIG_WIFI_DISPLAY
2677 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2678 cli_cmd_flag_none,
2679 "<subelem> [contents] = set Wi-Fi Display subelement" },
2680 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2681 cli_cmd_flag_none,
2682 "<subelem> = get Wi-Fi Display subelement" },
2683#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002684#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002685 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002686 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002687 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2688 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002689 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002690 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002691 cli_cmd_flag_none,
2692 "[auto] = perform Interworking network selection" },
2693 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002694 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002695 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002696 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2697 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002698 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002699 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2700 cli_cmd_flag_none,
2701 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2702 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2703 wpa_cli_complete_bss, cli_cmd_flag_none,
2704 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002705#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002706#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002707 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2708 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002709 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2710 },
2711 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002712 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002713 "<addr> <home realm> = get HS20 nai home realm list" },
2714#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002715 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2716 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002717 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002718 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002719 cli_cmd_flag_none,
2720 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002721 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722 cli_cmd_flag_none,
2723 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002724 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002725 cli_cmd_flag_none,
2726 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002727 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002728 cli_cmd_flag_none,
2729 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002730 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002731 cli_cmd_flag_none,
2732 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002733 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2734 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002735 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002736#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002737 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002738 "[params] = Set or unset (if none) autoscan parameters" },
2739#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002740 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2741 "<params..> = Sent unprocessed command" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002742#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002743 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002744 cli_cmd_flag_none,
2745 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002746#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002747 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748};
2749
2750
2751/*
2752 * Prints command usage, lines are padded with the specified string.
2753 */
2754static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2755{
2756 char c;
2757 size_t n;
2758
2759 printf("%s%s ", pad, cmd->cmd);
2760 for (n = 0; (c = cmd->usage[n]); n++) {
2761 printf("%c", c);
2762 if (c == '\n')
2763 printf("%s", pad);
2764 }
2765 printf("\n");
2766}
2767
2768
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002769static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002770{
2771 int n;
2772 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002773 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2774 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2775 print_cmd_help(&wpa_cli_commands[n], " ");
2776 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002777}
2778
2779
2780static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2781{
2782 const char *c, *delim;
2783 int n;
2784 size_t len;
2785
2786 delim = os_strchr(cmd, ' ');
2787 if (delim)
2788 len = delim - cmd;
2789 else
2790 len = os_strlen(cmd);
2791
2792 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2793 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2794 return (wpa_cli_commands[n].flags &
2795 cli_cmd_flag_sensitive);
2796 }
2797 return 0;
2798}
2799
2800
2801static char ** wpa_list_cmd_list(void)
2802{
2803 char **res;
2804 int i, count;
2805
2806 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002807 res = os_calloc(count, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002808 if (res == NULL)
2809 return NULL;
2810
2811 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2812 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2813 if (res[i] == NULL)
2814 break;
2815 }
2816
2817 return res;
2818}
2819
2820
2821static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2822 int pos)
2823{
2824 int i;
2825
2826 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2827 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002828 if (wpa_cli_commands[i].completion)
2829 return wpa_cli_commands[i].completion(str,
2830 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002831 edit_clear_line();
2832 printf("\r%s\n", wpa_cli_commands[i].usage);
2833 edit_redraw();
2834 break;
2835 }
2836 }
2837
2838 return NULL;
2839}
2840
2841
2842static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2843{
2844 char **res;
2845 const char *end;
2846 char *cmd;
2847
2848 end = os_strchr(str, ' ');
2849 if (end == NULL || str + pos < end)
2850 return wpa_list_cmd_list();
2851
2852 cmd = os_malloc(pos + 1);
2853 if (cmd == NULL)
2854 return NULL;
2855 os_memcpy(cmd, str, pos);
2856 cmd[end - str] = '\0';
2857 res = wpa_cli_cmd_completion(cmd, str, pos);
2858 os_free(cmd);
2859 return res;
2860}
2861
2862
2863static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2864{
2865 struct wpa_cli_cmd *cmd, *match = NULL;
2866 int count;
2867 int ret = 0;
2868
2869 count = 0;
2870 cmd = wpa_cli_commands;
2871 while (cmd->cmd) {
2872 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2873 {
2874 match = cmd;
2875 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2876 /* we have an exact match */
2877 count = 1;
2878 break;
2879 }
2880 count++;
2881 }
2882 cmd++;
2883 }
2884
2885 if (count > 1) {
2886 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2887 cmd = wpa_cli_commands;
2888 while (cmd->cmd) {
2889 if (os_strncasecmp(cmd->cmd, argv[0],
2890 os_strlen(argv[0])) == 0) {
2891 printf(" %s", cmd->cmd);
2892 }
2893 cmd++;
2894 }
2895 printf("\n");
2896 ret = 1;
2897 } else if (count == 0) {
2898 printf("Unknown command '%s'\n", argv[0]);
2899 ret = 1;
2900 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07002901#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
2902 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
2903 redirect_interface = os_strdup(argv[1]);
2904 ret = match->handler(ctrl, argc - 2, &argv[2]);
2905 }
2906 else
2907#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002908 ret = match->handler(ctrl, argc - 1, &argv[1]);
2909 }
2910
2911 return ret;
2912}
2913
2914
2915static int str_match(const char *a, const char *b)
2916{
2917 return os_strncmp(a, b, os_strlen(b)) == 0;
2918}
2919
2920
2921static int wpa_cli_exec(const char *program, const char *arg1,
2922 const char *arg2)
2923{
2924 char *cmd;
2925 size_t len;
2926 int res;
2927 int ret = 0;
2928
2929 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2930 cmd = os_malloc(len);
2931 if (cmd == NULL)
2932 return -1;
2933 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2934 if (res < 0 || (size_t) res >= len) {
2935 os_free(cmd);
2936 return -1;
2937 }
2938 cmd[len - 1] = '\0';
2939#ifndef _WIN32_WCE
2940 if (system(cmd) < 0)
2941 ret = -1;
2942#endif /* _WIN32_WCE */
2943 os_free(cmd);
2944
2945 return ret;
2946}
2947
2948
2949static void wpa_cli_action_process(const char *msg)
2950{
2951 const char *pos;
2952 char *copy = NULL, *id, *pos2;
2953
2954 pos = msg;
2955 if (*pos == '<') {
2956 /* skip priority */
2957 pos = os_strchr(pos, '>');
2958 if (pos)
2959 pos++;
2960 else
2961 pos = msg;
2962 }
2963
2964 if (str_match(pos, WPA_EVENT_CONNECTED)) {
2965 int new_id = -1;
2966 os_unsetenv("WPA_ID");
2967 os_unsetenv("WPA_ID_STR");
2968 os_unsetenv("WPA_CTRL_DIR");
2969
2970 pos = os_strstr(pos, "[id=");
2971 if (pos)
2972 copy = os_strdup(pos + 4);
2973
2974 if (copy) {
2975 pos2 = id = copy;
2976 while (*pos2 && *pos2 != ' ')
2977 pos2++;
2978 *pos2++ = '\0';
2979 new_id = atoi(id);
2980 os_setenv("WPA_ID", id, 1);
2981 while (*pos2 && *pos2 != '=')
2982 pos2++;
2983 if (*pos2 == '=')
2984 pos2++;
2985 id = pos2;
2986 while (*pos2 && *pos2 != ']')
2987 pos2++;
2988 *pos2 = '\0';
2989 os_setenv("WPA_ID_STR", id, 1);
2990 os_free(copy);
2991 }
2992
2993 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
2994
2995 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
2996 wpa_cli_connected = 1;
2997 wpa_cli_last_id = new_id;
2998 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
2999 }
3000 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3001 if (wpa_cli_connected) {
3002 wpa_cli_connected = 0;
3003 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3004 }
3005 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3006 wpa_cli_exec(action_file, ctrl_ifname, pos);
3007 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3008 wpa_cli_exec(action_file, ctrl_ifname, pos);
3009 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3010 wpa_cli_exec(action_file, ctrl_ifname, pos);
3011 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3012 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003013 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3014 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003015 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3016 wpa_cli_exec(action_file, ctrl_ifname, pos);
3017 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3018 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003019 } else if (str_match(pos, AP_STA_CONNECTED)) {
3020 wpa_cli_exec(action_file, ctrl_ifname, pos);
3021 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3022 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003023 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3024 printf("wpa_supplicant is terminating - stop monitoring\n");
3025 wpa_cli_quit = 1;
3026 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003027}
3028
3029
3030#ifndef CONFIG_ANSI_C_EXTRA
3031static void wpa_cli_action_cb(char *msg, size_t len)
3032{
3033 wpa_cli_action_process(msg);
3034}
3035#endif /* CONFIG_ANSI_C_EXTRA */
3036
3037
3038static void wpa_cli_reconnect(void)
3039{
3040 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003041 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3042 return;
3043
3044 if (interactive) {
3045 edit_clear_line();
3046 printf("\rConnection to wpa_supplicant re-established\n");
3047 edit_redraw();
3048 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003049}
3050
3051
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003052static void cli_event(const char *str)
3053{
3054 const char *start, *s;
3055
3056 start = os_strchr(str, '>');
3057 if (start == NULL)
3058 return;
3059
3060 start++;
3061
3062 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3063 s = os_strchr(start, ' ');
3064 if (s == NULL)
3065 return;
3066 s = os_strchr(s + 1, ' ');
3067 if (s == NULL)
3068 return;
3069 cli_txt_list_add(&bsses, s + 1);
3070 return;
3071 }
3072
3073 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3074 s = os_strchr(start, ' ');
3075 if (s == NULL)
3076 return;
3077 s = os_strchr(s + 1, ' ');
3078 if (s == NULL)
3079 return;
3080 cli_txt_list_del_addr(&bsses, s + 1);
3081 return;
3082 }
3083
3084#ifdef CONFIG_P2P
3085 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3086 s = os_strstr(start, " p2p_dev_addr=");
3087 if (s == NULL)
3088 return;
3089 cli_txt_list_add_addr(&p2p_peers, s + 14);
3090 return;
3091 }
3092
3093 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3094 s = os_strstr(start, " p2p_dev_addr=");
3095 if (s == NULL)
3096 return;
3097 cli_txt_list_del_addr(&p2p_peers, s + 14);
3098 return;
3099 }
3100
3101 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3102 s = os_strchr(start, ' ');
3103 if (s == NULL)
3104 return;
3105 cli_txt_list_add_word(&p2p_groups, s + 1);
3106 return;
3107 }
3108
3109 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3110 s = os_strchr(start, ' ');
3111 if (s == NULL)
3112 return;
3113 cli_txt_list_del_word(&p2p_groups, s + 1);
3114 return;
3115 }
3116#endif /* CONFIG_P2P */
3117}
3118
3119
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003120static int check_terminating(const char *msg)
3121{
3122 const char *pos = msg;
3123
3124 if (*pos == '<') {
3125 /* skip priority */
3126 pos = os_strchr(pos, '>');
3127 if (pos)
3128 pos++;
3129 else
3130 pos = msg;
3131 }
3132
3133 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3134 edit_clear_line();
3135 printf("\rConnection to wpa_supplicant lost - trying to "
3136 "reconnect\n");
3137 edit_redraw();
3138 wpa_cli_attached = 0;
3139 wpa_cli_close_connection();
3140 return 1;
3141 }
3142
3143 return 0;
3144}
3145
3146
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003147static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3148{
3149 if (ctrl_conn == NULL) {
3150 wpa_cli_reconnect();
3151 return;
3152 }
3153 while (wpa_ctrl_pending(ctrl) > 0) {
3154 char buf[256];
3155 size_t len = sizeof(buf) - 1;
3156 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3157 buf[len] = '\0';
3158 if (action_monitor)
3159 wpa_cli_action_process(buf);
3160 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003161 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003162 if (wpa_cli_show_event(buf)) {
3163 edit_clear_line();
3164 printf("\r%s\n", buf);
3165 edit_redraw();
3166 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003167
3168 if (interactive && check_terminating(buf) > 0)
3169 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003170 }
3171 } else {
3172 printf("Could not read pending message.\n");
3173 break;
3174 }
3175 }
3176
3177 if (wpa_ctrl_pending(ctrl) < 0) {
3178 printf("Connection to wpa_supplicant lost - trying to "
3179 "reconnect\n");
3180 wpa_cli_reconnect();
3181 }
3182}
3183
3184#define max_args 10
3185
3186static int tokenize_cmd(char *cmd, char *argv[])
3187{
3188 char *pos;
3189 int argc = 0;
3190
3191 pos = cmd;
3192 for (;;) {
3193 while (*pos == ' ')
3194 pos++;
3195 if (*pos == '\0')
3196 break;
3197 argv[argc] = pos;
3198 argc++;
3199 if (argc == max_args)
3200 break;
3201 if (*pos == '"') {
3202 char *pos2 = os_strrchr(pos, '"');
3203 if (pos2)
3204 pos = pos2 + 1;
3205 }
3206 while (*pos != '\0' && *pos != ' ')
3207 pos++;
3208 if (*pos == ' ')
3209 *pos++ = '\0';
3210 }
3211
3212 return argc;
3213}
3214
3215
3216static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3217{
3218 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3219 printf("Connection to wpa_supplicant lost - trying to "
3220 "reconnect\n");
3221 wpa_cli_close_connection();
3222 }
3223 if (!ctrl_conn)
3224 wpa_cli_reconnect();
3225 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3226}
3227
3228
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003229static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3230{
3231 wpa_cli_recv_pending(mon_conn, 0);
3232}
3233
3234
3235static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3236{
3237 char *argv[max_args];
3238 int argc;
3239 argc = tokenize_cmd(cmd, argv);
3240 if (argc)
3241 wpa_request(ctrl_conn, argc, argv);
3242}
3243
3244
3245static void wpa_cli_edit_eof_cb(void *ctx)
3246{
3247 eloop_terminate();
3248}
3249
3250
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003251static int warning_displayed = 0;
3252static char *hfile = NULL;
3253static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003254
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003255static void start_edit(void)
3256{
3257 char *home;
3258 char *ps = NULL;
3259
3260#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3261 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3262#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003263
3264 home = getenv("HOME");
3265 if (home) {
3266 const char *fname = ".wpa_cli_history";
3267 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3268 hfile = os_malloc(hfile_len);
3269 if (hfile)
3270 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3271 }
3272
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003273 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3274 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3275 eloop_terminate();
3276 return;
3277 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003278
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003279 edit_started = 1;
3280 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3281}
3282
3283
3284static void try_connection(void *eloop_ctx, void *timeout_ctx)
3285{
3286 if (ctrl_ifname == NULL)
3287 ctrl_ifname = wpa_cli_get_default_ifname();
3288
3289 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3290 if (!warning_displayed) {
3291 printf("Could not connect to wpa_supplicant: "
3292 "%s - re-trying\n", ctrl_ifname);
3293 warning_displayed = 1;
3294 }
3295 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3296 return;
3297 }
3298
3299 if (warning_displayed)
3300 printf("Connection established.\n");
3301
3302 start_edit();
3303}
3304
3305
3306static void wpa_cli_interactive(void)
3307{
3308 printf("\nInteractive mode\n\n");
3309
3310 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003311 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003312 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003313
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003314 cli_txt_list_flush(&p2p_peers);
3315 cli_txt_list_flush(&p2p_groups);
3316 cli_txt_list_flush(&bsses);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003317 if (edit_started)
3318 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003319 os_free(hfile);
3320 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3321 wpa_cli_close_connection();
3322}
3323
3324
3325static void wpa_cli_action(struct wpa_ctrl *ctrl)
3326{
3327#ifdef CONFIG_ANSI_C_EXTRA
3328 /* TODO: ANSI C version(?) */
3329 printf("Action processing not supported in ANSI C build.\n");
3330#else /* CONFIG_ANSI_C_EXTRA */
3331 fd_set rfds;
3332 int fd, res;
3333 struct timeval tv;
3334 char buf[256]; /* note: large enough to fit in unsolicited messages */
3335 size_t len;
3336
3337 fd = wpa_ctrl_get_fd(ctrl);
3338
3339 while (!wpa_cli_quit) {
3340 FD_ZERO(&rfds);
3341 FD_SET(fd, &rfds);
3342 tv.tv_sec = ping_interval;
3343 tv.tv_usec = 0;
3344 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3345 if (res < 0 && errno != EINTR) {
3346 perror("select");
3347 break;
3348 }
3349
3350 if (FD_ISSET(fd, &rfds))
3351 wpa_cli_recv_pending(ctrl, 1);
3352 else {
3353 /* verify that connection is still working */
3354 len = sizeof(buf) - 1;
3355 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3356 wpa_cli_action_cb) < 0 ||
3357 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3358 printf("wpa_supplicant did not reply to PING "
3359 "command - exiting\n");
3360 break;
3361 }
3362 }
3363 }
3364#endif /* CONFIG_ANSI_C_EXTRA */
3365}
3366
3367
3368static void wpa_cli_cleanup(void)
3369{
3370 wpa_cli_close_connection();
3371 if (pid_file)
3372 os_daemonize_terminate(pid_file);
3373
3374 os_program_deinit();
3375}
3376
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003377
3378static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003379{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003380 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003381}
3382
3383
3384static char * wpa_cli_get_default_ifname(void)
3385{
3386 char *ifname = NULL;
3387
3388#ifdef CONFIG_CTRL_IFACE_UNIX
3389 struct dirent *dent;
3390 DIR *dir = opendir(ctrl_iface_dir);
3391 if (!dir) {
3392#ifdef ANDROID
3393 char ifprop[PROPERTY_VALUE_MAX];
3394 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3395 ifname = os_strdup(ifprop);
3396 printf("Using interface '%s'\n", ifname);
3397 return ifname;
3398 }
3399#endif /* ANDROID */
3400 return NULL;
3401 }
3402 while ((dent = readdir(dir))) {
3403#ifdef _DIRENT_HAVE_D_TYPE
3404 /*
3405 * Skip the file if it is not a socket. Also accept
3406 * DT_UNKNOWN (0) in case the C library or underlying
3407 * file system does not support d_type.
3408 */
3409 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3410 continue;
3411#endif /* _DIRENT_HAVE_D_TYPE */
3412 if (os_strcmp(dent->d_name, ".") == 0 ||
3413 os_strcmp(dent->d_name, "..") == 0)
3414 continue;
3415 printf("Selected interface '%s'\n", dent->d_name);
3416 ifname = os_strdup(dent->d_name);
3417 break;
3418 }
3419 closedir(dir);
3420#endif /* CONFIG_CTRL_IFACE_UNIX */
3421
3422#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003423#ifdef ANDROID
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -07003424 char buf[4096], *pos;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003425#else
3426 char buf[2048], *pos;
3427#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003428 size_t len;
3429 struct wpa_ctrl *ctrl;
3430 int ret;
3431
3432 ctrl = wpa_ctrl_open(NULL);
3433 if (ctrl == NULL)
3434 return NULL;
3435
3436 len = sizeof(buf) - 1;
3437 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3438 if (ret >= 0) {
3439 buf[len] = '\0';
3440 pos = os_strchr(buf, '\n');
3441 if (pos)
3442 *pos = '\0';
3443 ifname = os_strdup(buf);
3444 }
3445 wpa_ctrl_close(ctrl);
3446#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3447
3448 return ifname;
3449}
3450
3451
3452int main(int argc, char *argv[])
3453{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003454 int c;
3455 int daemonize = 0;
3456 int ret = 0;
3457 const char *global = NULL;
3458
3459 if (os_program_init())
3460 return -1;
3461
3462 for (;;) {
3463 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3464 if (c < 0)
3465 break;
3466 switch (c) {
3467 case 'a':
3468 action_file = optarg;
3469 break;
3470 case 'B':
3471 daemonize = 1;
3472 break;
3473 case 'g':
3474 global = optarg;
3475 break;
3476 case 'G':
3477 ping_interval = atoi(optarg);
3478 break;
3479 case 'h':
3480 usage();
3481 return 0;
3482 case 'v':
3483 printf("%s\n", wpa_cli_version);
3484 return 0;
3485 case 'i':
3486 os_free(ctrl_ifname);
3487 ctrl_ifname = os_strdup(optarg);
3488 break;
3489 case 'p':
3490 ctrl_iface_dir = optarg;
3491 break;
3492 case 'P':
3493 pid_file = optarg;
3494 break;
3495 default:
3496 usage();
3497 return -1;
3498 }
3499 }
3500
3501 interactive = (argc == optind) && (action_file == NULL);
3502
3503 if (interactive)
3504 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3505
3506 if (eloop_init())
3507 return -1;
3508
3509 if (global) {
3510#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3511 ctrl_conn = wpa_ctrl_open(NULL);
3512#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3513 ctrl_conn = wpa_ctrl_open(global);
3514#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3515 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003516 fprintf(stderr, "Failed to connect to wpa_supplicant "
3517 "global interface: %s error: %s\n",
3518 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003519 return -1;
3520 }
3521 }
3522
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003523 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003524
3525 if (ctrl_ifname == NULL)
3526 ctrl_ifname = wpa_cli_get_default_ifname();
3527
3528 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003529 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003530 } else {
3531 if (!global &&
3532 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003533 fprintf(stderr, "Failed to connect to non-global "
3534 "ctrl_ifname: %s error: %s\n",
3535 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003536 return -1;
3537 }
3538
3539 if (action_file) {
3540 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3541 wpa_cli_attached = 1;
3542 } else {
3543 printf("Warning: Failed to attach to "
3544 "wpa_supplicant.\n");
3545 return -1;
3546 }
3547 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003548
3549 if (daemonize && os_daemonize(pid_file))
3550 return -1;
3551
3552 if (action_file)
3553 wpa_cli_action(ctrl_conn);
3554 else
3555 ret = wpa_request(ctrl_conn, argc - optind,
3556 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003557 }
3558
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003559 os_free(ctrl_ifname);
3560 eloop_destroy();
3561 wpa_cli_cleanup();
3562
3563 return ret;
3564}
3565
3566#else /* CONFIG_CTRL_IFACE */
3567int main(int argc, char *argv[])
3568{
3569 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3570 return -1;
3571}
3572#endif /* CONFIG_CTRL_IFACE */