blob: cdbe011b343a19856be41849109f0ed9b6d295ec [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 Shmidt444d5672013-04-01 13:08:44 -07002326static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2327{
2328 return wpa_ctrl_command(ctrl, "FLUSH");
2329}
2330
2331
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002332enum wpa_cli_cmd_flags {
2333 cli_cmd_flag_none = 0x00,
2334 cli_cmd_flag_sensitive = 0x01
2335};
2336
2337struct wpa_cli_cmd {
2338 const char *cmd;
2339 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002340 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002341 enum wpa_cli_cmd_flags flags;
2342 const char *usage;
2343};
2344
2345static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002346 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002347 cli_cmd_flag_none,
2348 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002349 { "ifname", wpa_cli_cmd_ifname, NULL,
2350 cli_cmd_flag_none,
2351 "= get current interface name" },
2352 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002353 cli_cmd_flag_none,
2354 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002355 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002356 cli_cmd_flag_none,
2357 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002358 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002359 cli_cmd_flag_none,
2360 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002361 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002362 cli_cmd_flag_none,
2363 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002364 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002365 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002366 "[command] = show usage help" },
2367 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002368 cli_cmd_flag_none,
2369 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002370 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002371 cli_cmd_flag_none,
2372 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002373 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002374 cli_cmd_flag_none,
2375 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002376 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002377 cli_cmd_flag_none,
2378 "= exit wpa_cli" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002379 { "set", wpa_cli_cmd_set, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002380 cli_cmd_flag_none,
2381 "= set variables (shows list of variables when run without "
2382 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002383 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002384 cli_cmd_flag_none,
2385 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002386 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002387 cli_cmd_flag_none,
2388 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002389 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002390 cli_cmd_flag_none,
2391 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002392 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002393 cli_cmd_flag_none,
2394 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002395 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002396 cli_cmd_flag_none,
2397 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002398 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002399 cli_cmd_flag_none,
2400 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002401 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002402 cli_cmd_flag_none,
2403 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002404 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002405 cli_cmd_flag_sensitive,
2406 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002407 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002408 cli_cmd_flag_sensitive,
2409 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002410 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002411 cli_cmd_flag_sensitive,
2412 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002413 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002414 cli_cmd_flag_sensitive,
2415 "<network id> <password> = configure one-time-password for an SSID"
2416 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002417 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002418 cli_cmd_flag_sensitive,
2419 "<network id> <passphrase> = configure private key passphrase\n"
2420 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002421 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002422 cli_cmd_flag_none,
2423 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002424 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002425 cli_cmd_flag_none,
2426 "<BSSID> = add a BSSID to the blacklist\n"
2427 "blacklist clear = clear the blacklist\n"
2428 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002429 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002430 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002431 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002432 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002433 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002434 cli_cmd_flag_none,
2435 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002436 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002437 cli_cmd_flag_none,
2438 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002439 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002440 cli_cmd_flag_none,
2441 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002442 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002443 cli_cmd_flag_none,
2444 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002445 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002446 cli_cmd_flag_none,
2447 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002448 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002449 cli_cmd_flag_none,
2450 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002451 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002452 cli_cmd_flag_sensitive,
2453 "<network id> <variable> <value> = set network variables (shows\n"
2454 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002455 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002456 cli_cmd_flag_none,
2457 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002458 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002459 cli_cmd_flag_none,
2460 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002461 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002462 cli_cmd_flag_none,
2463 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002464 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002465 cli_cmd_flag_none,
2466 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002467 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002468 cli_cmd_flag_sensitive,
2469 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002470 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002471 cli_cmd_flag_none,
2472 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002473 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002474 cli_cmd_flag_none,
2475 "= disconnect and wait for reassociate/reconnect command before\n"
2476 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002477 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002478 cli_cmd_flag_none,
2479 "= like reassociate, but only takes effect if already disconnected"
2480 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002481 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002482 cli_cmd_flag_none,
2483 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002484 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002485 cli_cmd_flag_none,
2486 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002487 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002488 cli_cmd_flag_none,
2489 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002490 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002491 cli_cmd_flag_none,
Dmitry Shmidt700a1372013-03-15 14:14:44 -07002492 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002493 "= get capabilies" },
2494 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002495 cli_cmd_flag_none,
2496 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002497 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002498 cli_cmd_flag_none,
2499 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002500 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002501 cli_cmd_flag_none,
2502 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2503 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2504 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002505 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002506 cli_cmd_flag_none,
2507 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002508 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002509 cli_cmd_flag_none,
2510 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002511 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002512 cli_cmd_flag_none,
2513 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002514 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002515 cli_cmd_flag_none,
2516 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002517 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002518 cli_cmd_flag_none,
2519 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002520 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521 cli_cmd_flag_none,
2522 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002523 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002524 cli_cmd_flag_none,
2525 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002526 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002527 cli_cmd_flag_none,
2528 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002529 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002530 cli_cmd_flag_none,
2531 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002532 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002533 cli_cmd_flag_none,
2534 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002535 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002536 cli_cmd_flag_sensitive,
2537 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2538 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002539 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002540 cli_cmd_flag_sensitive,
2541 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002542 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002543 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002544#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002545 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002546 cli_cmd_flag_none,
2547 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002548 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2549 cli_cmd_flag_none,
2550 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002551 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002552 cli_cmd_flag_none,
2553 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002554 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002555 cli_cmd_flag_sensitive,
2556 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002557 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2558 cli_cmd_flag_none,
2559 "<NDEF> <WPS> = create NFC handover request" },
2560 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2561 cli_cmd_flag_none,
2562 "<NDEF> <WPS> = create NFC handover select" },
2563 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2564 cli_cmd_flag_none,
2565 "<hexdump of payload> = report received NFC handover request" },
2566 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2567 cli_cmd_flag_none,
2568 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002569 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2570 cli_cmd_flag_none,
2571 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2572 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002573#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002574 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002575 cli_cmd_flag_sensitive,
2576 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002577 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002578 cli_cmd_flag_sensitive,
2579 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002580 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002581 cli_cmd_flag_none,
2582 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002583 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002584 cli_cmd_flag_none,
2585 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002586 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002587 cli_cmd_flag_sensitive,
2588 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002589 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002590 cli_cmd_flag_none,
2591 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002592 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002593 cli_cmd_flag_sensitive,
2594 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002595 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002596 cli_cmd_flag_none,
2597 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002598 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002599 cli_cmd_flag_sensitive,
2600 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002601#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002602 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002603 cli_cmd_flag_none,
2604 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2605#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002606 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002607 cli_cmd_flag_none,
2608 "<addr> = request RSN authentication with <addr> in IBSS" },
2609#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002610 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002611 cli_cmd_flag_none,
2612 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002613 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002614 cli_cmd_flag_none,
2615 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002616 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002617 cli_cmd_flag_none,
2618 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002619 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002620 cli_cmd_flag_none,
2621 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002622#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002623 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002625 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002626 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002627 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002629 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002630 cli_cmd_flag_none,
2631 "<addr> = roam to the specified BSS" },
2632#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002633 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2634 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002635 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002636 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002637 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002638 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2639 cli_cmd_flag_none,
2640 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2641 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002642 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002643 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2644 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002646 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2647 "[ht40] = add a new P2P group (local end as GO)" },
2648 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2649 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002650 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002651 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652 cli_cmd_flag_none,
2653 "= get the passphrase for a group (GO only)" },
2654 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002655 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002656 "<addr> <TLVs> = schedule service discovery request" },
2657 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002658 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002659 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002660 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 cli_cmd_flag_none,
2662 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002663 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002664 cli_cmd_flag_none,
2665 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002666 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002667 cli_cmd_flag_none,
2668 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002669 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002670 cli_cmd_flag_none,
2671 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002672 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002673 cli_cmd_flag_none,
2674 "<bonjour|upnp> <query|version> <response|service> = add a local "
2675 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002676 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002677 cli_cmd_flag_none,
2678 "<bonjour|upnp> <query|version> [|service] = remove a local "
2679 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002680 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002681 cli_cmd_flag_none,
2682 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002683 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002684 cli_cmd_flag_none,
2685 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002686 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002687 "[discovered] = list known (optionally, only fully discovered) P2P "
2688 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002689 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2690 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002691 "<address> = show information about known P2P peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002692 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002694 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002695 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002696 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002697 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002698 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2699 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002700 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002701 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2702 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002703 "[<duration> <interval>] [<duration> <interval>] = request GO "
2704 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002705 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2706 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002707 "[<period> <interval>] = set extended listen timing" },
2708#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002709#ifdef CONFIG_WIFI_DISPLAY
2710 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2711 cli_cmd_flag_none,
2712 "<subelem> [contents] = set Wi-Fi Display subelement" },
2713 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2714 cli_cmd_flag_none,
2715 "<subelem> = get Wi-Fi Display subelement" },
2716#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002717#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002718 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002719 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002720 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2721 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002722 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002723 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002724 cli_cmd_flag_none,
2725 "[auto] = perform Interworking network selection" },
2726 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002727 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002728 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002729 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2730 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002731 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002732 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2733 cli_cmd_flag_none,
2734 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2735 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2736 wpa_cli_complete_bss, cli_cmd_flag_none,
2737 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002738#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002739#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002740 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2741 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002742 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2743 },
2744 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002745 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002746 "<addr> <home realm> = get HS20 nai home realm list" },
2747#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002748 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2749 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002750 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002751 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002752 cli_cmd_flag_none,
2753 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002754 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002755 cli_cmd_flag_none,
2756 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002757 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002758 cli_cmd_flag_none,
2759 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002760 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002761 cli_cmd_flag_none,
2762 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002763 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002764 cli_cmd_flag_none,
2765 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002766 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2767 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002768 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002769#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002770 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002771 "[params] = Set or unset (if none) autoscan parameters" },
2772#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002773#ifdef CONFIG_WNM
2774 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2775 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
2776#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002777 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2778 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002779 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2780 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002781#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002782 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002783 cli_cmd_flag_none,
2784 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002785#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002786 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002787};
2788
2789
2790/*
2791 * Prints command usage, lines are padded with the specified string.
2792 */
2793static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2794{
2795 char c;
2796 size_t n;
2797
2798 printf("%s%s ", pad, cmd->cmd);
2799 for (n = 0; (c = cmd->usage[n]); n++) {
2800 printf("%c", c);
2801 if (c == '\n')
2802 printf("%s", pad);
2803 }
2804 printf("\n");
2805}
2806
2807
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002808static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002809{
2810 int n;
2811 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002812 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2813 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2814 print_cmd_help(&wpa_cli_commands[n], " ");
2815 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002816}
2817
2818
2819static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2820{
2821 const char *c, *delim;
2822 int n;
2823 size_t len;
2824
2825 delim = os_strchr(cmd, ' ');
2826 if (delim)
2827 len = delim - cmd;
2828 else
2829 len = os_strlen(cmd);
2830
2831 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2832 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2833 return (wpa_cli_commands[n].flags &
2834 cli_cmd_flag_sensitive);
2835 }
2836 return 0;
2837}
2838
2839
2840static char ** wpa_list_cmd_list(void)
2841{
2842 char **res;
2843 int i, count;
2844
2845 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002846 res = os_calloc(count, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002847 if (res == NULL)
2848 return NULL;
2849
2850 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2851 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2852 if (res[i] == NULL)
2853 break;
2854 }
2855
2856 return res;
2857}
2858
2859
2860static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2861 int pos)
2862{
2863 int i;
2864
2865 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2866 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002867 if (wpa_cli_commands[i].completion)
2868 return wpa_cli_commands[i].completion(str,
2869 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002870 edit_clear_line();
2871 printf("\r%s\n", wpa_cli_commands[i].usage);
2872 edit_redraw();
2873 break;
2874 }
2875 }
2876
2877 return NULL;
2878}
2879
2880
2881static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2882{
2883 char **res;
2884 const char *end;
2885 char *cmd;
2886
2887 end = os_strchr(str, ' ');
2888 if (end == NULL || str + pos < end)
2889 return wpa_list_cmd_list();
2890
2891 cmd = os_malloc(pos + 1);
2892 if (cmd == NULL)
2893 return NULL;
2894 os_memcpy(cmd, str, pos);
2895 cmd[end - str] = '\0';
2896 res = wpa_cli_cmd_completion(cmd, str, pos);
2897 os_free(cmd);
2898 return res;
2899}
2900
2901
2902static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2903{
2904 struct wpa_cli_cmd *cmd, *match = NULL;
2905 int count;
2906 int ret = 0;
2907
2908 count = 0;
2909 cmd = wpa_cli_commands;
2910 while (cmd->cmd) {
2911 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2912 {
2913 match = cmd;
2914 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2915 /* we have an exact match */
2916 count = 1;
2917 break;
2918 }
2919 count++;
2920 }
2921 cmd++;
2922 }
2923
2924 if (count > 1) {
2925 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2926 cmd = wpa_cli_commands;
2927 while (cmd->cmd) {
2928 if (os_strncasecmp(cmd->cmd, argv[0],
2929 os_strlen(argv[0])) == 0) {
2930 printf(" %s", cmd->cmd);
2931 }
2932 cmd++;
2933 }
2934 printf("\n");
2935 ret = 1;
2936 } else if (count == 0) {
2937 printf("Unknown command '%s'\n", argv[0]);
2938 ret = 1;
2939 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07002940#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
2941 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
2942 redirect_interface = os_strdup(argv[1]);
2943 ret = match->handler(ctrl, argc - 2, &argv[2]);
2944 }
2945 else
2946#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002947 ret = match->handler(ctrl, argc - 1, &argv[1]);
2948 }
2949
2950 return ret;
2951}
2952
2953
2954static int str_match(const char *a, const char *b)
2955{
2956 return os_strncmp(a, b, os_strlen(b)) == 0;
2957}
2958
2959
2960static int wpa_cli_exec(const char *program, const char *arg1,
2961 const char *arg2)
2962{
2963 char *cmd;
2964 size_t len;
2965 int res;
2966 int ret = 0;
2967
2968 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2969 cmd = os_malloc(len);
2970 if (cmd == NULL)
2971 return -1;
2972 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2973 if (res < 0 || (size_t) res >= len) {
2974 os_free(cmd);
2975 return -1;
2976 }
2977 cmd[len - 1] = '\0';
2978#ifndef _WIN32_WCE
2979 if (system(cmd) < 0)
2980 ret = -1;
2981#endif /* _WIN32_WCE */
2982 os_free(cmd);
2983
2984 return ret;
2985}
2986
2987
2988static void wpa_cli_action_process(const char *msg)
2989{
2990 const char *pos;
2991 char *copy = NULL, *id, *pos2;
2992
2993 pos = msg;
2994 if (*pos == '<') {
2995 /* skip priority */
2996 pos = os_strchr(pos, '>');
2997 if (pos)
2998 pos++;
2999 else
3000 pos = msg;
3001 }
3002
3003 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3004 int new_id = -1;
3005 os_unsetenv("WPA_ID");
3006 os_unsetenv("WPA_ID_STR");
3007 os_unsetenv("WPA_CTRL_DIR");
3008
3009 pos = os_strstr(pos, "[id=");
3010 if (pos)
3011 copy = os_strdup(pos + 4);
3012
3013 if (copy) {
3014 pos2 = id = copy;
3015 while (*pos2 && *pos2 != ' ')
3016 pos2++;
3017 *pos2++ = '\0';
3018 new_id = atoi(id);
3019 os_setenv("WPA_ID", id, 1);
3020 while (*pos2 && *pos2 != '=')
3021 pos2++;
3022 if (*pos2 == '=')
3023 pos2++;
3024 id = pos2;
3025 while (*pos2 && *pos2 != ']')
3026 pos2++;
3027 *pos2 = '\0';
3028 os_setenv("WPA_ID_STR", id, 1);
3029 os_free(copy);
3030 }
3031
3032 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3033
3034 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3035 wpa_cli_connected = 1;
3036 wpa_cli_last_id = new_id;
3037 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3038 }
3039 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3040 if (wpa_cli_connected) {
3041 wpa_cli_connected = 0;
3042 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3043 }
3044 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3045 wpa_cli_exec(action_file, ctrl_ifname, pos);
3046 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3047 wpa_cli_exec(action_file, ctrl_ifname, pos);
3048 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3049 wpa_cli_exec(action_file, ctrl_ifname, pos);
3050 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3051 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003052 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3053 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003054 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3055 wpa_cli_exec(action_file, ctrl_ifname, pos);
3056 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3057 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003058 } else if (str_match(pos, AP_STA_CONNECTED)) {
3059 wpa_cli_exec(action_file, ctrl_ifname, pos);
3060 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3061 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003062 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3063 printf("wpa_supplicant is terminating - stop monitoring\n");
3064 wpa_cli_quit = 1;
3065 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003066}
3067
3068
3069#ifndef CONFIG_ANSI_C_EXTRA
3070static void wpa_cli_action_cb(char *msg, size_t len)
3071{
3072 wpa_cli_action_process(msg);
3073}
3074#endif /* CONFIG_ANSI_C_EXTRA */
3075
3076
3077static void wpa_cli_reconnect(void)
3078{
3079 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003080 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3081 return;
3082
3083 if (interactive) {
3084 edit_clear_line();
3085 printf("\rConnection to wpa_supplicant re-established\n");
3086 edit_redraw();
3087 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003088}
3089
3090
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003091static void cli_event(const char *str)
3092{
3093 const char *start, *s;
3094
3095 start = os_strchr(str, '>');
3096 if (start == NULL)
3097 return;
3098
3099 start++;
3100
3101 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3102 s = os_strchr(start, ' ');
3103 if (s == NULL)
3104 return;
3105 s = os_strchr(s + 1, ' ');
3106 if (s == NULL)
3107 return;
3108 cli_txt_list_add(&bsses, s + 1);
3109 return;
3110 }
3111
3112 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3113 s = os_strchr(start, ' ');
3114 if (s == NULL)
3115 return;
3116 s = os_strchr(s + 1, ' ');
3117 if (s == NULL)
3118 return;
3119 cli_txt_list_del_addr(&bsses, s + 1);
3120 return;
3121 }
3122
3123#ifdef CONFIG_P2P
3124 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3125 s = os_strstr(start, " p2p_dev_addr=");
3126 if (s == NULL)
3127 return;
3128 cli_txt_list_add_addr(&p2p_peers, s + 14);
3129 return;
3130 }
3131
3132 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3133 s = os_strstr(start, " p2p_dev_addr=");
3134 if (s == NULL)
3135 return;
3136 cli_txt_list_del_addr(&p2p_peers, s + 14);
3137 return;
3138 }
3139
3140 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3141 s = os_strchr(start, ' ');
3142 if (s == NULL)
3143 return;
3144 cli_txt_list_add_word(&p2p_groups, s + 1);
3145 return;
3146 }
3147
3148 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3149 s = os_strchr(start, ' ');
3150 if (s == NULL)
3151 return;
3152 cli_txt_list_del_word(&p2p_groups, s + 1);
3153 return;
3154 }
3155#endif /* CONFIG_P2P */
3156}
3157
3158
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003159static int check_terminating(const char *msg)
3160{
3161 const char *pos = msg;
3162
3163 if (*pos == '<') {
3164 /* skip priority */
3165 pos = os_strchr(pos, '>');
3166 if (pos)
3167 pos++;
3168 else
3169 pos = msg;
3170 }
3171
3172 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3173 edit_clear_line();
3174 printf("\rConnection to wpa_supplicant lost - trying to "
3175 "reconnect\n");
3176 edit_redraw();
3177 wpa_cli_attached = 0;
3178 wpa_cli_close_connection();
3179 return 1;
3180 }
3181
3182 return 0;
3183}
3184
3185
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003186static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3187{
3188 if (ctrl_conn == NULL) {
3189 wpa_cli_reconnect();
3190 return;
3191 }
3192 while (wpa_ctrl_pending(ctrl) > 0) {
3193 char buf[256];
3194 size_t len = sizeof(buf) - 1;
3195 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3196 buf[len] = '\0';
3197 if (action_monitor)
3198 wpa_cli_action_process(buf);
3199 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003200 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003201 if (wpa_cli_show_event(buf)) {
3202 edit_clear_line();
3203 printf("\r%s\n", buf);
3204 edit_redraw();
3205 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003206
3207 if (interactive && check_terminating(buf) > 0)
3208 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003209 }
3210 } else {
3211 printf("Could not read pending message.\n");
3212 break;
3213 }
3214 }
3215
3216 if (wpa_ctrl_pending(ctrl) < 0) {
3217 printf("Connection to wpa_supplicant lost - trying to "
3218 "reconnect\n");
3219 wpa_cli_reconnect();
3220 }
3221}
3222
3223#define max_args 10
3224
3225static int tokenize_cmd(char *cmd, char *argv[])
3226{
3227 char *pos;
3228 int argc = 0;
3229
3230 pos = cmd;
3231 for (;;) {
3232 while (*pos == ' ')
3233 pos++;
3234 if (*pos == '\0')
3235 break;
3236 argv[argc] = pos;
3237 argc++;
3238 if (argc == max_args)
3239 break;
3240 if (*pos == '"') {
3241 char *pos2 = os_strrchr(pos, '"');
3242 if (pos2)
3243 pos = pos2 + 1;
3244 }
3245 while (*pos != '\0' && *pos != ' ')
3246 pos++;
3247 if (*pos == ' ')
3248 *pos++ = '\0';
3249 }
3250
3251 return argc;
3252}
3253
3254
3255static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3256{
3257 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3258 printf("Connection to wpa_supplicant lost - trying to "
3259 "reconnect\n");
3260 wpa_cli_close_connection();
3261 }
3262 if (!ctrl_conn)
3263 wpa_cli_reconnect();
3264 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3265}
3266
3267
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003268static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3269{
3270 wpa_cli_recv_pending(mon_conn, 0);
3271}
3272
3273
3274static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3275{
3276 char *argv[max_args];
3277 int argc;
3278 argc = tokenize_cmd(cmd, argv);
3279 if (argc)
3280 wpa_request(ctrl_conn, argc, argv);
3281}
3282
3283
3284static void wpa_cli_edit_eof_cb(void *ctx)
3285{
3286 eloop_terminate();
3287}
3288
3289
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003290static int warning_displayed = 0;
3291static char *hfile = NULL;
3292static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003293
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003294static void start_edit(void)
3295{
3296 char *home;
3297 char *ps = NULL;
3298
3299#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3300 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3301#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003302
3303 home = getenv("HOME");
3304 if (home) {
3305 const char *fname = ".wpa_cli_history";
3306 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3307 hfile = os_malloc(hfile_len);
3308 if (hfile)
3309 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3310 }
3311
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003312 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3313 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3314 eloop_terminate();
3315 return;
3316 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003317
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003318 edit_started = 1;
3319 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3320}
3321
3322
3323static void try_connection(void *eloop_ctx, void *timeout_ctx)
3324{
3325 if (ctrl_ifname == NULL)
3326 ctrl_ifname = wpa_cli_get_default_ifname();
3327
3328 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3329 if (!warning_displayed) {
3330 printf("Could not connect to wpa_supplicant: "
3331 "%s - re-trying\n", ctrl_ifname);
3332 warning_displayed = 1;
3333 }
3334 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3335 return;
3336 }
3337
3338 if (warning_displayed)
3339 printf("Connection established.\n");
3340
3341 start_edit();
3342}
3343
3344
3345static void wpa_cli_interactive(void)
3346{
3347 printf("\nInteractive mode\n\n");
3348
3349 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003350 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003351 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003352
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003353 cli_txt_list_flush(&p2p_peers);
3354 cli_txt_list_flush(&p2p_groups);
3355 cli_txt_list_flush(&bsses);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003356 if (edit_started)
3357 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003358 os_free(hfile);
3359 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3360 wpa_cli_close_connection();
3361}
3362
3363
3364static void wpa_cli_action(struct wpa_ctrl *ctrl)
3365{
3366#ifdef CONFIG_ANSI_C_EXTRA
3367 /* TODO: ANSI C version(?) */
3368 printf("Action processing not supported in ANSI C build.\n");
3369#else /* CONFIG_ANSI_C_EXTRA */
3370 fd_set rfds;
3371 int fd, res;
3372 struct timeval tv;
3373 char buf[256]; /* note: large enough to fit in unsolicited messages */
3374 size_t len;
3375
3376 fd = wpa_ctrl_get_fd(ctrl);
3377
3378 while (!wpa_cli_quit) {
3379 FD_ZERO(&rfds);
3380 FD_SET(fd, &rfds);
3381 tv.tv_sec = ping_interval;
3382 tv.tv_usec = 0;
3383 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3384 if (res < 0 && errno != EINTR) {
3385 perror("select");
3386 break;
3387 }
3388
3389 if (FD_ISSET(fd, &rfds))
3390 wpa_cli_recv_pending(ctrl, 1);
3391 else {
3392 /* verify that connection is still working */
3393 len = sizeof(buf) - 1;
3394 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3395 wpa_cli_action_cb) < 0 ||
3396 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3397 printf("wpa_supplicant did not reply to PING "
3398 "command - exiting\n");
3399 break;
3400 }
3401 }
3402 }
3403#endif /* CONFIG_ANSI_C_EXTRA */
3404}
3405
3406
3407static void wpa_cli_cleanup(void)
3408{
3409 wpa_cli_close_connection();
3410 if (pid_file)
3411 os_daemonize_terminate(pid_file);
3412
3413 os_program_deinit();
3414}
3415
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003416
3417static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003418{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003419 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003420}
3421
3422
3423static char * wpa_cli_get_default_ifname(void)
3424{
3425 char *ifname = NULL;
3426
3427#ifdef CONFIG_CTRL_IFACE_UNIX
3428 struct dirent *dent;
3429 DIR *dir = opendir(ctrl_iface_dir);
3430 if (!dir) {
3431#ifdef ANDROID
3432 char ifprop[PROPERTY_VALUE_MAX];
3433 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3434 ifname = os_strdup(ifprop);
3435 printf("Using interface '%s'\n", ifname);
3436 return ifname;
3437 }
3438#endif /* ANDROID */
3439 return NULL;
3440 }
3441 while ((dent = readdir(dir))) {
3442#ifdef _DIRENT_HAVE_D_TYPE
3443 /*
3444 * Skip the file if it is not a socket. Also accept
3445 * DT_UNKNOWN (0) in case the C library or underlying
3446 * file system does not support d_type.
3447 */
3448 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3449 continue;
3450#endif /* _DIRENT_HAVE_D_TYPE */
3451 if (os_strcmp(dent->d_name, ".") == 0 ||
3452 os_strcmp(dent->d_name, "..") == 0)
3453 continue;
3454 printf("Selected interface '%s'\n", dent->d_name);
3455 ifname = os_strdup(dent->d_name);
3456 break;
3457 }
3458 closedir(dir);
3459#endif /* CONFIG_CTRL_IFACE_UNIX */
3460
3461#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003462 char buf[2048], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003463 size_t len;
3464 struct wpa_ctrl *ctrl;
3465 int ret;
3466
3467 ctrl = wpa_ctrl_open(NULL);
3468 if (ctrl == NULL)
3469 return NULL;
3470
3471 len = sizeof(buf) - 1;
3472 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3473 if (ret >= 0) {
3474 buf[len] = '\0';
3475 pos = os_strchr(buf, '\n');
3476 if (pos)
3477 *pos = '\0';
3478 ifname = os_strdup(buf);
3479 }
3480 wpa_ctrl_close(ctrl);
3481#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3482
3483 return ifname;
3484}
3485
3486
3487int main(int argc, char *argv[])
3488{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003489 int c;
3490 int daemonize = 0;
3491 int ret = 0;
3492 const char *global = NULL;
3493
3494 if (os_program_init())
3495 return -1;
3496
3497 for (;;) {
3498 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3499 if (c < 0)
3500 break;
3501 switch (c) {
3502 case 'a':
3503 action_file = optarg;
3504 break;
3505 case 'B':
3506 daemonize = 1;
3507 break;
3508 case 'g':
3509 global = optarg;
3510 break;
3511 case 'G':
3512 ping_interval = atoi(optarg);
3513 break;
3514 case 'h':
3515 usage();
3516 return 0;
3517 case 'v':
3518 printf("%s\n", wpa_cli_version);
3519 return 0;
3520 case 'i':
3521 os_free(ctrl_ifname);
3522 ctrl_ifname = os_strdup(optarg);
3523 break;
3524 case 'p':
3525 ctrl_iface_dir = optarg;
3526 break;
3527 case 'P':
3528 pid_file = optarg;
3529 break;
3530 default:
3531 usage();
3532 return -1;
3533 }
3534 }
3535
3536 interactive = (argc == optind) && (action_file == NULL);
3537
3538 if (interactive)
3539 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3540
3541 if (eloop_init())
3542 return -1;
3543
3544 if (global) {
3545#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3546 ctrl_conn = wpa_ctrl_open(NULL);
3547#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3548 ctrl_conn = wpa_ctrl_open(global);
3549#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3550 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003551 fprintf(stderr, "Failed to connect to wpa_supplicant "
3552 "global interface: %s error: %s\n",
3553 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003554 return -1;
3555 }
3556 }
3557
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003558 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003559
3560 if (ctrl_ifname == NULL)
3561 ctrl_ifname = wpa_cli_get_default_ifname();
3562
3563 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003564 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003565 } else {
3566 if (!global &&
3567 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003568 fprintf(stderr, "Failed to connect to non-global "
3569 "ctrl_ifname: %s error: %s\n",
3570 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003571 return -1;
3572 }
3573
3574 if (action_file) {
3575 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3576 wpa_cli_attached = 1;
3577 } else {
3578 printf("Warning: Failed to attach to "
3579 "wpa_supplicant.\n");
3580 return -1;
3581 }
3582 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003583
3584 if (daemonize && os_daemonize(pid_file))
3585 return -1;
3586
3587 if (action_file)
3588 wpa_cli_action(ctrl_conn);
3589 else
3590 ret = wpa_request(ctrl_conn, argc - optind,
3591 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003592 }
3593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003594 os_free(ctrl_ifname);
3595 eloop_destroy();
3596 wpa_cli_cleanup();
3597
3598 return ret;
3599}
3600
3601#else /* CONFIG_CTRL_IFACE */
3602int main(int argc, char *argv[])
3603{
3604 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3605 return -1;
3606}
3607#endif /* CONFIG_CTRL_IFACE */