blob: 90e416985e19f21300db8e136677da737ab92ffd [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 Shmidtc97d8bf2011-08-30 11:10:13 -0700406 char buf[4096];
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -0700407#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
408 char _cmd[256];
409#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700410 size_t len;
411 int ret;
412
413 if (ctrl_conn == NULL) {
414 printf("Not connected to wpa_supplicant - command dropped.\n");
415 return -1;
416 }
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -0700417#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
418 if (redirect_interface) {
419 char *arg;
420 arg = os_strchr(cmd, ' ');
421 if (arg) {
422 *arg++ = '\0';
423 ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s %s", cmd, redirect_interface, arg);
424 }
425 else {
426 ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s", cmd, redirect_interface);
427 }
428 cmd = _cmd;
429 os_free(redirect_interface);
430 redirect_interface = NULL;
431 }
432#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700433 len = sizeof(buf) - 1;
434 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
435 wpa_cli_msg_cb);
436 if (ret == -2) {
437 printf("'%s' command timed out.\n", cmd);
438 return -2;
439 } else if (ret < 0) {
440 printf("'%s' command failed.\n", cmd);
441 return -1;
442 }
443 if (print) {
444 buf[len] = '\0';
445 printf("%s", buf);
446 if (interactive && len > 0 && buf[len - 1] != '\n')
447 printf("\n");
448 }
449 return 0;
450}
451
452
453static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
454{
455 return _wpa_ctrl_command(ctrl, cmd, 1);
456}
457
458
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700459static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
460 char *argv[])
461{
462 int i, res;
463 char *pos, *end;
464
465 pos = buf;
466 end = buf + buflen;
467
468 res = os_snprintf(pos, end - pos, "%s", cmd);
469 if (res < 0 || res >= end - pos)
470 goto fail;
471 pos += res;
472
473 for (i = 0; i < argc; i++) {
474 res = os_snprintf(pos, end - pos, " %s", argv[i]);
475 if (res < 0 || res >= end - pos)
476 goto fail;
477 pos += res;
478 }
479
480 buf[buflen - 1] = '\0';
481 return 0;
482
483fail:
484 printf("Too long command\n");
485 return -1;
486}
487
488
489static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
490 int argc, char *argv[])
491{
492 char buf[256];
493 if (argc < min_args) {
494 printf("Invalid %s command - at least %d argument%s "
495 "required.\n", cmd, min_args,
496 min_args > 1 ? "s are" : " is");
497 return -1;
498 }
499 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
500 return -1;
501 return wpa_ctrl_command(ctrl, buf);
502}
503
504
505static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
506{
507 return wpa_ctrl_command(ctrl, "IFNAME");
508}
509
510
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700511static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800513 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
514 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
515 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
516 return wpa_ctrl_command(ctrl, "STATUS-WPS");
517 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700518}
519
520
521static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
522{
523 return wpa_ctrl_command(ctrl, "PING");
524}
525
526
527static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
528{
529 return wpa_ctrl_command(ctrl, "RELOG");
530}
531
532
533static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
534{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700535 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700536}
537
538
539static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
540{
541 return wpa_ctrl_command(ctrl, "MIB");
542}
543
544
545static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
546{
547 return wpa_ctrl_command(ctrl, "PMKSA");
548}
549
550
551static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
552{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700553 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700554 return 0;
555}
556
557
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700558static char ** wpa_cli_complete_help(const char *str, int pos)
559{
560 int arg = get_cmd_arg_num(str, pos);
561 char **res = NULL;
562
563 switch (arg) {
564 case 1:
565 res = wpa_list_cmd_list();
566 break;
567 }
568
569 return res;
570}
571
572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
574{
575 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
576 return 0;
577}
578
579
580static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
581{
582 wpa_cli_quit = 1;
583 if (interactive)
584 eloop_terminate();
585 return 0;
586}
587
588
589static void wpa_cli_show_variables(void)
590{
591 printf("set variables:\n"
592 " EAPOL::heldPeriod (EAPOL state machine held period, "
593 "in seconds)\n"
594 " EAPOL::authPeriod (EAPOL state machine authentication "
595 "period, in seconds)\n"
596 " EAPOL::startPeriod (EAPOL state machine start period, in "
597 "seconds)\n"
598 " EAPOL::maxStart (EAPOL state machine maximum start "
599 "attempts)\n");
600 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
601 "seconds)\n"
602 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
603 " threshold\n\tpercentage)\n"
604 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
605 "security\n\tassociation in seconds)\n");
606}
607
608
609static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
610{
611 char cmd[256];
612 int res;
613
614 if (argc == 0) {
615 wpa_cli_show_variables();
616 return 0;
617 }
618
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800619 if (argc != 1 && argc != 2) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700620 printf("Invalid SET command: needs two arguments (variable "
621 "name and value)\n");
622 return -1;
623 }
624
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800625 if (argc == 1)
626 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
627 else
628 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
629 argv[0], argv[1]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700630 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
631 printf("Too long SET command.\n");
632 return -1;
633 }
634 return wpa_ctrl_command(ctrl, cmd);
635}
636
637
638static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
639{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700640 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700641}
642
643
644static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
645{
646 return wpa_ctrl_command(ctrl, "LOGOFF");
647}
648
649
650static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
651{
652 return wpa_ctrl_command(ctrl, "LOGON");
653}
654
655
656static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
657 char *argv[])
658{
659 return wpa_ctrl_command(ctrl, "REASSOCIATE");
660}
661
662
663static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
664 char *argv[])
665{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700666 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700667}
668
669
670static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
671{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700672 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700673}
674
675
676static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
677 char *argv[])
678{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700679 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700680}
681
682
683static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
684 char *argv[])
685{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700686 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700687}
688
689
690static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
691 char *argv[])
692{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700693 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700694}
695
696
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700697static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
698{
699 char cmd[256];
700 int res;
701
702 if (argc < 1)
703 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
704 else
705 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
706 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
707 printf("Too long BSS_FLUSH command.\n");
708 return -1;
709 }
710 return wpa_ctrl_command(ctrl, cmd);
711}
712
713
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700714static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
715 char *argv[])
716{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700717 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700718}
719
720
721static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
722{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700723 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700724}
725
726
727static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
728{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700729 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700730}
731
732
733static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
734{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700735 if (argc == 0) {
736 printf("Invalid WPS_PIN command: need one or two arguments:\n"
737 "- BSSID: use 'any' to select any\n"
738 "- PIN: optional, used only with devices that have no "
739 "display\n");
740 return -1;
741 }
742
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700743 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700744}
745
746
747static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
748 char *argv[])
749{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700750 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700751}
752
753
754static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
755 char *argv[])
756{
757 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
758}
759
760
Dmitry Shmidt04949592012-07-19 12:16:46 -0700761#ifdef CONFIG_WPS_NFC
762
763static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
764{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700765 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700766}
767
768
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800769static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
770 char *argv[])
771{
772 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
773}
774
775
Dmitry Shmidt04949592012-07-19 12:16:46 -0700776static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
777 char *argv[])
778{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700779 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700780}
781
782
783static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
784 char *argv[])
785{
786 int ret;
787 char *buf;
788 size_t buflen;
789
790 if (argc != 1) {
791 printf("Invalid 'wps_nfc_tag_read' command - one argument "
792 "is required.\n");
793 return -1;
794 }
795
796 buflen = 18 + os_strlen(argv[0]);
797 buf = os_malloc(buflen);
798 if (buf == NULL)
799 return -1;
800 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
801
802 ret = wpa_ctrl_command(ctrl, buf);
803 os_free(buf);
804
805 return ret;
806}
807
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800808
809static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
810 char *argv[])
811{
812 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
813}
814
815
816static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
817 char *argv[])
818{
819 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
820}
821
822
823static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
824 char *argv[])
825{
826 int ret;
827 char *buf;
828 size_t buflen;
829
830 if (argc != 1) {
831 printf("Invalid 'nfc_rx_handover_req' command - one argument "
832 "is required.\n");
833 return -1;
834 }
835
836 buflen = 21 + os_strlen(argv[0]);
837 buf = os_malloc(buflen);
838 if (buf == NULL)
839 return -1;
840 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
841
842 ret = wpa_ctrl_command(ctrl, buf);
843 os_free(buf);
844
845 return ret;
846}
847
848
849static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
850 char *argv[])
851{
852 int ret;
853 char *buf;
854 size_t buflen;
855
856 if (argc != 1) {
857 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
858 "is required.\n");
859 return -1;
860 }
861
862 buflen = 21 + os_strlen(argv[0]);
863 buf = os_malloc(buflen);
864 if (buf == NULL)
865 return -1;
866 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
867
868 ret = wpa_ctrl_command(ctrl, buf);
869 os_free(buf);
870
871 return ret;
872}
873
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800874
875static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
876 char *argv[])
877{
878 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
879}
880
Dmitry Shmidt04949592012-07-19 12:16:46 -0700881#endif /* CONFIG_WPS_NFC */
882
883
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700884static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
885{
886 char cmd[256];
887 int res;
888
889 if (argc == 2)
890 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
891 argv[0], argv[1]);
892 else if (argc == 5 || argc == 6) {
893 char ssid_hex[2 * 32 + 1];
894 char key_hex[2 * 64 + 1];
895 int i;
896
897 ssid_hex[0] = '\0';
898 for (i = 0; i < 32; i++) {
899 if (argv[2][i] == '\0')
900 break;
901 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
902 }
903
904 key_hex[0] = '\0';
905 if (argc == 6) {
906 for (i = 0; i < 64; i++) {
907 if (argv[5][i] == '\0')
908 break;
909 os_snprintf(&key_hex[i * 2], 3, "%02x",
910 argv[5][i]);
911 }
912 }
913
914 res = os_snprintf(cmd, sizeof(cmd),
915 "WPS_REG %s %s %s %s %s %s",
916 argv[0], argv[1], ssid_hex, argv[3], argv[4],
917 key_hex);
918 } else {
919 printf("Invalid WPS_REG command: need two arguments:\n"
920 "- BSSID of the target AP\n"
921 "- AP PIN\n");
922 printf("Alternatively, six arguments can be used to "
923 "reconfigure the AP:\n"
924 "- BSSID of the target AP\n"
925 "- AP PIN\n"
926 "- new SSID\n"
927 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
928 "- new encr (NONE, WEP, TKIP, CCMP)\n"
929 "- new key\n");
930 return -1;
931 }
932
933 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
934 printf("Too long WPS_REG command.\n");
935 return -1;
936 }
937 return wpa_ctrl_command(ctrl, cmd);
938}
939
940
941static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
942 char *argv[])
943{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700944 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700945}
946
947
948static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
949 char *argv[])
950{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700951 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700952}
953
954
955static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
956 char *argv[])
957{
958 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
959
960}
961
962
963static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
964 char *argv[])
965{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700966 if (argc < 2) {
967 printf("Invalid WPS_ER_PIN command: need at least two "
968 "arguments:\n"
969 "- UUID: use 'any' to select any\n"
970 "- PIN: Enrollee PIN\n"
971 "optional: - Enrollee MAC address\n");
972 return -1;
973 }
974
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700975 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700976}
977
978
979static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
980 char *argv[])
981{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700982 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700983}
984
985
986static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
987 char *argv[])
988{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989 if (argc != 2) {
990 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
991 "- UUID: specify which AP to use\n"
992 "- PIN: AP PIN\n");
993 return -1;
994 }
995
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700996 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700997}
998
999
1000static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1001 char *argv[])
1002{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001003 if (argc != 2) {
1004 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1005 "arguments:\n"
1006 "- UUID: specify which AP to use\n"
1007 "- Network configuration id\n");
1008 return -1;
1009 }
1010
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001011 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001012}
1013
1014
1015static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1016 char *argv[])
1017{
1018 char cmd[256];
1019 int res;
1020
1021 if (argc == 5 || argc == 6) {
1022 char ssid_hex[2 * 32 + 1];
1023 char key_hex[2 * 64 + 1];
1024 int i;
1025
1026 ssid_hex[0] = '\0';
1027 for (i = 0; i < 32; i++) {
1028 if (argv[2][i] == '\0')
1029 break;
1030 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1031 }
1032
1033 key_hex[0] = '\0';
1034 if (argc == 6) {
1035 for (i = 0; i < 64; i++) {
1036 if (argv[5][i] == '\0')
1037 break;
1038 os_snprintf(&key_hex[i * 2], 3, "%02x",
1039 argv[5][i]);
1040 }
1041 }
1042
1043 res = os_snprintf(cmd, sizeof(cmd),
1044 "WPS_ER_CONFIG %s %s %s %s %s %s",
1045 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1046 key_hex);
1047 } else {
1048 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1049 "- AP UUID\n"
1050 "- AP PIN\n"
1051 "- new SSID\n"
1052 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1053 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1054 "- new key\n");
1055 return -1;
1056 }
1057
1058 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1059 printf("Too long WPS_ER_CONFIG command.\n");
1060 return -1;
1061 }
1062 return wpa_ctrl_command(ctrl, cmd);
1063}
1064
1065
Dmitry Shmidt04949592012-07-19 12:16:46 -07001066#ifdef CONFIG_WPS_NFC
1067static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1068 char *argv[])
1069{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001070 if (argc != 2) {
1071 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1072 "arguments:\n"
1073 "- WPS/NDEF: token format\n"
1074 "- UUID: specify which AP to use\n");
1075 return -1;
1076 }
1077
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001078 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001079}
1080#endif /* CONFIG_WPS_NFC */
1081
1082
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001083static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1084{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001085 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001086}
1087
1088
1089static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1090{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001091 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001092}
1093
1094
1095static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1096{
1097 char cmd[256], *pos, *end;
1098 int i, ret;
1099
1100 if (argc < 2) {
1101 printf("Invalid IDENTITY command: needs two arguments "
1102 "(network id and identity)\n");
1103 return -1;
1104 }
1105
1106 end = cmd + sizeof(cmd);
1107 pos = cmd;
1108 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1109 argv[0], argv[1]);
1110 if (ret < 0 || ret >= end - pos) {
1111 printf("Too long IDENTITY command.\n");
1112 return -1;
1113 }
1114 pos += ret;
1115 for (i = 2; i < argc; i++) {
1116 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1117 if (ret < 0 || ret >= end - pos) {
1118 printf("Too long IDENTITY command.\n");
1119 return -1;
1120 }
1121 pos += ret;
1122 }
1123
1124 return wpa_ctrl_command(ctrl, cmd);
1125}
1126
1127
1128static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1129{
1130 char cmd[256], *pos, *end;
1131 int i, ret;
1132
1133 if (argc < 2) {
1134 printf("Invalid PASSWORD command: needs two arguments "
1135 "(network id and password)\n");
1136 return -1;
1137 }
1138
1139 end = cmd + sizeof(cmd);
1140 pos = cmd;
1141 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1142 argv[0], argv[1]);
1143 if (ret < 0 || ret >= end - pos) {
1144 printf("Too long PASSWORD command.\n");
1145 return -1;
1146 }
1147 pos += ret;
1148 for (i = 2; i < argc; i++) {
1149 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1150 if (ret < 0 || ret >= end - pos) {
1151 printf("Too long PASSWORD command.\n");
1152 return -1;
1153 }
1154 pos += ret;
1155 }
1156
1157 return wpa_ctrl_command(ctrl, cmd);
1158}
1159
1160
1161static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1162 char *argv[])
1163{
1164 char cmd[256], *pos, *end;
1165 int i, ret;
1166
1167 if (argc < 2) {
1168 printf("Invalid NEW_PASSWORD command: needs two arguments "
1169 "(network id and password)\n");
1170 return -1;
1171 }
1172
1173 end = cmd + sizeof(cmd);
1174 pos = cmd;
1175 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1176 argv[0], argv[1]);
1177 if (ret < 0 || ret >= end - pos) {
1178 printf("Too long NEW_PASSWORD command.\n");
1179 return -1;
1180 }
1181 pos += ret;
1182 for (i = 2; i < argc; i++) {
1183 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1184 if (ret < 0 || ret >= end - pos) {
1185 printf("Too long NEW_PASSWORD command.\n");
1186 return -1;
1187 }
1188 pos += ret;
1189 }
1190
1191 return wpa_ctrl_command(ctrl, cmd);
1192}
1193
1194
1195static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1196{
1197 char cmd[256], *pos, *end;
1198 int i, ret;
1199
1200 if (argc < 2) {
1201 printf("Invalid PIN command: needs two arguments "
1202 "(network id and pin)\n");
1203 return -1;
1204 }
1205
1206 end = cmd + sizeof(cmd);
1207 pos = cmd;
1208 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1209 argv[0], argv[1]);
1210 if (ret < 0 || ret >= end - pos) {
1211 printf("Too long PIN command.\n");
1212 return -1;
1213 }
1214 pos += ret;
1215 for (i = 2; i < argc; i++) {
1216 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1217 if (ret < 0 || ret >= end - pos) {
1218 printf("Too long PIN command.\n");
1219 return -1;
1220 }
1221 pos += ret;
1222 }
1223 return wpa_ctrl_command(ctrl, cmd);
1224}
1225
1226
1227static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1228{
1229 char cmd[256], *pos, *end;
1230 int i, ret;
1231
1232 if (argc < 2) {
1233 printf("Invalid OTP command: needs two arguments (network "
1234 "id and password)\n");
1235 return -1;
1236 }
1237
1238 end = cmd + sizeof(cmd);
1239 pos = cmd;
1240 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1241 argv[0], argv[1]);
1242 if (ret < 0 || ret >= end - pos) {
1243 printf("Too long OTP command.\n");
1244 return -1;
1245 }
1246 pos += ret;
1247 for (i = 2; i < argc; i++) {
1248 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1249 if (ret < 0 || ret >= end - pos) {
1250 printf("Too long OTP command.\n");
1251 return -1;
1252 }
1253 pos += ret;
1254 }
1255
1256 return wpa_ctrl_command(ctrl, cmd);
1257}
1258
1259
1260static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1261 char *argv[])
1262{
1263 char cmd[256], *pos, *end;
1264 int i, ret;
1265
1266 if (argc < 2) {
1267 printf("Invalid PASSPHRASE command: needs two arguments "
1268 "(network id and passphrase)\n");
1269 return -1;
1270 }
1271
1272 end = cmd + sizeof(cmd);
1273 pos = cmd;
1274 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1275 argv[0], argv[1]);
1276 if (ret < 0 || ret >= end - pos) {
1277 printf("Too long PASSPHRASE command.\n");
1278 return -1;
1279 }
1280 pos += ret;
1281 for (i = 2; i < argc; i++) {
1282 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1283 if (ret < 0 || ret >= end - pos) {
1284 printf("Too long PASSPHRASE command.\n");
1285 return -1;
1286 }
1287 pos += ret;
1288 }
1289
1290 return wpa_ctrl_command(ctrl, cmd);
1291}
1292
1293
1294static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1295{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001296 if (argc < 2) {
1297 printf("Invalid BSSID command: needs two arguments (network "
1298 "id and BSSID)\n");
1299 return -1;
1300 }
1301
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001302 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001303}
1304
1305
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001306static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1307{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001308 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001309}
1310
1311
1312static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1313{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001314 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001315}
1316
1317
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001318static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1319 char *argv[])
1320{
1321 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1322}
1323
1324
1325static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1326 char *argv[])
1327{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001328 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001329}
1330
1331
1332static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1333 char *argv[])
1334{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001335 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001336}
1337
1338
1339static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1340 char *argv[])
1341{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001342 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001343}
1344
1345
1346static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1347 char *argv[])
1348{
1349 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1350}
1351
1352
1353static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1354 char *argv[])
1355{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001356 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001357}
1358
1359
1360static void wpa_cli_show_network_variables(void)
1361{
1362 printf("set_network variables:\n"
1363 " ssid (network name, SSID)\n"
1364 " psk (WPA passphrase or pre-shared key)\n"
1365 " key_mgmt (key management protocol)\n"
1366 " identity (EAP identity)\n"
1367 " password (EAP password)\n"
1368 " ...\n"
1369 "\n"
1370 "Note: Values are entered in the same format as the "
1371 "configuration file is using,\n"
1372 "i.e., strings values need to be inside double quotation "
1373 "marks.\n"
1374 "For example: set_network 1 ssid \"network name\"\n"
1375 "\n"
1376 "Please see wpa_supplicant.conf documentation for full list "
1377 "of\navailable variables.\n");
1378}
1379
1380
1381static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1382 char *argv[])
1383{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001384 if (argc == 0) {
1385 wpa_cli_show_network_variables();
1386 return 0;
1387 }
1388
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001389 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001390 printf("Invalid SET_NETWORK command: needs three arguments\n"
1391 "(network id, variable name, and value)\n");
1392 return -1;
1393 }
1394
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001395 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001396}
1397
1398
1399static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1400 char *argv[])
1401{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001402 if (argc == 0) {
1403 wpa_cli_show_network_variables();
1404 return 0;
1405 }
1406
1407 if (argc != 2) {
1408 printf("Invalid GET_NETWORK command: needs two arguments\n"
1409 "(network id and variable name)\n");
1410 return -1;
1411 }
1412
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001413 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001414}
1415
1416
Dmitry Shmidt04949592012-07-19 12:16:46 -07001417static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1418 char *argv[])
1419{
1420 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1421}
1422
1423
1424static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1425{
1426 return wpa_ctrl_command(ctrl, "ADD_CRED");
1427}
1428
1429
1430static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1431 char *argv[])
1432{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001433 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001434}
1435
1436
1437static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1438{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001439 if (argc != 3) {
1440 printf("Invalid SET_CRED command: needs three arguments\n"
1441 "(cred id, variable name, and value)\n");
1442 return -1;
1443 }
1444
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001445 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001446}
1447
1448
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001449static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1450 char *argv[])
1451{
1452 return wpa_ctrl_command(ctrl, "DISCONNECT");
1453}
1454
1455
1456static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1457 char *argv[])
1458{
1459 return wpa_ctrl_command(ctrl, "RECONNECT");
1460}
1461
1462
1463static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1464 char *argv[])
1465{
1466 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1467}
1468
1469
1470static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1471{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001472 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001473}
1474
1475
1476static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1477 char *argv[])
1478{
1479 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1480}
1481
1482
1483static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1484{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001485 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001486}
1487
1488
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001489static char ** wpa_cli_complete_bss(const char *str, int pos)
1490{
1491 int arg = get_cmd_arg_num(str, pos);
1492 char **res = NULL;
1493
1494 switch (arg) {
1495 case 1:
1496 res = cli_txt_list_array(&bsses);
1497 break;
1498 }
1499
1500 return res;
1501}
1502
1503
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001504static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1505 char *argv[])
1506{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001507 if (argc < 1 || argc > 2) {
1508 printf("Invalid GET_CAPABILITY command: need either one or "
1509 "two arguments\n");
1510 return -1;
1511 }
1512
1513 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1514 printf("Invalid GET_CAPABILITY command: second argument, "
1515 "if any, must be 'strict'\n");
1516 return -1;
1517 }
1518
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001519 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001520}
1521
1522
1523static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1524{
1525 printf("Available interfaces:\n");
1526 return wpa_ctrl_command(ctrl, "INTERFACES");
1527}
1528
1529
1530static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1531{
1532 if (argc < 1) {
1533 wpa_cli_list_interfaces(ctrl);
1534 return 0;
1535 }
1536
1537 wpa_cli_close_connection();
1538 os_free(ctrl_ifname);
1539 ctrl_ifname = os_strdup(argv[0]);
1540
1541 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1542 printf("Connected to interface '%s.\n", ctrl_ifname);
1543 } else {
1544 printf("Could not connect to interface '%s' - re-trying\n",
1545 ctrl_ifname);
1546 }
1547 return 0;
1548}
1549
1550
1551static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1552 char *argv[])
1553{
1554 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1555}
1556
1557
1558static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1559 char *argv[])
1560{
1561 return wpa_ctrl_command(ctrl, "TERMINATE");
1562}
1563
1564
1565static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1566 char *argv[])
1567{
1568 char cmd[256];
1569 int res;
1570
1571 if (argc < 1) {
1572 printf("Invalid INTERFACE_ADD command: needs at least one "
1573 "argument (interface name)\n"
1574 "All arguments: ifname confname driver ctrl_interface "
1575 "driver_param bridge_name\n");
1576 return -1;
1577 }
1578
1579 /*
1580 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1581 * <driver_param>TAB<bridge_name>
1582 */
1583 res = os_snprintf(cmd, sizeof(cmd),
1584 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1585 argv[0],
1586 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1587 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1588 argc > 5 ? argv[5] : "");
1589 if (res < 0 || (size_t) res >= sizeof(cmd))
1590 return -1;
1591 cmd[sizeof(cmd) - 1] = '\0';
1592 return wpa_ctrl_command(ctrl, cmd);
1593}
1594
1595
1596static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1597 char *argv[])
1598{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001599 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001600}
1601
1602
1603static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1604 char *argv[])
1605{
1606 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1607}
1608
1609
1610#ifdef CONFIG_AP
1611static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1612{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001613 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001614}
1615
1616
1617static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1618 char *addr, size_t addr_len)
1619{
1620 char buf[4096], *pos;
1621 size_t len;
1622 int ret;
1623
1624 if (ctrl_conn == NULL) {
1625 printf("Not connected to hostapd - command dropped.\n");
1626 return -1;
1627 }
1628 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001629 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001630 wpa_cli_msg_cb);
1631 if (ret == -2) {
1632 printf("'%s' command timed out.\n", cmd);
1633 return -2;
1634 } else if (ret < 0) {
1635 printf("'%s' command failed.\n", cmd);
1636 return -1;
1637 }
1638
1639 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001640 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001641 return -1;
1642 printf("%s", buf);
1643
1644 pos = buf;
1645 while (*pos != '\0' && *pos != '\n')
1646 pos++;
1647 *pos = '\0';
1648 os_strlcpy(addr, buf, addr_len);
1649 return 0;
1650}
1651
1652
1653static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1654{
1655 char addr[32], cmd[64];
1656
1657 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1658 return 0;
1659 do {
1660 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1661 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1662
1663 return -1;
1664}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001665
1666
1667static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1668 char *argv[])
1669{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001670 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001671}
1672
1673
1674static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1675 char *argv[])
1676{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001677 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001678}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001679#endif /* CONFIG_AP */
1680
1681
1682static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1683{
1684 return wpa_ctrl_command(ctrl, "SUSPEND");
1685}
1686
1687
1688static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1689{
1690 return wpa_ctrl_command(ctrl, "RESUME");
1691}
1692
1693
1694static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1695{
1696 return wpa_ctrl_command(ctrl, "DROP_SA");
1697}
1698
1699
1700static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1701{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001702 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001703}
1704
1705
1706#ifdef CONFIG_P2P
1707
1708static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1709{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001710 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1711}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001712
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001713
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001714static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1715{
1716 char **res = NULL;
1717 int arg = get_cmd_arg_num(str, pos);
1718
1719 res = os_calloc(6, sizeof(char *));
1720 if (res == NULL)
1721 return NULL;
1722 res[0] = os_strdup("type=social");
1723 if (res[0] == NULL) {
1724 os_free(res);
1725 return NULL;
1726 }
1727 res[1] = os_strdup("type=progressive");
1728 if (res[1] == NULL)
1729 return res;
1730 res[2] = os_strdup("delay=");
1731 if (res[2] == NULL)
1732 return res;
1733 res[3] = os_strdup("dev_id=");
1734 if (res[3] == NULL)
1735 return res;
1736 if (arg == 1)
1737 res[4] = os_strdup("[timeout]");
1738
1739 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001740}
1741
1742
1743static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1744 char *argv[])
1745{
1746 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1747}
1748
1749
1750static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1751 char *argv[])
1752{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001753 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001754}
1755
1756
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001757static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1758{
1759 int arg = get_cmd_arg_num(str, pos);
1760 char **res = NULL;
1761
1762 switch (arg) {
1763 case 1:
1764 res = cli_txt_list_array(&p2p_peers);
1765 break;
1766 }
1767
1768 return res;
1769}
1770
1771
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001772static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1773 char *argv[])
1774{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001775 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001776}
1777
1778
1779static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1780 char *argv[])
1781{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001782 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001783}
1784
1785
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001786static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1787{
1788 int arg = get_cmd_arg_num(str, pos);
1789 char **res = NULL;
1790
1791 switch (arg) {
1792 case 1:
1793 res = cli_txt_list_array(&p2p_groups);
1794 break;
1795 }
1796
1797 return res;
1798}
1799
1800
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001801static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1802 char *argv[])
1803{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001804 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001805}
1806
1807
1808static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1809 char *argv[])
1810{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001811 if (argc != 2 && argc != 3) {
1812 printf("Invalid P2P_PROV_DISC command: needs at least "
1813 "two arguments, address and config method\n"
1814 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001815 return -1;
1816 }
1817
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001818 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001819}
1820
1821
1822static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1823 char *argv[])
1824{
1825 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1826}
1827
1828
1829static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1830 char *argv[])
1831{
1832 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001833
1834 if (argc != 2 && argc != 4) {
1835 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1836 "arguments (address and TLVs) or four arguments "
1837 "(address, \"upnp\", version, search target "
1838 "(SSDP ST:)\n");
1839 return -1;
1840 }
1841
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001842 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001843 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001844 return wpa_ctrl_command(ctrl, cmd);
1845}
1846
1847
1848static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1849 int argc, char *argv[])
1850{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001851 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001852}
1853
1854
1855static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1856 char *argv[])
1857{
1858 char cmd[4096];
1859 int res;
1860
1861 if (argc != 4) {
1862 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1863 "arguments (freq, address, dialog token, and TLVs)\n");
1864 return -1;
1865 }
1866
1867 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1868 argv[0], argv[1], argv[2], argv[3]);
1869 if (res < 0 || (size_t) res >= sizeof(cmd))
1870 return -1;
1871 cmd[sizeof(cmd) - 1] = '\0';
1872 return wpa_ctrl_command(ctrl, cmd);
1873}
1874
1875
1876static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1877 char *argv[])
1878{
1879 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1880}
1881
1882
1883static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1884 int argc, char *argv[])
1885{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001886 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001887}
1888
1889
1890static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1891 char *argv[])
1892{
1893 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1894}
1895
1896
1897static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1898 char *argv[])
1899{
1900 char cmd[4096];
1901 int res;
1902
1903 if (argc != 3 && argc != 4) {
1904 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1905 "arguments\n");
1906 return -1;
1907 }
1908
1909 if (argc == 4)
1910 res = os_snprintf(cmd, sizeof(cmd),
1911 "P2P_SERVICE_ADD %s %s %s %s",
1912 argv[0], argv[1], argv[2], argv[3]);
1913 else
1914 res = os_snprintf(cmd, sizeof(cmd),
1915 "P2P_SERVICE_ADD %s %s %s",
1916 argv[0], argv[1], argv[2]);
1917 if (res < 0 || (size_t) res >= sizeof(cmd))
1918 return -1;
1919 cmd[sizeof(cmd) - 1] = '\0';
1920 return wpa_ctrl_command(ctrl, cmd);
1921}
1922
1923
1924static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1925 char *argv[])
1926{
1927 char cmd[4096];
1928 int res;
1929
1930 if (argc != 2 && argc != 3) {
1931 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1932 "arguments\n");
1933 return -1;
1934 }
1935
1936 if (argc == 3)
1937 res = os_snprintf(cmd, sizeof(cmd),
1938 "P2P_SERVICE_DEL %s %s %s",
1939 argv[0], argv[1], argv[2]);
1940 else
1941 res = os_snprintf(cmd, sizeof(cmd),
1942 "P2P_SERVICE_DEL %s %s",
1943 argv[0], argv[1]);
1944 if (res < 0 || (size_t) res >= sizeof(cmd))
1945 return -1;
1946 cmd[sizeof(cmd) - 1] = '\0';
1947 return wpa_ctrl_command(ctrl, cmd);
1948}
1949
1950
1951static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1952 int argc, char *argv[])
1953{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001954 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001955}
1956
1957
1958static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1959 int argc, char *argv[])
1960{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001961 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001962}
1963
1964
1965static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1966{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001967 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001968}
1969
1970
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001971static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1972{
1973 int arg = get_cmd_arg_num(str, pos);
1974 char **res = NULL;
1975
1976 switch (arg) {
1977 case 1:
1978 res = cli_txt_list_array(&p2p_peers);
1979 break;
1980 }
1981
1982 return res;
1983}
1984
1985
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001986static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1987 char *addr, size_t addr_len,
1988 int discovered)
1989{
1990 char buf[4096], *pos;
1991 size_t len;
1992 int ret;
1993
1994 if (ctrl_conn == NULL)
1995 return -1;
1996 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001997 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001998 wpa_cli_msg_cb);
1999 if (ret == -2) {
2000 printf("'%s' command timed out.\n", cmd);
2001 return -2;
2002 } else if (ret < 0) {
2003 printf("'%s' command failed.\n", cmd);
2004 return -1;
2005 }
2006
2007 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002008 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002009 return -1;
2010
2011 pos = buf;
2012 while (*pos != '\0' && *pos != '\n')
2013 pos++;
2014 *pos++ = '\0';
2015 os_strlcpy(addr, buf, addr_len);
2016 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2017 printf("%s\n", addr);
2018 return 0;
2019}
2020
2021
2022static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2023{
2024 char addr[32], cmd[64];
2025 int discovered;
2026
2027 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2028
2029 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2030 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002031 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002032 do {
2033 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2034 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2035 discovered) == 0);
2036
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002037 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002038}
2039
2040
2041static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2042{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002043 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002044}
2045
2046
2047static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2048{
2049 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2050}
2051
2052
2053static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2054 char *argv[])
2055{
2056 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2057}
2058
2059
2060static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2061 char *argv[])
2062{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002063 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002064}
2065
2066
2067static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2068 char *argv[])
2069{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002070 if (argc != 0 && argc != 2 && argc != 4) {
2071 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2072 "(preferred duration, interval; in microsecods).\n"
2073 "Optional second pair can be used to provide "
2074 "acceptable values.\n");
2075 return -1;
2076 }
2077
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002078 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002079}
2080
2081
2082static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2083 char *argv[])
2084{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002085 if (argc != 0 && argc != 2) {
2086 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2087 "(availability period, availability interval; in "
2088 "millisecods).\n"
2089 "Extended Listen Timing can be cancelled with this "
2090 "command when used without parameters.\n");
2091 return -1;
2092 }
2093
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002094 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2095}
2096
2097#endif /* CONFIG_P2P */
2098
2099#ifdef CONFIG_WIFI_DISPLAY
2100
2101static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2102 char *argv[])
2103{
2104 char cmd[100];
2105 int res;
2106
2107 if (argc != 1 && argc != 2) {
2108 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2109 "arguments (subelem, hexdump)\n");
2110 return -1;
2111 }
2112
2113 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2114 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002115 if (res < 0 || (size_t) res >= sizeof(cmd))
2116 return -1;
2117 cmd[sizeof(cmd) - 1] = '\0';
2118 return wpa_ctrl_command(ctrl, cmd);
2119}
2120
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002121
2122static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2123 char *argv[])
2124{
2125 char cmd[100];
2126 int res;
2127
2128 if (argc != 1) {
2129 printf("Invalid WFD_SUBELEM_GET command: needs one "
2130 "argument (subelem)\n");
2131 return -1;
2132 }
2133
2134 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2135 argv[0]);
2136 if (res < 0 || (size_t) res >= sizeof(cmd))
2137 return -1;
2138 cmd[sizeof(cmd) - 1] = '\0';
2139 return wpa_ctrl_command(ctrl, cmd);
2140}
2141#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002142
2143
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002144#ifdef CONFIG_INTERWORKING
2145static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2146 char *argv[])
2147{
2148 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2149}
2150
2151
2152static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2153 char *argv[])
2154{
2155 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2156}
2157
2158
2159static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2160 char *argv[])
2161{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002162 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002163}
2164
2165
2166static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2167 char *argv[])
2168{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002169 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002170}
2171
2172
2173static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2174{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002175 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2176}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002177
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002178
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002179static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2180 char *argv[])
2181{
2182 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2183}
2184
2185
2186static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2187 char *argv[])
2188{
2189 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002190}
2191#endif /* CONFIG_INTERWORKING */
2192
2193
Dmitry Shmidt04949592012-07-19 12:16:46 -07002194#ifdef CONFIG_HS20
2195
2196static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2197 char *argv[])
2198{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002199 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002200}
2201
2202
2203static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2204 char *argv[])
2205{
2206 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002207
2208 if (argc == 0) {
2209 printf("Command needs one or two arguments (dst mac addr and "
2210 "optional home realm)\n");
2211 return -1;
2212 }
2213
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002214 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2215 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002216 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002217
2218 return wpa_ctrl_command(ctrl, cmd);
2219}
2220
2221#endif /* CONFIG_HS20 */
2222
2223
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002224static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2225 char *argv[])
2226{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002227 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002228}
2229
2230
2231static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2232 char *argv[])
2233{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002234 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002235}
2236
2237
2238static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2239 char *argv[])
2240{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002241 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002242}
2243
2244
2245static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2246 char *argv[])
2247{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002248 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002249}
2250
2251
2252static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2253 char *argv[])
2254{
2255 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2256}
2257
2258
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002259static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2260 char *argv[])
2261{
2262 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2263}
2264
2265
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002266static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2267 char *argv[])
2268{
2269 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2270}
2271
Dmitry Shmidt04949592012-07-19 12:16:46 -07002272
2273#ifdef CONFIG_AUTOSCAN
2274
2275static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2276{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002277 if (argc == 0)
2278 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2279
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002280 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002281}
2282
2283#endif /* CONFIG_AUTOSCAN */
2284
2285
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002286#ifdef CONFIG_WNM
2287
2288static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2289{
2290 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2291}
2292
2293#endif /* CONFIG_WNM */
2294
2295
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002296static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2297{
2298 if (argc == 0)
2299 return -1;
2300 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2301}
2302
2303
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002304#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002305static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2306{
2307 char cmd[256];
2308 int i;
2309 int len;
2310
2311 if (argc < 1) {
2312 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2313 return -1;
2314 }
2315
2316 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2317 for (i=1; i < argc; i++)
2318 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2319 cmd[sizeof(cmd) - 1] = '\0';
2320 printf("%s: %s\n", __func__, cmd);
2321 return wpa_ctrl_command(ctrl, cmd);
2322}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002323#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002324
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002325
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002326enum wpa_cli_cmd_flags {
2327 cli_cmd_flag_none = 0x00,
2328 cli_cmd_flag_sensitive = 0x01
2329};
2330
2331struct wpa_cli_cmd {
2332 const char *cmd;
2333 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002334 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002335 enum wpa_cli_cmd_flags flags;
2336 const char *usage;
2337};
2338
2339static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002340 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002341 cli_cmd_flag_none,
2342 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002343 { "ifname", wpa_cli_cmd_ifname, NULL,
2344 cli_cmd_flag_none,
2345 "= get current interface name" },
2346 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347 cli_cmd_flag_none,
2348 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002349 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002350 cli_cmd_flag_none,
2351 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002352 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002353 cli_cmd_flag_none,
2354 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002355 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002356 cli_cmd_flag_none,
2357 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002358 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002359 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002360 "[command] = show usage help" },
2361 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002362 cli_cmd_flag_none,
2363 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002364 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002365 cli_cmd_flag_none,
2366 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002367 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002368 cli_cmd_flag_none,
2369 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002370 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002371 cli_cmd_flag_none,
2372 "= exit wpa_cli" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002373 { "set", wpa_cli_cmd_set, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002374 cli_cmd_flag_none,
2375 "= set variables (shows list of variables when run without "
2376 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002377 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002378 cli_cmd_flag_none,
2379 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002380 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002381 cli_cmd_flag_none,
2382 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002383 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002384 cli_cmd_flag_none,
2385 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002386 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002387 cli_cmd_flag_none,
2388 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002389 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002390 cli_cmd_flag_none,
2391 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002392 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002393 cli_cmd_flag_none,
2394 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002395 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002396 cli_cmd_flag_none,
2397 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002398 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002399 cli_cmd_flag_sensitive,
2400 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002401 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002402 cli_cmd_flag_sensitive,
2403 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002404 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002405 cli_cmd_flag_sensitive,
2406 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002407 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002408 cli_cmd_flag_sensitive,
2409 "<network id> <password> = configure one-time-password for an SSID"
2410 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002411 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002412 cli_cmd_flag_sensitive,
2413 "<network id> <passphrase> = configure private key passphrase\n"
2414 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002415 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002416 cli_cmd_flag_none,
2417 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002418 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002419 cli_cmd_flag_none,
2420 "<BSSID> = add a BSSID to the blacklist\n"
2421 "blacklist clear = clear the blacklist\n"
2422 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002423 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002424 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002425 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002426 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002427 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002428 cli_cmd_flag_none,
2429 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002430 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002431 cli_cmd_flag_none,
2432 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002433 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002434 cli_cmd_flag_none,
2435 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002436 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002437 cli_cmd_flag_none,
2438 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002439 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002440 cli_cmd_flag_none,
2441 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002442 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002443 cli_cmd_flag_none,
2444 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002445 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002446 cli_cmd_flag_sensitive,
2447 "<network id> <variable> <value> = set network variables (shows\n"
2448 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002449 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002450 cli_cmd_flag_none,
2451 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002452 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002453 cli_cmd_flag_none,
2454 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002455 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002456 cli_cmd_flag_none,
2457 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002458 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002459 cli_cmd_flag_none,
2460 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002461 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002462 cli_cmd_flag_sensitive,
2463 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002464 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002465 cli_cmd_flag_none,
2466 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002467 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002468 cli_cmd_flag_none,
2469 "= disconnect and wait for reassociate/reconnect command before\n"
2470 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002471 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002472 cli_cmd_flag_none,
2473 "= like reassociate, but only takes effect if already disconnected"
2474 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002475 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 cli_cmd_flag_none,
2477 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002478 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002479 cli_cmd_flag_none,
2480 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002481 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002482 cli_cmd_flag_none,
2483 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002484 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002485 cli_cmd_flag_none,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002486 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002487 "= get capabilies" },
2488 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489 cli_cmd_flag_none,
2490 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002491 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 cli_cmd_flag_none,
2493 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002494 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002495 cli_cmd_flag_none,
2496 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2497 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2498 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002499 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002500 cli_cmd_flag_none,
2501 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002502 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002503 cli_cmd_flag_none,
2504 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002505 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002506 cli_cmd_flag_none,
2507 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002508 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002509 cli_cmd_flag_none,
2510 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002511 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002512 cli_cmd_flag_none,
2513 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002514 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002515 cli_cmd_flag_none,
2516 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002517 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002518 cli_cmd_flag_none,
2519 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002520 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521 cli_cmd_flag_none,
2522 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002523 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002524 cli_cmd_flag_none,
2525 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002526 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002527 cli_cmd_flag_none,
2528 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002529 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002530 cli_cmd_flag_sensitive,
2531 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2532 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002533 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002534 cli_cmd_flag_sensitive,
2535 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002536 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002537 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002538#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002539 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002540 cli_cmd_flag_none,
2541 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002542 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2543 cli_cmd_flag_none,
2544 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002545 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002546 cli_cmd_flag_none,
2547 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002548 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002549 cli_cmd_flag_sensitive,
2550 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002551 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2552 cli_cmd_flag_none,
2553 "<NDEF> <WPS> = create NFC handover request" },
2554 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2555 cli_cmd_flag_none,
2556 "<NDEF> <WPS> = create NFC handover select" },
2557 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2558 cli_cmd_flag_none,
2559 "<hexdump of payload> = report received NFC handover request" },
2560 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2561 cli_cmd_flag_none,
2562 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002563 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2564 cli_cmd_flag_none,
2565 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2566 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002567#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002568 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002569 cli_cmd_flag_sensitive,
2570 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002571 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002572 cli_cmd_flag_sensitive,
2573 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002574 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002575 cli_cmd_flag_none,
2576 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002577 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002578 cli_cmd_flag_none,
2579 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002580 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 cli_cmd_flag_sensitive,
2582 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002583 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002584 cli_cmd_flag_none,
2585 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002586 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587 cli_cmd_flag_sensitive,
2588 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002589 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002590 cli_cmd_flag_none,
2591 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002592 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002593 cli_cmd_flag_sensitive,
2594 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002595#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002596 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002597 cli_cmd_flag_none,
2598 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2599#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002600 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002601 cli_cmd_flag_none,
2602 "<addr> = request RSN authentication with <addr> in IBSS" },
2603#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002604 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002605 cli_cmd_flag_none,
2606 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002607 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002608 cli_cmd_flag_none,
2609 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002610 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002611 cli_cmd_flag_none,
2612 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002613 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002614 cli_cmd_flag_none,
2615 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002616#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002617 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002618 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002619 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002621 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002622 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002623 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 cli_cmd_flag_none,
2625 "<addr> = roam to the specified BSS" },
2626#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002627 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2628 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002629 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002630 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002631 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002632 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2633 cli_cmd_flag_none,
2634 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2635 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002636 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002637 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2638 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002639 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002640 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2641 "[ht40] = add a new P2P group (local end as GO)" },
2642 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2643 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002644 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002645 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646 cli_cmd_flag_none,
2647 "= get the passphrase for a group (GO only)" },
2648 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002649 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002650 "<addr> <TLVs> = schedule service discovery request" },
2651 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002652 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002653 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002654 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002655 cli_cmd_flag_none,
2656 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002657 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002658 cli_cmd_flag_none,
2659 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002660 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 cli_cmd_flag_none,
2662 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002663 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002664 cli_cmd_flag_none,
2665 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002666 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002667 cli_cmd_flag_none,
2668 "<bonjour|upnp> <query|version> <response|service> = add a local "
2669 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002670 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002671 cli_cmd_flag_none,
2672 "<bonjour|upnp> <query|version> [|service] = remove a local "
2673 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002674 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002675 cli_cmd_flag_none,
2676 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002677 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002678 cli_cmd_flag_none,
2679 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002680 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002681 "[discovered] = list known (optionally, only fully discovered) P2P "
2682 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002683 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2684 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002685 "<address> = show information about known P2P peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002686 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002687 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002688 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002689 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002690 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002691 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002692 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2693 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002694 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002695 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2696 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002697 "[<duration> <interval>] [<duration> <interval>] = request GO "
2698 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002699 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2700 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002701 "[<period> <interval>] = set extended listen timing" },
2702#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002703#ifdef CONFIG_WIFI_DISPLAY
2704 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2705 cli_cmd_flag_none,
2706 "<subelem> [contents] = set Wi-Fi Display subelement" },
2707 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2708 cli_cmd_flag_none,
2709 "<subelem> = get Wi-Fi Display subelement" },
2710#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002711#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002712 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002713 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002714 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2715 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002716 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002717 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002718 cli_cmd_flag_none,
2719 "[auto] = perform Interworking network selection" },
2720 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002721 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002722 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002723 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2724 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002725 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002726 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2727 cli_cmd_flag_none,
2728 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2729 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2730 wpa_cli_complete_bss, cli_cmd_flag_none,
2731 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002732#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002733#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002734 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2735 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002736 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2737 },
2738 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002739 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002740 "<addr> <home realm> = get HS20 nai home realm list" },
2741#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002742 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2743 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002744 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002745 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002746 cli_cmd_flag_none,
2747 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002748 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002749 cli_cmd_flag_none,
2750 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002751 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002752 cli_cmd_flag_none,
2753 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002754 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002755 cli_cmd_flag_none,
2756 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002757 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002758 cli_cmd_flag_none,
2759 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002760 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2761 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002762 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002763#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002764 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002765 "[params] = Set or unset (if none) autoscan parameters" },
2766#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002767#ifdef CONFIG_WNM
2768 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2769 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
2770#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002771 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2772 "<params..> = Sent unprocessed command" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002773#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002774 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002775 cli_cmd_flag_none,
2776 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002777#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002778 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002779};
2780
2781
2782/*
2783 * Prints command usage, lines are padded with the specified string.
2784 */
2785static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2786{
2787 char c;
2788 size_t n;
2789
2790 printf("%s%s ", pad, cmd->cmd);
2791 for (n = 0; (c = cmd->usage[n]); n++) {
2792 printf("%c", c);
2793 if (c == '\n')
2794 printf("%s", pad);
2795 }
2796 printf("\n");
2797}
2798
2799
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002800static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002801{
2802 int n;
2803 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002804 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2805 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2806 print_cmd_help(&wpa_cli_commands[n], " ");
2807 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002808}
2809
2810
2811static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2812{
2813 const char *c, *delim;
2814 int n;
2815 size_t len;
2816
2817 delim = os_strchr(cmd, ' ');
2818 if (delim)
2819 len = delim - cmd;
2820 else
2821 len = os_strlen(cmd);
2822
2823 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2824 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2825 return (wpa_cli_commands[n].flags &
2826 cli_cmd_flag_sensitive);
2827 }
2828 return 0;
2829}
2830
2831
2832static char ** wpa_list_cmd_list(void)
2833{
2834 char **res;
2835 int i, count;
2836
2837 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002838 res = os_calloc(count, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002839 if (res == NULL)
2840 return NULL;
2841
2842 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2843 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2844 if (res[i] == NULL)
2845 break;
2846 }
2847
2848 return res;
2849}
2850
2851
2852static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2853 int pos)
2854{
2855 int i;
2856
2857 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2858 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002859 if (wpa_cli_commands[i].completion)
2860 return wpa_cli_commands[i].completion(str,
2861 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002862 edit_clear_line();
2863 printf("\r%s\n", wpa_cli_commands[i].usage);
2864 edit_redraw();
2865 break;
2866 }
2867 }
2868
2869 return NULL;
2870}
2871
2872
2873static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2874{
2875 char **res;
2876 const char *end;
2877 char *cmd;
2878
2879 end = os_strchr(str, ' ');
2880 if (end == NULL || str + pos < end)
2881 return wpa_list_cmd_list();
2882
2883 cmd = os_malloc(pos + 1);
2884 if (cmd == NULL)
2885 return NULL;
2886 os_memcpy(cmd, str, pos);
2887 cmd[end - str] = '\0';
2888 res = wpa_cli_cmd_completion(cmd, str, pos);
2889 os_free(cmd);
2890 return res;
2891}
2892
2893
2894static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2895{
2896 struct wpa_cli_cmd *cmd, *match = NULL;
2897 int count;
2898 int ret = 0;
2899
2900 count = 0;
2901 cmd = wpa_cli_commands;
2902 while (cmd->cmd) {
2903 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2904 {
2905 match = cmd;
2906 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2907 /* we have an exact match */
2908 count = 1;
2909 break;
2910 }
2911 count++;
2912 }
2913 cmd++;
2914 }
2915
2916 if (count > 1) {
2917 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2918 cmd = wpa_cli_commands;
2919 while (cmd->cmd) {
2920 if (os_strncasecmp(cmd->cmd, argv[0],
2921 os_strlen(argv[0])) == 0) {
2922 printf(" %s", cmd->cmd);
2923 }
2924 cmd++;
2925 }
2926 printf("\n");
2927 ret = 1;
2928 } else if (count == 0) {
2929 printf("Unknown command '%s'\n", argv[0]);
2930 ret = 1;
2931 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07002932#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
2933 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
2934 redirect_interface = os_strdup(argv[1]);
2935 ret = match->handler(ctrl, argc - 2, &argv[2]);
2936 }
2937 else
2938#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002939 ret = match->handler(ctrl, argc - 1, &argv[1]);
2940 }
2941
2942 return ret;
2943}
2944
2945
2946static int str_match(const char *a, const char *b)
2947{
2948 return os_strncmp(a, b, os_strlen(b)) == 0;
2949}
2950
2951
2952static int wpa_cli_exec(const char *program, const char *arg1,
2953 const char *arg2)
2954{
2955 char *cmd;
2956 size_t len;
2957 int res;
2958 int ret = 0;
2959
2960 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2961 cmd = os_malloc(len);
2962 if (cmd == NULL)
2963 return -1;
2964 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2965 if (res < 0 || (size_t) res >= len) {
2966 os_free(cmd);
2967 return -1;
2968 }
2969 cmd[len - 1] = '\0';
2970#ifndef _WIN32_WCE
2971 if (system(cmd) < 0)
2972 ret = -1;
2973#endif /* _WIN32_WCE */
2974 os_free(cmd);
2975
2976 return ret;
2977}
2978
2979
2980static void wpa_cli_action_process(const char *msg)
2981{
2982 const char *pos;
2983 char *copy = NULL, *id, *pos2;
2984
2985 pos = msg;
2986 if (*pos == '<') {
2987 /* skip priority */
2988 pos = os_strchr(pos, '>');
2989 if (pos)
2990 pos++;
2991 else
2992 pos = msg;
2993 }
2994
2995 if (str_match(pos, WPA_EVENT_CONNECTED)) {
2996 int new_id = -1;
2997 os_unsetenv("WPA_ID");
2998 os_unsetenv("WPA_ID_STR");
2999 os_unsetenv("WPA_CTRL_DIR");
3000
3001 pos = os_strstr(pos, "[id=");
3002 if (pos)
3003 copy = os_strdup(pos + 4);
3004
3005 if (copy) {
3006 pos2 = id = copy;
3007 while (*pos2 && *pos2 != ' ')
3008 pos2++;
3009 *pos2++ = '\0';
3010 new_id = atoi(id);
3011 os_setenv("WPA_ID", id, 1);
3012 while (*pos2 && *pos2 != '=')
3013 pos2++;
3014 if (*pos2 == '=')
3015 pos2++;
3016 id = pos2;
3017 while (*pos2 && *pos2 != ']')
3018 pos2++;
3019 *pos2 = '\0';
3020 os_setenv("WPA_ID_STR", id, 1);
3021 os_free(copy);
3022 }
3023
3024 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3025
3026 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3027 wpa_cli_connected = 1;
3028 wpa_cli_last_id = new_id;
3029 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3030 }
3031 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3032 if (wpa_cli_connected) {
3033 wpa_cli_connected = 0;
3034 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3035 }
3036 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3037 wpa_cli_exec(action_file, ctrl_ifname, pos);
3038 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3039 wpa_cli_exec(action_file, ctrl_ifname, pos);
3040 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3041 wpa_cli_exec(action_file, ctrl_ifname, pos);
3042 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3043 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003044 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3045 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003046 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3047 wpa_cli_exec(action_file, ctrl_ifname, pos);
3048 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3049 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003050 } else if (str_match(pos, AP_STA_CONNECTED)) {
3051 wpa_cli_exec(action_file, ctrl_ifname, pos);
3052 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3053 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003054 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3055 printf("wpa_supplicant is terminating - stop monitoring\n");
3056 wpa_cli_quit = 1;
3057 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003058}
3059
3060
3061#ifndef CONFIG_ANSI_C_EXTRA
3062static void wpa_cli_action_cb(char *msg, size_t len)
3063{
3064 wpa_cli_action_process(msg);
3065}
3066#endif /* CONFIG_ANSI_C_EXTRA */
3067
3068
3069static void wpa_cli_reconnect(void)
3070{
3071 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003072 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3073 return;
3074
3075 if (interactive) {
3076 edit_clear_line();
3077 printf("\rConnection to wpa_supplicant re-established\n");
3078 edit_redraw();
3079 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003080}
3081
3082
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003083static void cli_event(const char *str)
3084{
3085 const char *start, *s;
3086
3087 start = os_strchr(str, '>');
3088 if (start == NULL)
3089 return;
3090
3091 start++;
3092
3093 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3094 s = os_strchr(start, ' ');
3095 if (s == NULL)
3096 return;
3097 s = os_strchr(s + 1, ' ');
3098 if (s == NULL)
3099 return;
3100 cli_txt_list_add(&bsses, s + 1);
3101 return;
3102 }
3103
3104 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3105 s = os_strchr(start, ' ');
3106 if (s == NULL)
3107 return;
3108 s = os_strchr(s + 1, ' ');
3109 if (s == NULL)
3110 return;
3111 cli_txt_list_del_addr(&bsses, s + 1);
3112 return;
3113 }
3114
3115#ifdef CONFIG_P2P
3116 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3117 s = os_strstr(start, " p2p_dev_addr=");
3118 if (s == NULL)
3119 return;
3120 cli_txt_list_add_addr(&p2p_peers, s + 14);
3121 return;
3122 }
3123
3124 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3125 s = os_strstr(start, " p2p_dev_addr=");
3126 if (s == NULL)
3127 return;
3128 cli_txt_list_del_addr(&p2p_peers, s + 14);
3129 return;
3130 }
3131
3132 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3133 s = os_strchr(start, ' ');
3134 if (s == NULL)
3135 return;
3136 cli_txt_list_add_word(&p2p_groups, s + 1);
3137 return;
3138 }
3139
3140 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3141 s = os_strchr(start, ' ');
3142 if (s == NULL)
3143 return;
3144 cli_txt_list_del_word(&p2p_groups, s + 1);
3145 return;
3146 }
3147#endif /* CONFIG_P2P */
3148}
3149
3150
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003151static int check_terminating(const char *msg)
3152{
3153 const char *pos = msg;
3154
3155 if (*pos == '<') {
3156 /* skip priority */
3157 pos = os_strchr(pos, '>');
3158 if (pos)
3159 pos++;
3160 else
3161 pos = msg;
3162 }
3163
3164 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3165 edit_clear_line();
3166 printf("\rConnection to wpa_supplicant lost - trying to "
3167 "reconnect\n");
3168 edit_redraw();
3169 wpa_cli_attached = 0;
3170 wpa_cli_close_connection();
3171 return 1;
3172 }
3173
3174 return 0;
3175}
3176
3177
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003178static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3179{
3180 if (ctrl_conn == NULL) {
3181 wpa_cli_reconnect();
3182 return;
3183 }
3184 while (wpa_ctrl_pending(ctrl) > 0) {
3185 char buf[256];
3186 size_t len = sizeof(buf) - 1;
3187 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3188 buf[len] = '\0';
3189 if (action_monitor)
3190 wpa_cli_action_process(buf);
3191 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003192 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003193 if (wpa_cli_show_event(buf)) {
3194 edit_clear_line();
3195 printf("\r%s\n", buf);
3196 edit_redraw();
3197 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003198
3199 if (interactive && check_terminating(buf) > 0)
3200 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003201 }
3202 } else {
3203 printf("Could not read pending message.\n");
3204 break;
3205 }
3206 }
3207
3208 if (wpa_ctrl_pending(ctrl) < 0) {
3209 printf("Connection to wpa_supplicant lost - trying to "
3210 "reconnect\n");
3211 wpa_cli_reconnect();
3212 }
3213}
3214
3215#define max_args 10
3216
3217static int tokenize_cmd(char *cmd, char *argv[])
3218{
3219 char *pos;
3220 int argc = 0;
3221
3222 pos = cmd;
3223 for (;;) {
3224 while (*pos == ' ')
3225 pos++;
3226 if (*pos == '\0')
3227 break;
3228 argv[argc] = pos;
3229 argc++;
3230 if (argc == max_args)
3231 break;
3232 if (*pos == '"') {
3233 char *pos2 = os_strrchr(pos, '"');
3234 if (pos2)
3235 pos = pos2 + 1;
3236 }
3237 while (*pos != '\0' && *pos != ' ')
3238 pos++;
3239 if (*pos == ' ')
3240 *pos++ = '\0';
3241 }
3242
3243 return argc;
3244}
3245
3246
3247static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3248{
3249 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3250 printf("Connection to wpa_supplicant lost - trying to "
3251 "reconnect\n");
3252 wpa_cli_close_connection();
3253 }
3254 if (!ctrl_conn)
3255 wpa_cli_reconnect();
3256 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3257}
3258
3259
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003260static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3261{
3262 wpa_cli_recv_pending(mon_conn, 0);
3263}
3264
3265
3266static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3267{
3268 char *argv[max_args];
3269 int argc;
3270 argc = tokenize_cmd(cmd, argv);
3271 if (argc)
3272 wpa_request(ctrl_conn, argc, argv);
3273}
3274
3275
3276static void wpa_cli_edit_eof_cb(void *ctx)
3277{
3278 eloop_terminate();
3279}
3280
3281
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003282static int warning_displayed = 0;
3283static char *hfile = NULL;
3284static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003285
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003286static void start_edit(void)
3287{
3288 char *home;
3289 char *ps = NULL;
3290
3291#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3292 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3293#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003294
3295 home = getenv("HOME");
3296 if (home) {
3297 const char *fname = ".wpa_cli_history";
3298 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3299 hfile = os_malloc(hfile_len);
3300 if (hfile)
3301 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3302 }
3303
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003304 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3305 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3306 eloop_terminate();
3307 return;
3308 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003309
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003310 edit_started = 1;
3311 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3312}
3313
3314
3315static void try_connection(void *eloop_ctx, void *timeout_ctx)
3316{
3317 if (ctrl_ifname == NULL)
3318 ctrl_ifname = wpa_cli_get_default_ifname();
3319
3320 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3321 if (!warning_displayed) {
3322 printf("Could not connect to wpa_supplicant: "
3323 "%s - re-trying\n", ctrl_ifname);
3324 warning_displayed = 1;
3325 }
3326 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3327 return;
3328 }
3329
3330 if (warning_displayed)
3331 printf("Connection established.\n");
3332
3333 start_edit();
3334}
3335
3336
3337static void wpa_cli_interactive(void)
3338{
3339 printf("\nInteractive mode\n\n");
3340
3341 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003342 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003343 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003344
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003345 cli_txt_list_flush(&p2p_peers);
3346 cli_txt_list_flush(&p2p_groups);
3347 cli_txt_list_flush(&bsses);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003348 if (edit_started)
3349 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003350 os_free(hfile);
3351 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3352 wpa_cli_close_connection();
3353}
3354
3355
3356static void wpa_cli_action(struct wpa_ctrl *ctrl)
3357{
3358#ifdef CONFIG_ANSI_C_EXTRA
3359 /* TODO: ANSI C version(?) */
3360 printf("Action processing not supported in ANSI C build.\n");
3361#else /* CONFIG_ANSI_C_EXTRA */
3362 fd_set rfds;
3363 int fd, res;
3364 struct timeval tv;
3365 char buf[256]; /* note: large enough to fit in unsolicited messages */
3366 size_t len;
3367
3368 fd = wpa_ctrl_get_fd(ctrl);
3369
3370 while (!wpa_cli_quit) {
3371 FD_ZERO(&rfds);
3372 FD_SET(fd, &rfds);
3373 tv.tv_sec = ping_interval;
3374 tv.tv_usec = 0;
3375 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3376 if (res < 0 && errno != EINTR) {
3377 perror("select");
3378 break;
3379 }
3380
3381 if (FD_ISSET(fd, &rfds))
3382 wpa_cli_recv_pending(ctrl, 1);
3383 else {
3384 /* verify that connection is still working */
3385 len = sizeof(buf) - 1;
3386 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3387 wpa_cli_action_cb) < 0 ||
3388 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3389 printf("wpa_supplicant did not reply to PING "
3390 "command - exiting\n");
3391 break;
3392 }
3393 }
3394 }
3395#endif /* CONFIG_ANSI_C_EXTRA */
3396}
3397
3398
3399static void wpa_cli_cleanup(void)
3400{
3401 wpa_cli_close_connection();
3402 if (pid_file)
3403 os_daemonize_terminate(pid_file);
3404
3405 os_program_deinit();
3406}
3407
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003408
3409static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003410{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003411 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003412}
3413
3414
3415static char * wpa_cli_get_default_ifname(void)
3416{
3417 char *ifname = NULL;
3418
3419#ifdef CONFIG_CTRL_IFACE_UNIX
3420 struct dirent *dent;
3421 DIR *dir = opendir(ctrl_iface_dir);
3422 if (!dir) {
3423#ifdef ANDROID
3424 char ifprop[PROPERTY_VALUE_MAX];
3425 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3426 ifname = os_strdup(ifprop);
3427 printf("Using interface '%s'\n", ifname);
3428 return ifname;
3429 }
3430#endif /* ANDROID */
3431 return NULL;
3432 }
3433 while ((dent = readdir(dir))) {
3434#ifdef _DIRENT_HAVE_D_TYPE
3435 /*
3436 * Skip the file if it is not a socket. Also accept
3437 * DT_UNKNOWN (0) in case the C library or underlying
3438 * file system does not support d_type.
3439 */
3440 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3441 continue;
3442#endif /* _DIRENT_HAVE_D_TYPE */
3443 if (os_strcmp(dent->d_name, ".") == 0 ||
3444 os_strcmp(dent->d_name, "..") == 0)
3445 continue;
3446 printf("Selected interface '%s'\n", dent->d_name);
3447 ifname = os_strdup(dent->d_name);
3448 break;
3449 }
3450 closedir(dir);
3451#endif /* CONFIG_CTRL_IFACE_UNIX */
3452
3453#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003454 char buf[2048], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003455 size_t len;
3456 struct wpa_ctrl *ctrl;
3457 int ret;
3458
3459 ctrl = wpa_ctrl_open(NULL);
3460 if (ctrl == NULL)
3461 return NULL;
3462
3463 len = sizeof(buf) - 1;
3464 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3465 if (ret >= 0) {
3466 buf[len] = '\0';
3467 pos = os_strchr(buf, '\n');
3468 if (pos)
3469 *pos = '\0';
3470 ifname = os_strdup(buf);
3471 }
3472 wpa_ctrl_close(ctrl);
3473#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3474
3475 return ifname;
3476}
3477
3478
3479int main(int argc, char *argv[])
3480{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003481 int c;
3482 int daemonize = 0;
3483 int ret = 0;
3484 const char *global = NULL;
3485
3486 if (os_program_init())
3487 return -1;
3488
3489 for (;;) {
3490 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3491 if (c < 0)
3492 break;
3493 switch (c) {
3494 case 'a':
3495 action_file = optarg;
3496 break;
3497 case 'B':
3498 daemonize = 1;
3499 break;
3500 case 'g':
3501 global = optarg;
3502 break;
3503 case 'G':
3504 ping_interval = atoi(optarg);
3505 break;
3506 case 'h':
3507 usage();
3508 return 0;
3509 case 'v':
3510 printf("%s\n", wpa_cli_version);
3511 return 0;
3512 case 'i':
3513 os_free(ctrl_ifname);
3514 ctrl_ifname = os_strdup(optarg);
3515 break;
3516 case 'p':
3517 ctrl_iface_dir = optarg;
3518 break;
3519 case 'P':
3520 pid_file = optarg;
3521 break;
3522 default:
3523 usage();
3524 return -1;
3525 }
3526 }
3527
3528 interactive = (argc == optind) && (action_file == NULL);
3529
3530 if (interactive)
3531 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3532
3533 if (eloop_init())
3534 return -1;
3535
3536 if (global) {
3537#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3538 ctrl_conn = wpa_ctrl_open(NULL);
3539#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3540 ctrl_conn = wpa_ctrl_open(global);
3541#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3542 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003543 fprintf(stderr, "Failed to connect to wpa_supplicant "
3544 "global interface: %s error: %s\n",
3545 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003546 return -1;
3547 }
3548 }
3549
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003550 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003551
3552 if (ctrl_ifname == NULL)
3553 ctrl_ifname = wpa_cli_get_default_ifname();
3554
3555 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003556 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003557 } else {
3558 if (!global &&
3559 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003560 fprintf(stderr, "Failed to connect to non-global "
3561 "ctrl_ifname: %s error: %s\n",
3562 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003563 return -1;
3564 }
3565
3566 if (action_file) {
3567 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3568 wpa_cli_attached = 1;
3569 } else {
3570 printf("Warning: Failed to attach to "
3571 "wpa_supplicant.\n");
3572 return -1;
3573 }
3574 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003575
3576 if (daemonize && os_daemonize(pid_file))
3577 return -1;
3578
3579 if (action_file)
3580 wpa_cli_action(ctrl_conn);
3581 else
3582 ret = wpa_request(ctrl_conn, argc - optind,
3583 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003584 }
3585
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003586 os_free(ctrl_ifname);
3587 eloop_destroy();
3588 wpa_cli_cleanup();
3589
3590 return ret;
3591}
3592
3593#else /* CONFIG_CTRL_IFACE */
3594int main(int argc, char *argv[])
3595{
3596 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3597 return -1;
3598}
3599#endif /* CONFIG_CTRL_IFACE */