blob: 2278138464ae8e05064353089cfdb423cdab4b48 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
Dmitry Shmidt04949592012-07-19 12:16:46 -07003 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#ifdef CONFIG_CTRL_IFACE
12
13#ifdef CONFIG_CTRL_IFACE_UNIX
14#include <dirent.h>
15#endif /* CONFIG_CTRL_IFACE_UNIX */
16
17#include "common/wpa_ctrl.h"
18#include "utils/common.h"
19#include "utils/eloop.h"
20#include "utils/edit.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "utils/list.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "common/version.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070023#include "common/ieee802_11_defs.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070024#ifdef ANDROID
25#include <cutils/properties.h>
26#endif /* ANDROID */
27
28
29static const char *wpa_cli_version =
30"wpa_cli v" VERSION_STR "\n"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080031"Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032
33
34static const char *wpa_cli_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080035"This software may be distributed under the terms of the BSD license.\n"
36"See README for more details.\n";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037
38static const char *wpa_cli_full_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080039"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040"\n"
41"Redistribution and use in source and binary forms, with or without\n"
42"modification, are permitted provided that the following conditions are\n"
43"met:\n"
44"\n"
45"1. Redistributions of source code must retain the above copyright\n"
46" notice, this list of conditions and the following disclaimer.\n"
47"\n"
48"2. Redistributions in binary form must reproduce the above copyright\n"
49" notice, this list of conditions and the following disclaimer in the\n"
50" documentation and/or other materials provided with the distribution.\n"
51"\n"
52"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53" names of its contributors may be used to endorse or promote products\n"
54" derived from this software without specific prior written permission.\n"
55"\n"
56"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67"\n";
68
69static struct wpa_ctrl *ctrl_conn;
70static struct wpa_ctrl *mon_conn;
71static int wpa_cli_quit = 0;
72static int wpa_cli_attached = 0;
73static int wpa_cli_connected = 0;
74static int wpa_cli_last_id = 0;
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
82static int ping_interval = 5;
83static int interactive = 0;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -070084#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
85static char* redirect_interface = NULL;
86#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070087
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080088struct cli_txt_entry {
89 struct dl_list list;
90 char *txt;
91};
92
93static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
94static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
95static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
96
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070097
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070098static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070099static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700100static void wpa_cli_close_connection(void);
101static char * wpa_cli_get_default_ifname(void);
102static char ** wpa_list_cmd_list(void);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700103
104
105static void usage(void)
106{
107 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
108 "[-a<action file>] \\\n"
109 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
110 "[command..]\n"
111 " -h = help (show this usage text)\n"
112 " -v = shown version information\n"
113 " -a = run in daemon mode executing the action file based on "
114 "events from\n"
115 " wpa_supplicant\n"
116 " -B = run a daemon in the background\n"
117 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
118 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700119 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700120}
121
122
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800123static void cli_txt_list_free(struct cli_txt_entry *e)
124{
125 dl_list_del(&e->list);
126 os_free(e->txt);
127 os_free(e);
128}
129
130
131static void cli_txt_list_flush(struct dl_list *list)
132{
133 struct cli_txt_entry *e;
134 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
135 cli_txt_list_free(e);
136}
137
138
139static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
140 const char *txt)
141{
142 struct cli_txt_entry *e;
143 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
144 if (os_strcmp(e->txt, txt) == 0)
145 return e;
146 }
147 return NULL;
148}
149
150
151static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
152{
153 struct cli_txt_entry *e;
154 e = cli_txt_list_get(txt_list, txt);
155 if (e)
156 cli_txt_list_free(e);
157}
158
159
160static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
161{
162 u8 addr[ETH_ALEN];
163 char buf[18];
164 if (hwaddr_aton(txt, addr) < 0)
165 return;
166 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
167 cli_txt_list_del(txt_list, buf);
168}
169
170
171#ifdef CONFIG_P2P
172static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
173{
174 const char *end;
175 char *buf;
176 end = os_strchr(txt, ' ');
177 if (end == NULL)
178 end = txt + os_strlen(txt);
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{
Dmitry Shmidt3a787e62013-01-17 10:32:35 -08001462 if (argc > 0)
1463 return wpa_cli_cmd(ctrl, "SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001464 return wpa_ctrl_command(ctrl, "SCAN");
1465}
1466
1467
1468static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1469 char *argv[])
1470{
1471 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1472}
1473
1474
1475static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1476{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001477 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001478}
1479
1480
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001481static char ** wpa_cli_complete_bss(const char *str, int pos)
1482{
1483 int arg = get_cmd_arg_num(str, pos);
1484 char **res = NULL;
1485
1486 switch (arg) {
1487 case 1:
1488 res = cli_txt_list_array(&bsses);
1489 break;
1490 }
1491
1492 return res;
1493}
1494
1495
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001496static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1497 char *argv[])
1498{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001499 if (argc < 1 || argc > 2) {
1500 printf("Invalid GET_CAPABILITY command: need either one or "
1501 "two arguments\n");
1502 return -1;
1503 }
1504
1505 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1506 printf("Invalid GET_CAPABILITY command: second argument, "
1507 "if any, must be 'strict'\n");
1508 return -1;
1509 }
1510
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001511 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001512}
1513
1514
1515static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1516{
1517 printf("Available interfaces:\n");
1518 return wpa_ctrl_command(ctrl, "INTERFACES");
1519}
1520
1521
1522static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1523{
1524 if (argc < 1) {
1525 wpa_cli_list_interfaces(ctrl);
1526 return 0;
1527 }
1528
1529 wpa_cli_close_connection();
1530 os_free(ctrl_ifname);
1531 ctrl_ifname = os_strdup(argv[0]);
1532
1533 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1534 printf("Connected to interface '%s.\n", ctrl_ifname);
1535 } else {
1536 printf("Could not connect to interface '%s' - re-trying\n",
1537 ctrl_ifname);
1538 }
1539 return 0;
1540}
1541
1542
1543static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1544 char *argv[])
1545{
1546 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1547}
1548
1549
1550static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1551 char *argv[])
1552{
1553 return wpa_ctrl_command(ctrl, "TERMINATE");
1554}
1555
1556
1557static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1558 char *argv[])
1559{
1560 char cmd[256];
1561 int res;
1562
1563 if (argc < 1) {
1564 printf("Invalid INTERFACE_ADD command: needs at least one "
1565 "argument (interface name)\n"
1566 "All arguments: ifname confname driver ctrl_interface "
1567 "driver_param bridge_name\n");
1568 return -1;
1569 }
1570
1571 /*
1572 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1573 * <driver_param>TAB<bridge_name>
1574 */
1575 res = os_snprintf(cmd, sizeof(cmd),
1576 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1577 argv[0],
1578 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1579 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1580 argc > 5 ? argv[5] : "");
1581 if (res < 0 || (size_t) res >= sizeof(cmd))
1582 return -1;
1583 cmd[sizeof(cmd) - 1] = '\0';
1584 return wpa_ctrl_command(ctrl, cmd);
1585}
1586
1587
1588static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1589 char *argv[])
1590{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001591 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001592}
1593
1594
1595static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1596 char *argv[])
1597{
1598 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1599}
1600
1601
1602#ifdef CONFIG_AP
1603static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1604{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001605 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001606}
1607
1608
1609static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1610 char *addr, size_t addr_len)
1611{
1612 char buf[4096], *pos;
1613 size_t len;
1614 int ret;
1615
1616 if (ctrl_conn == NULL) {
1617 printf("Not connected to hostapd - command dropped.\n");
1618 return -1;
1619 }
1620 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001621 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001622 wpa_cli_msg_cb);
1623 if (ret == -2) {
1624 printf("'%s' command timed out.\n", cmd);
1625 return -2;
1626 } else if (ret < 0) {
1627 printf("'%s' command failed.\n", cmd);
1628 return -1;
1629 }
1630
1631 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001632 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001633 return -1;
1634 printf("%s", buf);
1635
1636 pos = buf;
1637 while (*pos != '\0' && *pos != '\n')
1638 pos++;
1639 *pos = '\0';
1640 os_strlcpy(addr, buf, addr_len);
1641 return 0;
1642}
1643
1644
1645static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1646{
1647 char addr[32], cmd[64];
1648
1649 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1650 return 0;
1651 do {
1652 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1653 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1654
1655 return -1;
1656}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001657
1658
1659static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1660 char *argv[])
1661{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001662 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001663}
1664
1665
1666static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1667 char *argv[])
1668{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001669 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001670}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001671#endif /* CONFIG_AP */
1672
1673
1674static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1675{
1676 return wpa_ctrl_command(ctrl, "SUSPEND");
1677}
1678
1679
1680static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1681{
1682 return wpa_ctrl_command(ctrl, "RESUME");
1683}
1684
1685
1686static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1687{
1688 return wpa_ctrl_command(ctrl, "DROP_SA");
1689}
1690
1691
1692static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1693{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001694 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001695}
1696
1697
1698#ifdef CONFIG_P2P
1699
1700static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1701{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001702 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1703}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001704
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001705
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001706static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1707{
1708 char **res = NULL;
1709 int arg = get_cmd_arg_num(str, pos);
1710
1711 res = os_calloc(6, sizeof(char *));
1712 if (res == NULL)
1713 return NULL;
1714 res[0] = os_strdup("type=social");
1715 if (res[0] == NULL) {
1716 os_free(res);
1717 return NULL;
1718 }
1719 res[1] = os_strdup("type=progressive");
1720 if (res[1] == NULL)
1721 return res;
1722 res[2] = os_strdup("delay=");
1723 if (res[2] == NULL)
1724 return res;
1725 res[3] = os_strdup("dev_id=");
1726 if (res[3] == NULL)
1727 return res;
1728 if (arg == 1)
1729 res[4] = os_strdup("[timeout]");
1730
1731 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001732}
1733
1734
1735static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1736 char *argv[])
1737{
1738 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1739}
1740
1741
1742static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1743 char *argv[])
1744{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001745 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746}
1747
1748
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001749static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1750{
1751 int arg = get_cmd_arg_num(str, pos);
1752 char **res = NULL;
1753
1754 switch (arg) {
1755 case 1:
1756 res = cli_txt_list_array(&p2p_peers);
1757 break;
1758 }
1759
1760 return res;
1761}
1762
1763
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001764static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1765 char *argv[])
1766{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001767 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001768}
1769
1770
1771static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1772 char *argv[])
1773{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001774 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001775}
1776
1777
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001778static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1779{
1780 int arg = get_cmd_arg_num(str, pos);
1781 char **res = NULL;
1782
1783 switch (arg) {
1784 case 1:
1785 res = cli_txt_list_array(&p2p_groups);
1786 break;
1787 }
1788
1789 return res;
1790}
1791
1792
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001793static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1794 char *argv[])
1795{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001796 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797}
1798
1799
1800static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1801 char *argv[])
1802{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001803 if (argc != 2 && argc != 3) {
1804 printf("Invalid P2P_PROV_DISC command: needs at least "
1805 "two arguments, address and config method\n"
1806 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001807 return -1;
1808 }
1809
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001810 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001811}
1812
1813
1814static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1815 char *argv[])
1816{
1817 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1818}
1819
1820
1821static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1822 char *argv[])
1823{
1824 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001825
1826 if (argc != 2 && argc != 4) {
1827 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1828 "arguments (address and TLVs) or four arguments "
1829 "(address, \"upnp\", version, search target "
1830 "(SSDP ST:)\n");
1831 return -1;
1832 }
1833
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001834 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001835 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001836 return wpa_ctrl_command(ctrl, cmd);
1837}
1838
1839
1840static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1841 int argc, char *argv[])
1842{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001843 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001844}
1845
1846
1847static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1848 char *argv[])
1849{
1850 char cmd[4096];
1851 int res;
1852
1853 if (argc != 4) {
1854 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1855 "arguments (freq, address, dialog token, and TLVs)\n");
1856 return -1;
1857 }
1858
1859 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1860 argv[0], argv[1], argv[2], argv[3]);
1861 if (res < 0 || (size_t) res >= sizeof(cmd))
1862 return -1;
1863 cmd[sizeof(cmd) - 1] = '\0';
1864 return wpa_ctrl_command(ctrl, cmd);
1865}
1866
1867
1868static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1869 char *argv[])
1870{
1871 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1872}
1873
1874
1875static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1876 int argc, char *argv[])
1877{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001878 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001879}
1880
1881
1882static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1883 char *argv[])
1884{
1885 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1886}
1887
1888
1889static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1890 char *argv[])
1891{
1892 char cmd[4096];
1893 int res;
1894
1895 if (argc != 3 && argc != 4) {
1896 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1897 "arguments\n");
1898 return -1;
1899 }
1900
1901 if (argc == 4)
1902 res = os_snprintf(cmd, sizeof(cmd),
1903 "P2P_SERVICE_ADD %s %s %s %s",
1904 argv[0], argv[1], argv[2], argv[3]);
1905 else
1906 res = os_snprintf(cmd, sizeof(cmd),
1907 "P2P_SERVICE_ADD %s %s %s",
1908 argv[0], argv[1], argv[2]);
1909 if (res < 0 || (size_t) res >= sizeof(cmd))
1910 return -1;
1911 cmd[sizeof(cmd) - 1] = '\0';
1912 return wpa_ctrl_command(ctrl, cmd);
1913}
1914
1915
1916static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1917 char *argv[])
1918{
1919 char cmd[4096];
1920 int res;
1921
1922 if (argc != 2 && argc != 3) {
1923 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1924 "arguments\n");
1925 return -1;
1926 }
1927
1928 if (argc == 3)
1929 res = os_snprintf(cmd, sizeof(cmd),
1930 "P2P_SERVICE_DEL %s %s %s",
1931 argv[0], argv[1], argv[2]);
1932 else
1933 res = os_snprintf(cmd, sizeof(cmd),
1934 "P2P_SERVICE_DEL %s %s",
1935 argv[0], argv[1]);
1936 if (res < 0 || (size_t) res >= sizeof(cmd))
1937 return -1;
1938 cmd[sizeof(cmd) - 1] = '\0';
1939 return wpa_ctrl_command(ctrl, cmd);
1940}
1941
1942
1943static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1944 int argc, char *argv[])
1945{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001946 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001947}
1948
1949
1950static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1951 int argc, char *argv[])
1952{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001953 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001954}
1955
1956
1957static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1958{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001959 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001960}
1961
1962
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001963static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1964{
1965 int arg = get_cmd_arg_num(str, pos);
1966 char **res = NULL;
1967
1968 switch (arg) {
1969 case 1:
1970 res = cli_txt_list_array(&p2p_peers);
1971 break;
1972 }
1973
1974 return res;
1975}
1976
1977
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001978static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1979 char *addr, size_t addr_len,
1980 int discovered)
1981{
1982 char buf[4096], *pos;
1983 size_t len;
1984 int ret;
1985
1986 if (ctrl_conn == NULL)
1987 return -1;
1988 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001989 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001990 wpa_cli_msg_cb);
1991 if (ret == -2) {
1992 printf("'%s' command timed out.\n", cmd);
1993 return -2;
1994 } else if (ret < 0) {
1995 printf("'%s' command failed.\n", cmd);
1996 return -1;
1997 }
1998
1999 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002000 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002001 return -1;
2002
2003 pos = buf;
2004 while (*pos != '\0' && *pos != '\n')
2005 pos++;
2006 *pos++ = '\0';
2007 os_strlcpy(addr, buf, addr_len);
2008 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2009 printf("%s\n", addr);
2010 return 0;
2011}
2012
2013
2014static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2015{
2016 char addr[32], cmd[64];
2017 int discovered;
2018
2019 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2020
2021 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2022 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002023 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002024 do {
2025 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2026 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2027 discovered) == 0);
2028
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002029 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002030}
2031
2032
2033static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2034{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002035 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002036}
2037
2038
2039static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2040{
2041 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2042}
2043
2044
2045static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2046 char *argv[])
2047{
2048 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2049}
2050
2051
2052static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2053 char *argv[])
2054{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002055 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002056}
2057
2058
2059static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2060 char *argv[])
2061{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002062 if (argc != 0 && argc != 2 && argc != 4) {
2063 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2064 "(preferred duration, interval; in microsecods).\n"
2065 "Optional second pair can be used to provide "
2066 "acceptable values.\n");
2067 return -1;
2068 }
2069
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002070 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002071}
2072
2073
2074static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2075 char *argv[])
2076{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002077 if (argc != 0 && argc != 2) {
2078 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2079 "(availability period, availability interval; in "
2080 "millisecods).\n"
2081 "Extended Listen Timing can be cancelled with this "
2082 "command when used without parameters.\n");
2083 return -1;
2084 }
2085
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002086 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2087}
2088
2089#endif /* CONFIG_P2P */
2090
2091#ifdef CONFIG_WIFI_DISPLAY
2092
2093static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2094 char *argv[])
2095{
2096 char cmd[100];
2097 int res;
2098
2099 if (argc != 1 && argc != 2) {
2100 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2101 "arguments (subelem, hexdump)\n");
2102 return -1;
2103 }
2104
2105 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2106 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002107 if (res < 0 || (size_t) res >= sizeof(cmd))
2108 return -1;
2109 cmd[sizeof(cmd) - 1] = '\0';
2110 return wpa_ctrl_command(ctrl, cmd);
2111}
2112
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002113
2114static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2115 char *argv[])
2116{
2117 char cmd[100];
2118 int res;
2119
2120 if (argc != 1) {
2121 printf("Invalid WFD_SUBELEM_GET command: needs one "
2122 "argument (subelem)\n");
2123 return -1;
2124 }
2125
2126 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2127 argv[0]);
2128 if (res < 0 || (size_t) res >= sizeof(cmd))
2129 return -1;
2130 cmd[sizeof(cmd) - 1] = '\0';
2131 return wpa_ctrl_command(ctrl, cmd);
2132}
2133#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002134
2135
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002136#ifdef CONFIG_INTERWORKING
2137static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2138 char *argv[])
2139{
2140 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2141}
2142
2143
2144static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2145 char *argv[])
2146{
2147 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2148}
2149
2150
2151static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2152 char *argv[])
2153{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002154 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002155}
2156
2157
2158static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2159 char *argv[])
2160{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002161 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002162}
2163
2164
2165static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2166{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002167 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2168}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002169
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002170
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002171static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2172 char *argv[])
2173{
2174 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2175}
2176
2177
2178static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2179 char *argv[])
2180{
2181 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002182}
2183#endif /* CONFIG_INTERWORKING */
2184
2185
Dmitry Shmidt04949592012-07-19 12:16:46 -07002186#ifdef CONFIG_HS20
2187
2188static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2189 char *argv[])
2190{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002191 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002192}
2193
2194
2195static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2196 char *argv[])
2197{
2198 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002199
2200 if (argc == 0) {
2201 printf("Command needs one or two arguments (dst mac addr and "
2202 "optional home realm)\n");
2203 return -1;
2204 }
2205
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002206 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2207 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002208 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002209
2210 return wpa_ctrl_command(ctrl, cmd);
2211}
2212
2213#endif /* CONFIG_HS20 */
2214
2215
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002216static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2217 char *argv[])
2218{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002219 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002220}
2221
2222
2223static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2224 char *argv[])
2225{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002226 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002227}
2228
2229
2230static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2231 char *argv[])
2232{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002233 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002234}
2235
2236
2237static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2238 char *argv[])
2239{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002240 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241}
2242
2243
2244static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2245 char *argv[])
2246{
2247 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2248}
2249
2250
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002251static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2252 char *argv[])
2253{
2254 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2255}
2256
2257
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002258static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2259 char *argv[])
2260{
2261 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2262}
2263
Dmitry Shmidt04949592012-07-19 12:16:46 -07002264
2265#ifdef CONFIG_AUTOSCAN
2266
2267static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2268{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002269 if (argc == 0)
2270 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2271
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002272 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002273}
2274
2275#endif /* CONFIG_AUTOSCAN */
2276
2277
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002278#ifdef CONFIG_WNM
2279
2280static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2281{
2282 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2283}
2284
2285#endif /* CONFIG_WNM */
2286
2287
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002288static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2289{
2290 if (argc == 0)
2291 return -1;
2292 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2293}
2294
2295
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002296#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002297static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2298{
2299 char cmd[256];
2300 int i;
2301 int len;
2302
2303 if (argc < 1) {
2304 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2305 return -1;
2306 }
2307
2308 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2309 for (i=1; i < argc; i++)
2310 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2311 cmd[sizeof(cmd) - 1] = '\0';
2312 printf("%s: %s\n", __func__, cmd);
2313 return wpa_ctrl_command(ctrl, cmd);
2314}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002315#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002316
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002317
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002318enum wpa_cli_cmd_flags {
2319 cli_cmd_flag_none = 0x00,
2320 cli_cmd_flag_sensitive = 0x01
2321};
2322
2323struct wpa_cli_cmd {
2324 const char *cmd;
2325 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002326 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002327 enum wpa_cli_cmd_flags flags;
2328 const char *usage;
2329};
2330
2331static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002332 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002333 cli_cmd_flag_none,
2334 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002335 { "ifname", wpa_cli_cmd_ifname, NULL,
2336 cli_cmd_flag_none,
2337 "= get current interface name" },
2338 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002339 cli_cmd_flag_none,
2340 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002341 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002342 cli_cmd_flag_none,
2343 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002344 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002345 cli_cmd_flag_none,
2346 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002347 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002348 cli_cmd_flag_none,
2349 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002350 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002351 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002352 "[command] = show usage help" },
2353 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002354 cli_cmd_flag_none,
2355 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002356 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002357 cli_cmd_flag_none,
2358 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002359 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002360 cli_cmd_flag_none,
2361 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002362 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002363 cli_cmd_flag_none,
2364 "= exit wpa_cli" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002365 { "set", wpa_cli_cmd_set, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002366 cli_cmd_flag_none,
2367 "= set variables (shows list of variables when run without "
2368 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002369 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002370 cli_cmd_flag_none,
2371 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002372 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002373 cli_cmd_flag_none,
2374 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002375 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002376 cli_cmd_flag_none,
2377 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002378 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002379 cli_cmd_flag_none,
2380 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002381 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002382 cli_cmd_flag_none,
2383 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002384 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002385 cli_cmd_flag_none,
2386 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002387 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002388 cli_cmd_flag_none,
2389 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002390 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002391 cli_cmd_flag_sensitive,
2392 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002393 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002394 cli_cmd_flag_sensitive,
2395 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002396 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002397 cli_cmd_flag_sensitive,
2398 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002399 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002400 cli_cmd_flag_sensitive,
2401 "<network id> <password> = configure one-time-password for an SSID"
2402 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002403 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002404 cli_cmd_flag_sensitive,
2405 "<network id> <passphrase> = configure private key passphrase\n"
2406 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002407 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002408 cli_cmd_flag_none,
2409 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002410 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002411 cli_cmd_flag_none,
2412 "<BSSID> = add a BSSID to the blacklist\n"
2413 "blacklist clear = clear the blacklist\n"
2414 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002415 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002416 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002417 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002418 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002419 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002420 cli_cmd_flag_none,
2421 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002422 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002423 cli_cmd_flag_none,
2424 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002425 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002426 cli_cmd_flag_none,
2427 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002428 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002429 cli_cmd_flag_none,
2430 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002431 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002432 cli_cmd_flag_none,
2433 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002434 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002435 cli_cmd_flag_none,
2436 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002437 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002438 cli_cmd_flag_sensitive,
2439 "<network id> <variable> <value> = set network variables (shows\n"
2440 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002441 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002442 cli_cmd_flag_none,
2443 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002444 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002445 cli_cmd_flag_none,
2446 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002447 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002448 cli_cmd_flag_none,
2449 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002450 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002451 cli_cmd_flag_none,
2452 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002453 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002454 cli_cmd_flag_sensitive,
2455 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002456 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002457 cli_cmd_flag_none,
2458 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002459 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002460 cli_cmd_flag_none,
2461 "= disconnect and wait for reassociate/reconnect command before\n"
2462 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002463 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002464 cli_cmd_flag_none,
2465 "= like reassociate, but only takes effect if already disconnected"
2466 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002467 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 cli_cmd_flag_none,
2469 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002470 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002471 cli_cmd_flag_none,
2472 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002473 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002474 cli_cmd_flag_none,
2475 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002476 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002477 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002478 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels> "
2479 "= get capabilies" },
2480 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002481 cli_cmd_flag_none,
2482 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002483 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002484 cli_cmd_flag_none,
2485 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002486 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002487 cli_cmd_flag_none,
2488 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2489 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2490 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002491 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 cli_cmd_flag_none,
2493 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002494 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002495 cli_cmd_flag_none,
2496 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002497 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002498 cli_cmd_flag_none,
2499 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002500 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002501 cli_cmd_flag_none,
2502 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002503 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002504 cli_cmd_flag_none,
2505 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002506 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507 cli_cmd_flag_none,
2508 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002509 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002510 cli_cmd_flag_none,
2511 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002512 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 cli_cmd_flag_none,
2514 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002515 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002516 cli_cmd_flag_none,
2517 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002518 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002519 cli_cmd_flag_none,
2520 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002521 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002522 cli_cmd_flag_sensitive,
2523 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2524 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002525 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 cli_cmd_flag_sensitive,
2527 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002528 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002529 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002530#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002531 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002532 cli_cmd_flag_none,
2533 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002534 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002535 cli_cmd_flag_none,
2536 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002537 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002538 cli_cmd_flag_sensitive,
2539 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002540 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2541 cli_cmd_flag_none,
2542 "<NDEF> <WPS> = create NFC handover request" },
2543 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2544 cli_cmd_flag_none,
2545 "<NDEF> <WPS> = create NFC handover select" },
2546 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2547 cli_cmd_flag_none,
2548 "<hexdump of payload> = report received NFC handover request" },
2549 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2550 cli_cmd_flag_none,
2551 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002552#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002553 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002554 cli_cmd_flag_sensitive,
2555 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002556 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002557 cli_cmd_flag_sensitive,
2558 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002559 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560 cli_cmd_flag_none,
2561 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002562 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002563 cli_cmd_flag_none,
2564 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002565 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002566 cli_cmd_flag_sensitive,
2567 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002568 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002569 cli_cmd_flag_none,
2570 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002571 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002572 cli_cmd_flag_sensitive,
2573 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002574 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002575 cli_cmd_flag_none,
2576 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002577 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002578 cli_cmd_flag_sensitive,
2579 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002580#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002581 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002582 cli_cmd_flag_none,
2583 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2584#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002585 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002586 cli_cmd_flag_none,
2587 "<addr> = request RSN authentication with <addr> in IBSS" },
2588#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002589 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002590 cli_cmd_flag_none,
2591 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002592 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002593 cli_cmd_flag_none,
2594 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002595 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002596 cli_cmd_flag_none,
2597 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002598 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002599 cli_cmd_flag_none,
2600 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002601#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002602 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002604 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002605 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002606 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002607 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002608 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 cli_cmd_flag_none,
2610 "<addr> = roam to the specified BSS" },
2611#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002612 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2613 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002614 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002615 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002616 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002617 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2618 cli_cmd_flag_none,
2619 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2620 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002621 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002622 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2623 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002625 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2626 "[ht40] = add a new P2P group (local end as GO)" },
2627 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2628 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002629 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002630 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002631 cli_cmd_flag_none,
2632 "= get the passphrase for a group (GO only)" },
2633 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002634 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002635 "<addr> <TLVs> = schedule service discovery request" },
2636 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002637 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002639 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002640 cli_cmd_flag_none,
2641 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002642 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643 cli_cmd_flag_none,
2644 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002645 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646 cli_cmd_flag_none,
2647 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002648 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002649 cli_cmd_flag_none,
2650 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002651 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652 cli_cmd_flag_none,
2653 "<bonjour|upnp> <query|version> <response|service> = add a local "
2654 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002655 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002656 cli_cmd_flag_none,
2657 "<bonjour|upnp> <query|version> [|service] = remove a local "
2658 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002659 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002660 cli_cmd_flag_none,
2661 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002662 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002663 cli_cmd_flag_none,
2664 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002665 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002666 "[discovered] = list known (optionally, only fully discovered) P2P "
2667 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002668 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2669 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002670 "<address> = show information about known P2P peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002671 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002672 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002673 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002674 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002675 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002676 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002677 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2678 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002679 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002680 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2681 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002682 "[<duration> <interval>] [<duration> <interval>] = request GO "
2683 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002684 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2685 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002686 "[<period> <interval>] = set extended listen timing" },
2687#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002688#ifdef CONFIG_WIFI_DISPLAY
2689 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2690 cli_cmd_flag_none,
2691 "<subelem> [contents] = set Wi-Fi Display subelement" },
2692 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2693 cli_cmd_flag_none,
2694 "<subelem> = get Wi-Fi Display subelement" },
2695#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002696#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002697 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002698 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002699 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2700 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002701 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002702 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002703 cli_cmd_flag_none,
2704 "[auto] = perform Interworking network selection" },
2705 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002706 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002707 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002708 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2709 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002710 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002711 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2712 cli_cmd_flag_none,
2713 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2714 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2715 wpa_cli_complete_bss, cli_cmd_flag_none,
2716 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002717#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002718#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002719 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2720 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002721 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2722 },
2723 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002724 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002725 "<addr> <home realm> = get HS20 nai home realm list" },
2726#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002727 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2728 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002729 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002730 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002731 cli_cmd_flag_none,
2732 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002733 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002734 cli_cmd_flag_none,
2735 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002736 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002737 cli_cmd_flag_none,
2738 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002739 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002740 cli_cmd_flag_none,
2741 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002742 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002743 cli_cmd_flag_none,
2744 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002745 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2746 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002747 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002748#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002749 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002750 "[params] = Set or unset (if none) autoscan parameters" },
2751#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002752#ifdef CONFIG_WNM
2753 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2754 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
2755#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002756 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2757 "<params..> = Sent unprocessed command" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002758#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002759 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002760 cli_cmd_flag_none,
2761 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002762#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002763 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002764};
2765
2766
2767/*
2768 * Prints command usage, lines are padded with the specified string.
2769 */
2770static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2771{
2772 char c;
2773 size_t n;
2774
2775 printf("%s%s ", pad, cmd->cmd);
2776 for (n = 0; (c = cmd->usage[n]); n++) {
2777 printf("%c", c);
2778 if (c == '\n')
2779 printf("%s", pad);
2780 }
2781 printf("\n");
2782}
2783
2784
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002785static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002786{
2787 int n;
2788 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002789 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2790 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2791 print_cmd_help(&wpa_cli_commands[n], " ");
2792 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002793}
2794
2795
2796static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2797{
2798 const char *c, *delim;
2799 int n;
2800 size_t len;
2801
2802 delim = os_strchr(cmd, ' ');
2803 if (delim)
2804 len = delim - cmd;
2805 else
2806 len = os_strlen(cmd);
2807
2808 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2809 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2810 return (wpa_cli_commands[n].flags &
2811 cli_cmd_flag_sensitive);
2812 }
2813 return 0;
2814}
2815
2816
2817static char ** wpa_list_cmd_list(void)
2818{
2819 char **res;
2820 int i, count;
2821
2822 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002823 res = os_calloc(count, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002824 if (res == NULL)
2825 return NULL;
2826
2827 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2828 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2829 if (res[i] == NULL)
2830 break;
2831 }
2832
2833 return res;
2834}
2835
2836
2837static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2838 int pos)
2839{
2840 int i;
2841
2842 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2843 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002844 if (wpa_cli_commands[i].completion)
2845 return wpa_cli_commands[i].completion(str,
2846 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002847 edit_clear_line();
2848 printf("\r%s\n", wpa_cli_commands[i].usage);
2849 edit_redraw();
2850 break;
2851 }
2852 }
2853
2854 return NULL;
2855}
2856
2857
2858static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2859{
2860 char **res;
2861 const char *end;
2862 char *cmd;
2863
2864 end = os_strchr(str, ' ');
2865 if (end == NULL || str + pos < end)
2866 return wpa_list_cmd_list();
2867
2868 cmd = os_malloc(pos + 1);
2869 if (cmd == NULL)
2870 return NULL;
2871 os_memcpy(cmd, str, pos);
2872 cmd[end - str] = '\0';
2873 res = wpa_cli_cmd_completion(cmd, str, pos);
2874 os_free(cmd);
2875 return res;
2876}
2877
2878
2879static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2880{
2881 struct wpa_cli_cmd *cmd, *match = NULL;
2882 int count;
2883 int ret = 0;
2884
2885 count = 0;
2886 cmd = wpa_cli_commands;
2887 while (cmd->cmd) {
2888 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2889 {
2890 match = cmd;
2891 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2892 /* we have an exact match */
2893 count = 1;
2894 break;
2895 }
2896 count++;
2897 }
2898 cmd++;
2899 }
2900
2901 if (count > 1) {
2902 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2903 cmd = wpa_cli_commands;
2904 while (cmd->cmd) {
2905 if (os_strncasecmp(cmd->cmd, argv[0],
2906 os_strlen(argv[0])) == 0) {
2907 printf(" %s", cmd->cmd);
2908 }
2909 cmd++;
2910 }
2911 printf("\n");
2912 ret = 1;
2913 } else if (count == 0) {
2914 printf("Unknown command '%s'\n", argv[0]);
2915 ret = 1;
2916 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07002917#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
2918 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
2919 redirect_interface = os_strdup(argv[1]);
2920 ret = match->handler(ctrl, argc - 2, &argv[2]);
2921 }
2922 else
2923#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002924 ret = match->handler(ctrl, argc - 1, &argv[1]);
2925 }
2926
2927 return ret;
2928}
2929
2930
2931static int str_match(const char *a, const char *b)
2932{
2933 return os_strncmp(a, b, os_strlen(b)) == 0;
2934}
2935
2936
2937static int wpa_cli_exec(const char *program, const char *arg1,
2938 const char *arg2)
2939{
2940 char *cmd;
2941 size_t len;
2942 int res;
2943 int ret = 0;
2944
2945 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2946 cmd = os_malloc(len);
2947 if (cmd == NULL)
2948 return -1;
2949 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2950 if (res < 0 || (size_t) res >= len) {
2951 os_free(cmd);
2952 return -1;
2953 }
2954 cmd[len - 1] = '\0';
2955#ifndef _WIN32_WCE
2956 if (system(cmd) < 0)
2957 ret = -1;
2958#endif /* _WIN32_WCE */
2959 os_free(cmd);
2960
2961 return ret;
2962}
2963
2964
2965static void wpa_cli_action_process(const char *msg)
2966{
2967 const char *pos;
2968 char *copy = NULL, *id, *pos2;
2969
2970 pos = msg;
2971 if (*pos == '<') {
2972 /* skip priority */
2973 pos = os_strchr(pos, '>');
2974 if (pos)
2975 pos++;
2976 else
2977 pos = msg;
2978 }
2979
2980 if (str_match(pos, WPA_EVENT_CONNECTED)) {
2981 int new_id = -1;
2982 os_unsetenv("WPA_ID");
2983 os_unsetenv("WPA_ID_STR");
2984 os_unsetenv("WPA_CTRL_DIR");
2985
2986 pos = os_strstr(pos, "[id=");
2987 if (pos)
2988 copy = os_strdup(pos + 4);
2989
2990 if (copy) {
2991 pos2 = id = copy;
2992 while (*pos2 && *pos2 != ' ')
2993 pos2++;
2994 *pos2++ = '\0';
2995 new_id = atoi(id);
2996 os_setenv("WPA_ID", id, 1);
2997 while (*pos2 && *pos2 != '=')
2998 pos2++;
2999 if (*pos2 == '=')
3000 pos2++;
3001 id = pos2;
3002 while (*pos2 && *pos2 != ']')
3003 pos2++;
3004 *pos2 = '\0';
3005 os_setenv("WPA_ID_STR", id, 1);
3006 os_free(copy);
3007 }
3008
3009 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3010
3011 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3012 wpa_cli_connected = 1;
3013 wpa_cli_last_id = new_id;
3014 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3015 }
3016 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3017 if (wpa_cli_connected) {
3018 wpa_cli_connected = 0;
3019 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3020 }
3021 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3022 wpa_cli_exec(action_file, ctrl_ifname, pos);
3023 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3024 wpa_cli_exec(action_file, ctrl_ifname, pos);
3025 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3026 wpa_cli_exec(action_file, ctrl_ifname, pos);
3027 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3028 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003029 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3030 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003031 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3032 wpa_cli_exec(action_file, ctrl_ifname, pos);
3033 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3034 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003035 } else if (str_match(pos, AP_STA_CONNECTED)) {
3036 wpa_cli_exec(action_file, ctrl_ifname, pos);
3037 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3038 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003039 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3040 printf("wpa_supplicant is terminating - stop monitoring\n");
3041 wpa_cli_quit = 1;
3042 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003043}
3044
3045
3046#ifndef CONFIG_ANSI_C_EXTRA
3047static void wpa_cli_action_cb(char *msg, size_t len)
3048{
3049 wpa_cli_action_process(msg);
3050}
3051#endif /* CONFIG_ANSI_C_EXTRA */
3052
3053
3054static void wpa_cli_reconnect(void)
3055{
3056 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003057 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3058 return;
3059
3060 if (interactive) {
3061 edit_clear_line();
3062 printf("\rConnection to wpa_supplicant re-established\n");
3063 edit_redraw();
3064 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003065}
3066
3067
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003068static void cli_event(const char *str)
3069{
3070 const char *start, *s;
3071
3072 start = os_strchr(str, '>');
3073 if (start == NULL)
3074 return;
3075
3076 start++;
3077
3078 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3079 s = os_strchr(start, ' ');
3080 if (s == NULL)
3081 return;
3082 s = os_strchr(s + 1, ' ');
3083 if (s == NULL)
3084 return;
3085 cli_txt_list_add(&bsses, s + 1);
3086 return;
3087 }
3088
3089 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3090 s = os_strchr(start, ' ');
3091 if (s == NULL)
3092 return;
3093 s = os_strchr(s + 1, ' ');
3094 if (s == NULL)
3095 return;
3096 cli_txt_list_del_addr(&bsses, s + 1);
3097 return;
3098 }
3099
3100#ifdef CONFIG_P2P
3101 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3102 s = os_strstr(start, " p2p_dev_addr=");
3103 if (s == NULL)
3104 return;
3105 cli_txt_list_add_addr(&p2p_peers, s + 14);
3106 return;
3107 }
3108
3109 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3110 s = os_strstr(start, " p2p_dev_addr=");
3111 if (s == NULL)
3112 return;
3113 cli_txt_list_del_addr(&p2p_peers, s + 14);
3114 return;
3115 }
3116
3117 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3118 s = os_strchr(start, ' ');
3119 if (s == NULL)
3120 return;
3121 cli_txt_list_add_word(&p2p_groups, s + 1);
3122 return;
3123 }
3124
3125 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3126 s = os_strchr(start, ' ');
3127 if (s == NULL)
3128 return;
3129 cli_txt_list_del_word(&p2p_groups, s + 1);
3130 return;
3131 }
3132#endif /* CONFIG_P2P */
3133}
3134
3135
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003136static int check_terminating(const char *msg)
3137{
3138 const char *pos = msg;
3139
3140 if (*pos == '<') {
3141 /* skip priority */
3142 pos = os_strchr(pos, '>');
3143 if (pos)
3144 pos++;
3145 else
3146 pos = msg;
3147 }
3148
3149 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3150 edit_clear_line();
3151 printf("\rConnection to wpa_supplicant lost - trying to "
3152 "reconnect\n");
3153 edit_redraw();
3154 wpa_cli_attached = 0;
3155 wpa_cli_close_connection();
3156 return 1;
3157 }
3158
3159 return 0;
3160}
3161
3162
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003163static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3164{
3165 if (ctrl_conn == NULL) {
3166 wpa_cli_reconnect();
3167 return;
3168 }
3169 while (wpa_ctrl_pending(ctrl) > 0) {
3170 char buf[256];
3171 size_t len = sizeof(buf) - 1;
3172 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3173 buf[len] = '\0';
3174 if (action_monitor)
3175 wpa_cli_action_process(buf);
3176 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003177 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003178 if (wpa_cli_show_event(buf)) {
3179 edit_clear_line();
3180 printf("\r%s\n", buf);
3181 edit_redraw();
3182 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003183
3184 if (interactive && check_terminating(buf) > 0)
3185 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003186 }
3187 } else {
3188 printf("Could not read pending message.\n");
3189 break;
3190 }
3191 }
3192
3193 if (wpa_ctrl_pending(ctrl) < 0) {
3194 printf("Connection to wpa_supplicant lost - trying to "
3195 "reconnect\n");
3196 wpa_cli_reconnect();
3197 }
3198}
3199
3200#define max_args 10
3201
3202static int tokenize_cmd(char *cmd, char *argv[])
3203{
3204 char *pos;
3205 int argc = 0;
3206
3207 pos = cmd;
3208 for (;;) {
3209 while (*pos == ' ')
3210 pos++;
3211 if (*pos == '\0')
3212 break;
3213 argv[argc] = pos;
3214 argc++;
3215 if (argc == max_args)
3216 break;
3217 if (*pos == '"') {
3218 char *pos2 = os_strrchr(pos, '"');
3219 if (pos2)
3220 pos = pos2 + 1;
3221 }
3222 while (*pos != '\0' && *pos != ' ')
3223 pos++;
3224 if (*pos == ' ')
3225 *pos++ = '\0';
3226 }
3227
3228 return argc;
3229}
3230
3231
3232static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3233{
3234 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3235 printf("Connection to wpa_supplicant lost - trying to "
3236 "reconnect\n");
3237 wpa_cli_close_connection();
3238 }
3239 if (!ctrl_conn)
3240 wpa_cli_reconnect();
3241 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3242}
3243
3244
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003245static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3246{
3247 wpa_cli_recv_pending(mon_conn, 0);
3248}
3249
3250
3251static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3252{
3253 char *argv[max_args];
3254 int argc;
3255 argc = tokenize_cmd(cmd, argv);
3256 if (argc)
3257 wpa_request(ctrl_conn, argc, argv);
3258}
3259
3260
3261static void wpa_cli_edit_eof_cb(void *ctx)
3262{
3263 eloop_terminate();
3264}
3265
3266
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003267static int warning_displayed = 0;
3268static char *hfile = NULL;
3269static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003270
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003271static void start_edit(void)
3272{
3273 char *home;
3274 char *ps = NULL;
3275
3276#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3277 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3278#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003279
3280 home = getenv("HOME");
3281 if (home) {
3282 const char *fname = ".wpa_cli_history";
3283 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3284 hfile = os_malloc(hfile_len);
3285 if (hfile)
3286 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3287 }
3288
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003289 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3290 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3291 eloop_terminate();
3292 return;
3293 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003294
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003295 edit_started = 1;
3296 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3297}
3298
3299
3300static void try_connection(void *eloop_ctx, void *timeout_ctx)
3301{
3302 if (ctrl_ifname == NULL)
3303 ctrl_ifname = wpa_cli_get_default_ifname();
3304
3305 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3306 if (!warning_displayed) {
3307 printf("Could not connect to wpa_supplicant: "
3308 "%s - re-trying\n", ctrl_ifname);
3309 warning_displayed = 1;
3310 }
3311 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3312 return;
3313 }
3314
3315 if (warning_displayed)
3316 printf("Connection established.\n");
3317
3318 start_edit();
3319}
3320
3321
3322static void wpa_cli_interactive(void)
3323{
3324 printf("\nInteractive mode\n\n");
3325
3326 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003327 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003328 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003329
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003330 cli_txt_list_flush(&p2p_peers);
3331 cli_txt_list_flush(&p2p_groups);
3332 cli_txt_list_flush(&bsses);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003333 if (edit_started)
3334 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003335 os_free(hfile);
3336 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3337 wpa_cli_close_connection();
3338}
3339
3340
3341static void wpa_cli_action(struct wpa_ctrl *ctrl)
3342{
3343#ifdef CONFIG_ANSI_C_EXTRA
3344 /* TODO: ANSI C version(?) */
3345 printf("Action processing not supported in ANSI C build.\n");
3346#else /* CONFIG_ANSI_C_EXTRA */
3347 fd_set rfds;
3348 int fd, res;
3349 struct timeval tv;
3350 char buf[256]; /* note: large enough to fit in unsolicited messages */
3351 size_t len;
3352
3353 fd = wpa_ctrl_get_fd(ctrl);
3354
3355 while (!wpa_cli_quit) {
3356 FD_ZERO(&rfds);
3357 FD_SET(fd, &rfds);
3358 tv.tv_sec = ping_interval;
3359 tv.tv_usec = 0;
3360 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3361 if (res < 0 && errno != EINTR) {
3362 perror("select");
3363 break;
3364 }
3365
3366 if (FD_ISSET(fd, &rfds))
3367 wpa_cli_recv_pending(ctrl, 1);
3368 else {
3369 /* verify that connection is still working */
3370 len = sizeof(buf) - 1;
3371 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3372 wpa_cli_action_cb) < 0 ||
3373 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3374 printf("wpa_supplicant did not reply to PING "
3375 "command - exiting\n");
3376 break;
3377 }
3378 }
3379 }
3380#endif /* CONFIG_ANSI_C_EXTRA */
3381}
3382
3383
3384static void wpa_cli_cleanup(void)
3385{
3386 wpa_cli_close_connection();
3387 if (pid_file)
3388 os_daemonize_terminate(pid_file);
3389
3390 os_program_deinit();
3391}
3392
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003393
3394static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003395{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003396 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003397}
3398
3399
3400static char * wpa_cli_get_default_ifname(void)
3401{
3402 char *ifname = NULL;
3403
3404#ifdef CONFIG_CTRL_IFACE_UNIX
3405 struct dirent *dent;
3406 DIR *dir = opendir(ctrl_iface_dir);
3407 if (!dir) {
3408#ifdef ANDROID
3409 char ifprop[PROPERTY_VALUE_MAX];
3410 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3411 ifname = os_strdup(ifprop);
3412 printf("Using interface '%s'\n", ifname);
3413 return ifname;
3414 }
3415#endif /* ANDROID */
3416 return NULL;
3417 }
3418 while ((dent = readdir(dir))) {
3419#ifdef _DIRENT_HAVE_D_TYPE
3420 /*
3421 * Skip the file if it is not a socket. Also accept
3422 * DT_UNKNOWN (0) in case the C library or underlying
3423 * file system does not support d_type.
3424 */
3425 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3426 continue;
3427#endif /* _DIRENT_HAVE_D_TYPE */
3428 if (os_strcmp(dent->d_name, ".") == 0 ||
3429 os_strcmp(dent->d_name, "..") == 0)
3430 continue;
3431 printf("Selected interface '%s'\n", dent->d_name);
3432 ifname = os_strdup(dent->d_name);
3433 break;
3434 }
3435 closedir(dir);
3436#endif /* CONFIG_CTRL_IFACE_UNIX */
3437
3438#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003439#ifdef ANDROID
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -07003440 char buf[4096], *pos;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003441#else
3442 char buf[2048], *pos;
3443#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003444 size_t len;
3445 struct wpa_ctrl *ctrl;
3446 int ret;
3447
3448 ctrl = wpa_ctrl_open(NULL);
3449 if (ctrl == NULL)
3450 return NULL;
3451
3452 len = sizeof(buf) - 1;
3453 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3454 if (ret >= 0) {
3455 buf[len] = '\0';
3456 pos = os_strchr(buf, '\n');
3457 if (pos)
3458 *pos = '\0';
3459 ifname = os_strdup(buf);
3460 }
3461 wpa_ctrl_close(ctrl);
3462#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3463
3464 return ifname;
3465}
3466
3467
3468int main(int argc, char *argv[])
3469{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003470 int c;
3471 int daemonize = 0;
3472 int ret = 0;
3473 const char *global = NULL;
3474
3475 if (os_program_init())
3476 return -1;
3477
3478 for (;;) {
3479 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3480 if (c < 0)
3481 break;
3482 switch (c) {
3483 case 'a':
3484 action_file = optarg;
3485 break;
3486 case 'B':
3487 daemonize = 1;
3488 break;
3489 case 'g':
3490 global = optarg;
3491 break;
3492 case 'G':
3493 ping_interval = atoi(optarg);
3494 break;
3495 case 'h':
3496 usage();
3497 return 0;
3498 case 'v':
3499 printf("%s\n", wpa_cli_version);
3500 return 0;
3501 case 'i':
3502 os_free(ctrl_ifname);
3503 ctrl_ifname = os_strdup(optarg);
3504 break;
3505 case 'p':
3506 ctrl_iface_dir = optarg;
3507 break;
3508 case 'P':
3509 pid_file = optarg;
3510 break;
3511 default:
3512 usage();
3513 return -1;
3514 }
3515 }
3516
3517 interactive = (argc == optind) && (action_file == NULL);
3518
3519 if (interactive)
3520 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3521
3522 if (eloop_init())
3523 return -1;
3524
3525 if (global) {
3526#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3527 ctrl_conn = wpa_ctrl_open(NULL);
3528#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3529 ctrl_conn = wpa_ctrl_open(global);
3530#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3531 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003532 fprintf(stderr, "Failed to connect to wpa_supplicant "
3533 "global interface: %s error: %s\n",
3534 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003535 return -1;
3536 }
3537 }
3538
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003539 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003540
3541 if (ctrl_ifname == NULL)
3542 ctrl_ifname = wpa_cli_get_default_ifname();
3543
3544 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003545 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003546 } else {
3547 if (!global &&
3548 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003549 fprintf(stderr, "Failed to connect to non-global "
3550 "ctrl_ifname: %s error: %s\n",
3551 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003552 return -1;
3553 }
3554
3555 if (action_file) {
3556 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3557 wpa_cli_attached = 1;
3558 } else {
3559 printf("Warning: Failed to attach to "
3560 "wpa_supplicant.\n");
3561 return -1;
3562 }
3563 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003564
3565 if (daemonize && os_daemonize(pid_file))
3566 return -1;
3567
3568 if (action_file)
3569 wpa_cli_action(ctrl_conn);
3570 else
3571 ret = wpa_request(ctrl_conn, argc - optind,
3572 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003573 }
3574
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003575 os_free(ctrl_ifname);
3576 eloop_destroy();
3577 wpa_cli_cleanup();
3578
3579 return ret;
3580}
3581
3582#else /* CONFIG_CTRL_IFACE */
3583int main(int argc, char *argv[])
3584{
3585 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3586 return -1;
3587}
3588#endif /* CONFIG_CTRL_IFACE */