blob: 6d8b1f543cfcf7904489066d7d5e5379e62db323 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
Dmitry Shmidt04949592012-07-19 12:16:46 -07003 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#ifdef CONFIG_CTRL_IFACE
12
13#ifdef CONFIG_CTRL_IFACE_UNIX
14#include <dirent.h>
15#endif /* CONFIG_CTRL_IFACE_UNIX */
16
17#include "common/wpa_ctrl.h"
18#include "utils/common.h"
19#include "utils/eloop.h"
20#include "utils/edit.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "utils/list.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "common/version.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070023#include "common/ieee802_11_defs.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070024#ifdef ANDROID
25#include <cutils/properties.h>
26#endif /* ANDROID */
27
28
29static const char *wpa_cli_version =
30"wpa_cli v" VERSION_STR "\n"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080031"Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032
33
34static const char *wpa_cli_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080035"This software may be distributed under the terms of the BSD license.\n"
36"See README for more details.\n";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037
38static const char *wpa_cli_full_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080039"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040"\n"
41"Redistribution and use in source and binary forms, with or without\n"
42"modification, are permitted provided that the following conditions are\n"
43"met:\n"
44"\n"
45"1. Redistributions of source code must retain the above copyright\n"
46" notice, this list of conditions and the following disclaimer.\n"
47"\n"
48"2. Redistributions in binary form must reproduce the above copyright\n"
49" notice, this list of conditions and the following disclaimer in the\n"
50" documentation and/or other materials provided with the distribution.\n"
51"\n"
52"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53" names of its contributors may be used to endorse or promote products\n"
54" derived from this software without specific prior written permission.\n"
55"\n"
56"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67"\n";
68
69static struct wpa_ctrl *ctrl_conn;
70static struct wpa_ctrl *mon_conn;
71static int wpa_cli_quit = 0;
72static int wpa_cli_attached = 0;
73static int wpa_cli_connected = 0;
74static int wpa_cli_last_id = 0;
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
82static int ping_interval = 5;
83static int interactive = 0;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -070084#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
85static char* redirect_interface = NULL;
86#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070087
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080088struct cli_txt_entry {
89 struct dl_list list;
90 char *txt;
91};
92
93static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
94static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
95static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
96
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070097
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070098static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070099static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700100static void wpa_cli_close_connection(void);
101static char * wpa_cli_get_default_ifname(void);
102static char ** wpa_list_cmd_list(void);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700103
104
105static void usage(void)
106{
107 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
108 "[-a<action file>] \\\n"
109 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
110 "[command..]\n"
111 " -h = help (show this usage text)\n"
112 " -v = shown version information\n"
113 " -a = run in daemon mode executing the action file based on "
114 "events from\n"
115 " wpa_supplicant\n"
116 " -B = run a daemon in the background\n"
117 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
118 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700119 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700120}
121
122
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800123static void cli_txt_list_free(struct cli_txt_entry *e)
124{
125 dl_list_del(&e->list);
126 os_free(e->txt);
127 os_free(e);
128}
129
130
131static void cli_txt_list_flush(struct dl_list *list)
132{
133 struct cli_txt_entry *e;
134 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
135 cli_txt_list_free(e);
136}
137
138
139static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
140 const char *txt)
141{
142 struct cli_txt_entry *e;
143 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
144 if (os_strcmp(e->txt, txt) == 0)
145 return e;
146 }
147 return NULL;
148}
149
150
151static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
152{
153 struct cli_txt_entry *e;
154 e = cli_txt_list_get(txt_list, txt);
155 if (e)
156 cli_txt_list_free(e);
157}
158
159
160static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
161{
162 u8 addr[ETH_ALEN];
163 char buf[18];
164 if (hwaddr_aton(txt, addr) < 0)
165 return;
166 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
167 cli_txt_list_del(txt_list, buf);
168}
169
170
171#ifdef CONFIG_P2P
172static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
173{
174 const char *end;
175 char *buf;
176 end = os_strchr(txt, ' ');
177 if (end == NULL)
178 end = txt + os_strlen(txt);
179 buf = os_malloc(end - txt + 1);
180 if (buf == NULL)
181 return;
182 os_memcpy(buf, txt, end - txt);
183 buf[end - txt] = '\0';
184 cli_txt_list_del(txt_list, buf);
185 os_free(buf);
186}
187#endif /* CONFIG_P2P */
188
189
190static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
191{
192 struct cli_txt_entry *e;
193 e = cli_txt_list_get(txt_list, txt);
194 if (e)
195 return 0;
196 e = os_zalloc(sizeof(*e));
197 if (e == NULL)
198 return -1;
199 e->txt = os_strdup(txt);
200 if (e->txt == NULL) {
201 os_free(e);
202 return -1;
203 }
204 dl_list_add(txt_list, &e->list);
205 return 0;
206}
207
208
209#ifdef CONFIG_P2P
210static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
211{
212 u8 addr[ETH_ALEN];
213 char buf[18];
214 if (hwaddr_aton(txt, addr) < 0)
215 return -1;
216 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
217 return cli_txt_list_add(txt_list, buf);
218}
219
220
221static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
222{
223 const char *end;
224 char *buf;
225 int ret;
226 end = os_strchr(txt, ' ');
227 if (end == NULL)
228 end = txt + os_strlen(txt);
229 buf = os_malloc(end - txt + 1);
230 if (buf == NULL)
231 return -1;
232 os_memcpy(buf, txt, end - txt);
233 buf[end - txt] = '\0';
234 ret = cli_txt_list_add(txt_list, buf);
235 os_free(buf);
236 return ret;
237}
238#endif /* CONFIG_P2P */
239
240
241static char ** cli_txt_list_array(struct dl_list *txt_list)
242{
243 unsigned int i, count = dl_list_len(txt_list);
244 char **res;
245 struct cli_txt_entry *e;
246
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700247 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800248 if (res == NULL)
249 return NULL;
250
251 i = 0;
252 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
253 res[i] = os_strdup(e->txt);
254 if (res[i] == NULL)
255 break;
256 i++;
257 }
258
259 return res;
260}
261
262
263static int get_cmd_arg_num(const char *str, int pos)
264{
265 int arg = 0, i;
266
267 for (i = 0; i <= pos; i++) {
268 if (str[i] != ' ') {
269 arg++;
270 while (i <= pos && str[i] != ' ')
271 i++;
272 }
273 }
274
275 if (arg > 0)
276 arg--;
277 return arg;
278}
279
280
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700281static int str_starts(const char *src, const char *match)
282{
283 return os_strncmp(src, match, os_strlen(match)) == 0;
284}
285
286
287static int wpa_cli_show_event(const char *event)
288{
289 const char *start;
290
291 start = os_strchr(event, '>');
292 if (start == NULL)
293 return 1;
294
295 start++;
296 /*
297 * Skip BSS added/removed events since they can be relatively frequent
298 * and are likely of not much use for an interactive user.
299 */
300 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
301 str_starts(start, WPA_EVENT_BSS_REMOVED))
302 return 0;
303
304 return 1;
305}
306
307
308static int wpa_cli_open_connection(const char *ifname, int attach)
309{
310#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
311 ctrl_conn = wpa_ctrl_open(ifname);
312 if (ctrl_conn == NULL)
313 return -1;
314
315 if (attach && interactive)
316 mon_conn = wpa_ctrl_open(ifname);
317 else
318 mon_conn = NULL;
319#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
320 char *cfile = NULL;
321 int flen, res;
322
323 if (ifname == NULL)
324 return -1;
325
326#ifdef ANDROID
327 if (access(ctrl_iface_dir, F_OK) < 0) {
328 cfile = os_strdup(ifname);
329 if (cfile == NULL)
330 return -1;
331 }
332#endif /* ANDROID */
333
334 if (cfile == NULL) {
335 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
336 cfile = os_malloc(flen);
337 if (cfile == NULL)
338 return -1;
339 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
340 ifname);
341 if (res < 0 || res >= flen) {
342 os_free(cfile);
343 return -1;
344 }
345 }
346
347 ctrl_conn = wpa_ctrl_open(cfile);
348 if (ctrl_conn == NULL) {
349 os_free(cfile);
350 return -1;
351 }
352
353 if (attach && interactive)
354 mon_conn = wpa_ctrl_open(cfile);
355 else
356 mon_conn = NULL;
357 os_free(cfile);
358#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
359
360 if (mon_conn) {
361 if (wpa_ctrl_attach(mon_conn) == 0) {
362 wpa_cli_attached = 1;
363 if (interactive)
364 eloop_register_read_sock(
365 wpa_ctrl_get_fd(mon_conn),
366 wpa_cli_mon_receive, NULL, NULL);
367 } else {
368 printf("Warning: Failed to attach to "
369 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700370 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700371 return -1;
372 }
373 }
374
375 return 0;
376}
377
378
379static void wpa_cli_close_connection(void)
380{
381 if (ctrl_conn == NULL)
382 return;
383
384 if (wpa_cli_attached) {
385 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
386 wpa_cli_attached = 0;
387 }
388 wpa_ctrl_close(ctrl_conn);
389 ctrl_conn = NULL;
390 if (mon_conn) {
391 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
392 wpa_ctrl_close(mon_conn);
393 mon_conn = NULL;
394 }
395}
396
397
398static void wpa_cli_msg_cb(char *msg, size_t len)
399{
400 printf("%s\n", msg);
401}
402
403
404static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
405{
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800406#ifdef ANDROID
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700407 char buf[4096];
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -0800408#else
409 char buf[2048];
410#endif
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -0700411#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
412 char _cmd[256];
413#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700414 size_t len;
415 int ret;
416
417 if (ctrl_conn == NULL) {
418 printf("Not connected to wpa_supplicant - command dropped.\n");
419 return -1;
420 }
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -0700421#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
422 if (redirect_interface) {
423 char *arg;
424 arg = os_strchr(cmd, ' ');
425 if (arg) {
426 *arg++ = '\0';
427 ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s %s", cmd, redirect_interface, arg);
428 }
429 else {
430 ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s", cmd, redirect_interface);
431 }
432 cmd = _cmd;
433 os_free(redirect_interface);
434 redirect_interface = NULL;
435 }
436#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700437 len = sizeof(buf) - 1;
438 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
439 wpa_cli_msg_cb);
440 if (ret == -2) {
441 printf("'%s' command timed out.\n", cmd);
442 return -2;
443 } else if (ret < 0) {
444 printf("'%s' command failed.\n", cmd);
445 return -1;
446 }
447 if (print) {
448 buf[len] = '\0';
449 printf("%s", buf);
450 if (interactive && len > 0 && buf[len - 1] != '\n')
451 printf("\n");
452 }
453 return 0;
454}
455
456
457static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
458{
459 return _wpa_ctrl_command(ctrl, cmd, 1);
460}
461
462
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700463static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
464 char *argv[])
465{
466 int i, res;
467 char *pos, *end;
468
469 pos = buf;
470 end = buf + buflen;
471
472 res = os_snprintf(pos, end - pos, "%s", cmd);
473 if (res < 0 || res >= end - pos)
474 goto fail;
475 pos += res;
476
477 for (i = 0; i < argc; i++) {
478 res = os_snprintf(pos, end - pos, " %s", argv[i]);
479 if (res < 0 || res >= end - pos)
480 goto fail;
481 pos += res;
482 }
483
484 buf[buflen - 1] = '\0';
485 return 0;
486
487fail:
488 printf("Too long command\n");
489 return -1;
490}
491
492
493static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
494 int argc, char *argv[])
495{
496 char buf[256];
497 if (argc < min_args) {
498 printf("Invalid %s command - at least %d argument%s "
499 "required.\n", cmd, min_args,
500 min_args > 1 ? "s are" : " is");
501 return -1;
502 }
503 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
504 return -1;
505 return wpa_ctrl_command(ctrl, buf);
506}
507
508
509static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
510{
511 return wpa_ctrl_command(ctrl, "IFNAME");
512}
513
514
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700515static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
516{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800517 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
518 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
519 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
520 return wpa_ctrl_command(ctrl, "STATUS-WPS");
521 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700522}
523
524
525static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
526{
527 return wpa_ctrl_command(ctrl, "PING");
528}
529
530
531static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
532{
533 return wpa_ctrl_command(ctrl, "RELOG");
534}
535
536
537static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
538{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700539 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700540}
541
542
543static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
544{
545 return wpa_ctrl_command(ctrl, "MIB");
546}
547
548
549static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
550{
551 return wpa_ctrl_command(ctrl, "PMKSA");
552}
553
554
555static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
556{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700557 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700558 return 0;
559}
560
561
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700562static char ** wpa_cli_complete_help(const char *str, int pos)
563{
564 int arg = get_cmd_arg_num(str, pos);
565 char **res = NULL;
566
567 switch (arg) {
568 case 1:
569 res = wpa_list_cmd_list();
570 break;
571 }
572
573 return res;
574}
575
576
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700577static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
578{
579 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
580 return 0;
581}
582
583
584static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
585{
586 wpa_cli_quit = 1;
587 if (interactive)
588 eloop_terminate();
589 return 0;
590}
591
592
593static void wpa_cli_show_variables(void)
594{
595 printf("set variables:\n"
596 " EAPOL::heldPeriod (EAPOL state machine held period, "
597 "in seconds)\n"
598 " EAPOL::authPeriod (EAPOL state machine authentication "
599 "period, in seconds)\n"
600 " EAPOL::startPeriod (EAPOL state machine start period, in "
601 "seconds)\n"
602 " EAPOL::maxStart (EAPOL state machine maximum start "
603 "attempts)\n");
604 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
605 "seconds)\n"
606 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
607 " threshold\n\tpercentage)\n"
608 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
609 "security\n\tassociation in seconds)\n");
610}
611
612
613static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
614{
615 char cmd[256];
616 int res;
617
618 if (argc == 0) {
619 wpa_cli_show_variables();
620 return 0;
621 }
622
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800623 if (argc != 1 && argc != 2) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700624 printf("Invalid SET command: needs two arguments (variable "
625 "name and value)\n");
626 return -1;
627 }
628
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800629 if (argc == 1)
630 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
631 else
632 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
633 argv[0], argv[1]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700634 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
635 printf("Too long SET command.\n");
636 return -1;
637 }
638 return wpa_ctrl_command(ctrl, cmd);
639}
640
641
642static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
643{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700644 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700645}
646
647
648static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
649{
650 return wpa_ctrl_command(ctrl, "LOGOFF");
651}
652
653
654static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
655{
656 return wpa_ctrl_command(ctrl, "LOGON");
657}
658
659
660static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
661 char *argv[])
662{
663 return wpa_ctrl_command(ctrl, "REASSOCIATE");
664}
665
666
667static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
668 char *argv[])
669{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700670 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700671}
672
673
674static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
675{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700676 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700677}
678
679
680static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
681 char *argv[])
682{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700683 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700684}
685
686
687static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
688 char *argv[])
689{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700690 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700691}
692
693
694static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
695 char *argv[])
696{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700697 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700698}
699
700
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700701static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
702{
703 char cmd[256];
704 int res;
705
706 if (argc < 1)
707 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
708 else
709 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
710 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
711 printf("Too long BSS_FLUSH command.\n");
712 return -1;
713 }
714 return wpa_ctrl_command(ctrl, cmd);
715}
716
717
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700718static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
719 char *argv[])
720{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700721 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700722}
723
724
725static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
726{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700727 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700728}
729
730
731static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
732{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700733 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700734}
735
736
737static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
738{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700739 if (argc == 0) {
740 printf("Invalid WPS_PIN command: need one or two arguments:\n"
741 "- BSSID: use 'any' to select any\n"
742 "- PIN: optional, used only with devices that have no "
743 "display\n");
744 return -1;
745 }
746
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700747 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700748}
749
750
751static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
752 char *argv[])
753{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700754 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700755}
756
757
758static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
759 char *argv[])
760{
761 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
762}
763
764
Dmitry Shmidt04949592012-07-19 12:16:46 -0700765#ifdef CONFIG_WPS_NFC
766
767static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
768{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700769 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700770}
771
772
773static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
774 char *argv[])
775{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700776 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700777}
778
779
780static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
781 char *argv[])
782{
783 int ret;
784 char *buf;
785 size_t buflen;
786
787 if (argc != 1) {
788 printf("Invalid 'wps_nfc_tag_read' command - one argument "
789 "is required.\n");
790 return -1;
791 }
792
793 buflen = 18 + os_strlen(argv[0]);
794 buf = os_malloc(buflen);
795 if (buf == NULL)
796 return -1;
797 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
798
799 ret = wpa_ctrl_command(ctrl, buf);
800 os_free(buf);
801
802 return ret;
803}
804
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800805
806static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
807 char *argv[])
808{
809 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
810}
811
812
813static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
814 char *argv[])
815{
816 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
817}
818
819
820static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
821 char *argv[])
822{
823 int ret;
824 char *buf;
825 size_t buflen;
826
827 if (argc != 1) {
828 printf("Invalid 'nfc_rx_handover_req' command - one argument "
829 "is required.\n");
830 return -1;
831 }
832
833 buflen = 21 + os_strlen(argv[0]);
834 buf = os_malloc(buflen);
835 if (buf == NULL)
836 return -1;
837 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
838
839 ret = wpa_ctrl_command(ctrl, buf);
840 os_free(buf);
841
842 return ret;
843}
844
845
846static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
847 char *argv[])
848{
849 int ret;
850 char *buf;
851 size_t buflen;
852
853 if (argc != 1) {
854 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
855 "is required.\n");
856 return -1;
857 }
858
859 buflen = 21 + os_strlen(argv[0]);
860 buf = os_malloc(buflen);
861 if (buf == NULL)
862 return -1;
863 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
864
865 ret = wpa_ctrl_command(ctrl, buf);
866 os_free(buf);
867
868 return ret;
869}
870
Dmitry Shmidt04949592012-07-19 12:16:46 -0700871#endif /* CONFIG_WPS_NFC */
872
873
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700874static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
875{
876 char cmd[256];
877 int res;
878
879 if (argc == 2)
880 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
881 argv[0], argv[1]);
882 else if (argc == 5 || argc == 6) {
883 char ssid_hex[2 * 32 + 1];
884 char key_hex[2 * 64 + 1];
885 int i;
886
887 ssid_hex[0] = '\0';
888 for (i = 0; i < 32; i++) {
889 if (argv[2][i] == '\0')
890 break;
891 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
892 }
893
894 key_hex[0] = '\0';
895 if (argc == 6) {
896 for (i = 0; i < 64; i++) {
897 if (argv[5][i] == '\0')
898 break;
899 os_snprintf(&key_hex[i * 2], 3, "%02x",
900 argv[5][i]);
901 }
902 }
903
904 res = os_snprintf(cmd, sizeof(cmd),
905 "WPS_REG %s %s %s %s %s %s",
906 argv[0], argv[1], ssid_hex, argv[3], argv[4],
907 key_hex);
908 } else {
909 printf("Invalid WPS_REG command: need two arguments:\n"
910 "- BSSID of the target AP\n"
911 "- AP PIN\n");
912 printf("Alternatively, six arguments can be used to "
913 "reconfigure the AP:\n"
914 "- BSSID of the target AP\n"
915 "- AP PIN\n"
916 "- new SSID\n"
917 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
918 "- new encr (NONE, WEP, TKIP, CCMP)\n"
919 "- new key\n");
920 return -1;
921 }
922
923 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
924 printf("Too long WPS_REG command.\n");
925 return -1;
926 }
927 return wpa_ctrl_command(ctrl, cmd);
928}
929
930
931static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
932 char *argv[])
933{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700934 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700935}
936
937
938static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
939 char *argv[])
940{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700941 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700942}
943
944
945static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
946 char *argv[])
947{
948 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
949
950}
951
952
953static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
954 char *argv[])
955{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700956 if (argc < 2) {
957 printf("Invalid WPS_ER_PIN command: need at least two "
958 "arguments:\n"
959 "- UUID: use 'any' to select any\n"
960 "- PIN: Enrollee PIN\n"
961 "optional: - Enrollee MAC address\n");
962 return -1;
963 }
964
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700965 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700966}
967
968
969static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
970 char *argv[])
971{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700972 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700973}
974
975
976static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
977 char *argv[])
978{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979 if (argc != 2) {
980 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
981 "- UUID: specify which AP to use\n"
982 "- PIN: AP PIN\n");
983 return -1;
984 }
985
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700986 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700987}
988
989
990static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
991 char *argv[])
992{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993 if (argc != 2) {
994 printf("Invalid WPS_ER_SET_CONFIG command: need two "
995 "arguments:\n"
996 "- UUID: specify which AP to use\n"
997 "- Network configuration id\n");
998 return -1;
999 }
1000
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001001 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002}
1003
1004
1005static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1006 char *argv[])
1007{
1008 char cmd[256];
1009 int res;
1010
1011 if (argc == 5 || argc == 6) {
1012 char ssid_hex[2 * 32 + 1];
1013 char key_hex[2 * 64 + 1];
1014 int i;
1015
1016 ssid_hex[0] = '\0';
1017 for (i = 0; i < 32; i++) {
1018 if (argv[2][i] == '\0')
1019 break;
1020 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1021 }
1022
1023 key_hex[0] = '\0';
1024 if (argc == 6) {
1025 for (i = 0; i < 64; i++) {
1026 if (argv[5][i] == '\0')
1027 break;
1028 os_snprintf(&key_hex[i * 2], 3, "%02x",
1029 argv[5][i]);
1030 }
1031 }
1032
1033 res = os_snprintf(cmd, sizeof(cmd),
1034 "WPS_ER_CONFIG %s %s %s %s %s %s",
1035 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1036 key_hex);
1037 } else {
1038 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1039 "- AP UUID\n"
1040 "- AP PIN\n"
1041 "- new SSID\n"
1042 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1043 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1044 "- new key\n");
1045 return -1;
1046 }
1047
1048 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1049 printf("Too long WPS_ER_CONFIG command.\n");
1050 return -1;
1051 }
1052 return wpa_ctrl_command(ctrl, cmd);
1053}
1054
1055
Dmitry Shmidt04949592012-07-19 12:16:46 -07001056#ifdef CONFIG_WPS_NFC
1057static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1058 char *argv[])
1059{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001060 if (argc != 2) {
1061 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1062 "arguments:\n"
1063 "- WPS/NDEF: token format\n"
1064 "- UUID: specify which AP to use\n");
1065 return -1;
1066 }
1067
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001068 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001069}
1070#endif /* CONFIG_WPS_NFC */
1071
1072
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001073static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1074{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001075 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001076}
1077
1078
1079static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1080{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001081 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001082}
1083
1084
1085static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1086{
1087 char cmd[256], *pos, *end;
1088 int i, ret;
1089
1090 if (argc < 2) {
1091 printf("Invalid IDENTITY command: needs two arguments "
1092 "(network id and identity)\n");
1093 return -1;
1094 }
1095
1096 end = cmd + sizeof(cmd);
1097 pos = cmd;
1098 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1099 argv[0], argv[1]);
1100 if (ret < 0 || ret >= end - pos) {
1101 printf("Too long IDENTITY command.\n");
1102 return -1;
1103 }
1104 pos += ret;
1105 for (i = 2; i < argc; i++) {
1106 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1107 if (ret < 0 || ret >= end - pos) {
1108 printf("Too long IDENTITY command.\n");
1109 return -1;
1110 }
1111 pos += ret;
1112 }
1113
1114 return wpa_ctrl_command(ctrl, cmd);
1115}
1116
1117
1118static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1119{
1120 char cmd[256], *pos, *end;
1121 int i, ret;
1122
1123 if (argc < 2) {
1124 printf("Invalid PASSWORD command: needs two arguments "
1125 "(network id and password)\n");
1126 return -1;
1127 }
1128
1129 end = cmd + sizeof(cmd);
1130 pos = cmd;
1131 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1132 argv[0], argv[1]);
1133 if (ret < 0 || ret >= end - pos) {
1134 printf("Too long PASSWORD command.\n");
1135 return -1;
1136 }
1137 pos += ret;
1138 for (i = 2; i < argc; i++) {
1139 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1140 if (ret < 0 || ret >= end - pos) {
1141 printf("Too long PASSWORD command.\n");
1142 return -1;
1143 }
1144 pos += ret;
1145 }
1146
1147 return wpa_ctrl_command(ctrl, cmd);
1148}
1149
1150
1151static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1152 char *argv[])
1153{
1154 char cmd[256], *pos, *end;
1155 int i, ret;
1156
1157 if (argc < 2) {
1158 printf("Invalid NEW_PASSWORD command: needs two arguments "
1159 "(network id and password)\n");
1160 return -1;
1161 }
1162
1163 end = cmd + sizeof(cmd);
1164 pos = cmd;
1165 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1166 argv[0], argv[1]);
1167 if (ret < 0 || ret >= end - pos) {
1168 printf("Too long NEW_PASSWORD command.\n");
1169 return -1;
1170 }
1171 pos += ret;
1172 for (i = 2; i < argc; i++) {
1173 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1174 if (ret < 0 || ret >= end - pos) {
1175 printf("Too long NEW_PASSWORD command.\n");
1176 return -1;
1177 }
1178 pos += ret;
1179 }
1180
1181 return wpa_ctrl_command(ctrl, cmd);
1182}
1183
1184
1185static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1186{
1187 char cmd[256], *pos, *end;
1188 int i, ret;
1189
1190 if (argc < 2) {
1191 printf("Invalid PIN command: needs two arguments "
1192 "(network id and pin)\n");
1193 return -1;
1194 }
1195
1196 end = cmd + sizeof(cmd);
1197 pos = cmd;
1198 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1199 argv[0], argv[1]);
1200 if (ret < 0 || ret >= end - pos) {
1201 printf("Too long PIN command.\n");
1202 return -1;
1203 }
1204 pos += ret;
1205 for (i = 2; i < argc; i++) {
1206 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1207 if (ret < 0 || ret >= end - pos) {
1208 printf("Too long PIN command.\n");
1209 return -1;
1210 }
1211 pos += ret;
1212 }
1213 return wpa_ctrl_command(ctrl, cmd);
1214}
1215
1216
1217static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1218{
1219 char cmd[256], *pos, *end;
1220 int i, ret;
1221
1222 if (argc < 2) {
1223 printf("Invalid OTP command: needs two arguments (network "
1224 "id and password)\n");
1225 return -1;
1226 }
1227
1228 end = cmd + sizeof(cmd);
1229 pos = cmd;
1230 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1231 argv[0], argv[1]);
1232 if (ret < 0 || ret >= end - pos) {
1233 printf("Too long OTP command.\n");
1234 return -1;
1235 }
1236 pos += ret;
1237 for (i = 2; i < argc; i++) {
1238 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1239 if (ret < 0 || ret >= end - pos) {
1240 printf("Too long OTP command.\n");
1241 return -1;
1242 }
1243 pos += ret;
1244 }
1245
1246 return wpa_ctrl_command(ctrl, cmd);
1247}
1248
1249
1250static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1251 char *argv[])
1252{
1253 char cmd[256], *pos, *end;
1254 int i, ret;
1255
1256 if (argc < 2) {
1257 printf("Invalid PASSPHRASE command: needs two arguments "
1258 "(network id and passphrase)\n");
1259 return -1;
1260 }
1261
1262 end = cmd + sizeof(cmd);
1263 pos = cmd;
1264 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1265 argv[0], argv[1]);
1266 if (ret < 0 || ret >= end - pos) {
1267 printf("Too long PASSPHRASE command.\n");
1268 return -1;
1269 }
1270 pos += ret;
1271 for (i = 2; i < argc; i++) {
1272 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1273 if (ret < 0 || ret >= end - pos) {
1274 printf("Too long PASSPHRASE command.\n");
1275 return -1;
1276 }
1277 pos += ret;
1278 }
1279
1280 return wpa_ctrl_command(ctrl, cmd);
1281}
1282
1283
1284static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1285{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001286 if (argc < 2) {
1287 printf("Invalid BSSID command: needs two arguments (network "
1288 "id and BSSID)\n");
1289 return -1;
1290 }
1291
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001292 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001293}
1294
1295
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001296static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1297{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001298 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001299}
1300
1301
1302static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1303{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001304 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001305}
1306
1307
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001308static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1309 char *argv[])
1310{
1311 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1312}
1313
1314
1315static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1316 char *argv[])
1317{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001318 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001319}
1320
1321
1322static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1323 char *argv[])
1324{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001325 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001326}
1327
1328
1329static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1330 char *argv[])
1331{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001332 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001333}
1334
1335
1336static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1337 char *argv[])
1338{
1339 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1340}
1341
1342
1343static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1344 char *argv[])
1345{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001346 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001347}
1348
1349
1350static void wpa_cli_show_network_variables(void)
1351{
1352 printf("set_network variables:\n"
1353 " ssid (network name, SSID)\n"
1354 " psk (WPA passphrase or pre-shared key)\n"
1355 " key_mgmt (key management protocol)\n"
1356 " identity (EAP identity)\n"
1357 " password (EAP password)\n"
1358 " ...\n"
1359 "\n"
1360 "Note: Values are entered in the same format as the "
1361 "configuration file is using,\n"
1362 "i.e., strings values need to be inside double quotation "
1363 "marks.\n"
1364 "For example: set_network 1 ssid \"network name\"\n"
1365 "\n"
1366 "Please see wpa_supplicant.conf documentation for full list "
1367 "of\navailable variables.\n");
1368}
1369
1370
1371static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1372 char *argv[])
1373{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001374 if (argc == 0) {
1375 wpa_cli_show_network_variables();
1376 return 0;
1377 }
1378
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001379 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001380 printf("Invalid SET_NETWORK command: needs three arguments\n"
1381 "(network id, variable name, and value)\n");
1382 return -1;
1383 }
1384
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001385 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001386}
1387
1388
1389static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1390 char *argv[])
1391{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392 if (argc == 0) {
1393 wpa_cli_show_network_variables();
1394 return 0;
1395 }
1396
1397 if (argc != 2) {
1398 printf("Invalid GET_NETWORK command: needs two arguments\n"
1399 "(network id and variable name)\n");
1400 return -1;
1401 }
1402
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001403 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001404}
1405
1406
Dmitry Shmidt04949592012-07-19 12:16:46 -07001407static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1408 char *argv[])
1409{
1410 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1411}
1412
1413
1414static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1415{
1416 return wpa_ctrl_command(ctrl, "ADD_CRED");
1417}
1418
1419
1420static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1421 char *argv[])
1422{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001423 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001424}
1425
1426
1427static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1428{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001429 if (argc != 3) {
1430 printf("Invalid SET_CRED command: needs three arguments\n"
1431 "(cred id, variable name, and value)\n");
1432 return -1;
1433 }
1434
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001435 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001436}
1437
1438
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001439static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1440 char *argv[])
1441{
1442 return wpa_ctrl_command(ctrl, "DISCONNECT");
1443}
1444
1445
1446static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1447 char *argv[])
1448{
1449 return wpa_ctrl_command(ctrl, "RECONNECT");
1450}
1451
1452
1453static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1454 char *argv[])
1455{
1456 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1457}
1458
1459
1460static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1461{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001462 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001463}
1464
1465
1466static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1467 char *argv[])
1468{
1469 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1470}
1471
1472
1473static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1474{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001475 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001476}
1477
1478
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001479static char ** wpa_cli_complete_bss(const char *str, int pos)
1480{
1481 int arg = get_cmd_arg_num(str, pos);
1482 char **res = NULL;
1483
1484 switch (arg) {
1485 case 1:
1486 res = cli_txt_list_array(&bsses);
1487 break;
1488 }
1489
1490 return res;
1491}
1492
1493
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001494static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1495 char *argv[])
1496{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001497 if (argc < 1 || argc > 2) {
1498 printf("Invalid GET_CAPABILITY command: need either one or "
1499 "two arguments\n");
1500 return -1;
1501 }
1502
1503 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1504 printf("Invalid GET_CAPABILITY command: second argument, "
1505 "if any, must be 'strict'\n");
1506 return -1;
1507 }
1508
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001509 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001510}
1511
1512
1513static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1514{
1515 printf("Available interfaces:\n");
1516 return wpa_ctrl_command(ctrl, "INTERFACES");
1517}
1518
1519
1520static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1521{
1522 if (argc < 1) {
1523 wpa_cli_list_interfaces(ctrl);
1524 return 0;
1525 }
1526
1527 wpa_cli_close_connection();
1528 os_free(ctrl_ifname);
1529 ctrl_ifname = os_strdup(argv[0]);
1530
1531 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1532 printf("Connected to interface '%s.\n", ctrl_ifname);
1533 } else {
1534 printf("Could not connect to interface '%s' - re-trying\n",
1535 ctrl_ifname);
1536 }
1537 return 0;
1538}
1539
1540
1541static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1542 char *argv[])
1543{
1544 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1545}
1546
1547
1548static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1549 char *argv[])
1550{
1551 return wpa_ctrl_command(ctrl, "TERMINATE");
1552}
1553
1554
1555static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1556 char *argv[])
1557{
1558 char cmd[256];
1559 int res;
1560
1561 if (argc < 1) {
1562 printf("Invalid INTERFACE_ADD command: needs at least one "
1563 "argument (interface name)\n"
1564 "All arguments: ifname confname driver ctrl_interface "
1565 "driver_param bridge_name\n");
1566 return -1;
1567 }
1568
1569 /*
1570 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1571 * <driver_param>TAB<bridge_name>
1572 */
1573 res = os_snprintf(cmd, sizeof(cmd),
1574 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1575 argv[0],
1576 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1577 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1578 argc > 5 ? argv[5] : "");
1579 if (res < 0 || (size_t) res >= sizeof(cmd))
1580 return -1;
1581 cmd[sizeof(cmd) - 1] = '\0';
1582 return wpa_ctrl_command(ctrl, cmd);
1583}
1584
1585
1586static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1587 char *argv[])
1588{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001589 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001590}
1591
1592
1593static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1594 char *argv[])
1595{
1596 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1597}
1598
1599
1600#ifdef CONFIG_AP
1601static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1602{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001603 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001604}
1605
1606
1607static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1608 char *addr, size_t addr_len)
1609{
1610 char buf[4096], *pos;
1611 size_t len;
1612 int ret;
1613
1614 if (ctrl_conn == NULL) {
1615 printf("Not connected to hostapd - command dropped.\n");
1616 return -1;
1617 }
1618 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001619 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001620 wpa_cli_msg_cb);
1621 if (ret == -2) {
1622 printf("'%s' command timed out.\n", cmd);
1623 return -2;
1624 } else if (ret < 0) {
1625 printf("'%s' command failed.\n", cmd);
1626 return -1;
1627 }
1628
1629 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001630 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001631 return -1;
1632 printf("%s", buf);
1633
1634 pos = buf;
1635 while (*pos != '\0' && *pos != '\n')
1636 pos++;
1637 *pos = '\0';
1638 os_strlcpy(addr, buf, addr_len);
1639 return 0;
1640}
1641
1642
1643static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1644{
1645 char addr[32], cmd[64];
1646
1647 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1648 return 0;
1649 do {
1650 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1651 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1652
1653 return -1;
1654}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001655
1656
1657static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1658 char *argv[])
1659{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001660 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001661}
1662
1663
1664static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1665 char *argv[])
1666{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001667 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001668}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001669#endif /* CONFIG_AP */
1670
1671
1672static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1673{
1674 return wpa_ctrl_command(ctrl, "SUSPEND");
1675}
1676
1677
1678static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1679{
1680 return wpa_ctrl_command(ctrl, "RESUME");
1681}
1682
1683
1684static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1685{
1686 return wpa_ctrl_command(ctrl, "DROP_SA");
1687}
1688
1689
1690static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1691{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001692 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001693}
1694
1695
1696#ifdef CONFIG_P2P
1697
1698static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1699{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001700 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1701}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001702
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001703
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001704static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1705{
1706 char **res = NULL;
1707 int arg = get_cmd_arg_num(str, pos);
1708
1709 res = os_calloc(6, sizeof(char *));
1710 if (res == NULL)
1711 return NULL;
1712 res[0] = os_strdup("type=social");
1713 if (res[0] == NULL) {
1714 os_free(res);
1715 return NULL;
1716 }
1717 res[1] = os_strdup("type=progressive");
1718 if (res[1] == NULL)
1719 return res;
1720 res[2] = os_strdup("delay=");
1721 if (res[2] == NULL)
1722 return res;
1723 res[3] = os_strdup("dev_id=");
1724 if (res[3] == NULL)
1725 return res;
1726 if (arg == 1)
1727 res[4] = os_strdup("[timeout]");
1728
1729 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001730}
1731
1732
1733static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1734 char *argv[])
1735{
1736 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1737}
1738
1739
1740static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1741 char *argv[])
1742{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001743 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001744}
1745
1746
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001747static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1748{
1749 int arg = get_cmd_arg_num(str, pos);
1750 char **res = NULL;
1751
1752 switch (arg) {
1753 case 1:
1754 res = cli_txt_list_array(&p2p_peers);
1755 break;
1756 }
1757
1758 return res;
1759}
1760
1761
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001762static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1763 char *argv[])
1764{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001765 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001766}
1767
1768
1769static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1770 char *argv[])
1771{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001772 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001773}
1774
1775
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001776static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1777{
1778 int arg = get_cmd_arg_num(str, pos);
1779 char **res = NULL;
1780
1781 switch (arg) {
1782 case 1:
1783 res = cli_txt_list_array(&p2p_groups);
1784 break;
1785 }
1786
1787 return res;
1788}
1789
1790
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001791static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1792 char *argv[])
1793{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001794 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001795}
1796
1797
1798static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1799 char *argv[])
1800{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001801 if (argc != 2 && argc != 3) {
1802 printf("Invalid P2P_PROV_DISC command: needs at least "
1803 "two arguments, address and config method\n"
1804 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001805 return -1;
1806 }
1807
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001808 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001809}
1810
1811
1812static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1813 char *argv[])
1814{
1815 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1816}
1817
1818
1819static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1820 char *argv[])
1821{
1822 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001823
1824 if (argc != 2 && argc != 4) {
1825 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1826 "arguments (address and TLVs) or four arguments "
1827 "(address, \"upnp\", version, search target "
1828 "(SSDP ST:)\n");
1829 return -1;
1830 }
1831
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001832 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001833 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834 return wpa_ctrl_command(ctrl, cmd);
1835}
1836
1837
1838static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1839 int argc, char *argv[])
1840{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001841 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001842}
1843
1844
1845static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1846 char *argv[])
1847{
1848 char cmd[4096];
1849 int res;
1850
1851 if (argc != 4) {
1852 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1853 "arguments (freq, address, dialog token, and TLVs)\n");
1854 return -1;
1855 }
1856
1857 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1858 argv[0], argv[1], argv[2], argv[3]);
1859 if (res < 0 || (size_t) res >= sizeof(cmd))
1860 return -1;
1861 cmd[sizeof(cmd) - 1] = '\0';
1862 return wpa_ctrl_command(ctrl, cmd);
1863}
1864
1865
1866static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1867 char *argv[])
1868{
1869 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1870}
1871
1872
1873static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1874 int argc, char *argv[])
1875{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001876 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001877}
1878
1879
1880static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1881 char *argv[])
1882{
1883 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1884}
1885
1886
1887static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1888 char *argv[])
1889{
1890 char cmd[4096];
1891 int res;
1892
1893 if (argc != 3 && argc != 4) {
1894 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1895 "arguments\n");
1896 return -1;
1897 }
1898
1899 if (argc == 4)
1900 res = os_snprintf(cmd, sizeof(cmd),
1901 "P2P_SERVICE_ADD %s %s %s %s",
1902 argv[0], argv[1], argv[2], argv[3]);
1903 else
1904 res = os_snprintf(cmd, sizeof(cmd),
1905 "P2P_SERVICE_ADD %s %s %s",
1906 argv[0], argv[1], argv[2]);
1907 if (res < 0 || (size_t) res >= sizeof(cmd))
1908 return -1;
1909 cmd[sizeof(cmd) - 1] = '\0';
1910 return wpa_ctrl_command(ctrl, cmd);
1911}
1912
1913
1914static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1915 char *argv[])
1916{
1917 char cmd[4096];
1918 int res;
1919
1920 if (argc != 2 && argc != 3) {
1921 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1922 "arguments\n");
1923 return -1;
1924 }
1925
1926 if (argc == 3)
1927 res = os_snprintf(cmd, sizeof(cmd),
1928 "P2P_SERVICE_DEL %s %s %s",
1929 argv[0], argv[1], argv[2]);
1930 else
1931 res = os_snprintf(cmd, sizeof(cmd),
1932 "P2P_SERVICE_DEL %s %s",
1933 argv[0], argv[1]);
1934 if (res < 0 || (size_t) res >= sizeof(cmd))
1935 return -1;
1936 cmd[sizeof(cmd) - 1] = '\0';
1937 return wpa_ctrl_command(ctrl, cmd);
1938}
1939
1940
1941static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1942 int argc, char *argv[])
1943{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001944 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001945}
1946
1947
1948static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1949 int argc, char *argv[])
1950{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001951 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001952}
1953
1954
1955static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1956{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001957 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001958}
1959
1960
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001961static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1962{
1963 int arg = get_cmd_arg_num(str, pos);
1964 char **res = NULL;
1965
1966 switch (arg) {
1967 case 1:
1968 res = cli_txt_list_array(&p2p_peers);
1969 break;
1970 }
1971
1972 return res;
1973}
1974
1975
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001976static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1977 char *addr, size_t addr_len,
1978 int discovered)
1979{
1980 char buf[4096], *pos;
1981 size_t len;
1982 int ret;
1983
1984 if (ctrl_conn == NULL)
1985 return -1;
1986 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001987 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001988 wpa_cli_msg_cb);
1989 if (ret == -2) {
1990 printf("'%s' command timed out.\n", cmd);
1991 return -2;
1992 } else if (ret < 0) {
1993 printf("'%s' command failed.\n", cmd);
1994 return -1;
1995 }
1996
1997 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001998 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001999 return -1;
2000
2001 pos = buf;
2002 while (*pos != '\0' && *pos != '\n')
2003 pos++;
2004 *pos++ = '\0';
2005 os_strlcpy(addr, buf, addr_len);
2006 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2007 printf("%s\n", addr);
2008 return 0;
2009}
2010
2011
2012static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2013{
2014 char addr[32], cmd[64];
2015 int discovered;
2016
2017 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2018
2019 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2020 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002021 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022 do {
2023 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2024 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2025 discovered) == 0);
2026
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002027 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002028}
2029
2030
2031static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2032{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002033 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002034}
2035
2036
2037static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2038{
2039 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2040}
2041
2042
2043static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2044 char *argv[])
2045{
2046 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2047}
2048
2049
2050static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2051 char *argv[])
2052{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002053 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002054}
2055
2056
2057static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2058 char *argv[])
2059{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002060 if (argc != 0 && argc != 2 && argc != 4) {
2061 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2062 "(preferred duration, interval; in microsecods).\n"
2063 "Optional second pair can be used to provide "
2064 "acceptable values.\n");
2065 return -1;
2066 }
2067
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002068 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002069}
2070
2071
2072static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2073 char *argv[])
2074{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002075 if (argc != 0 && argc != 2) {
2076 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2077 "(availability period, availability interval; in "
2078 "millisecods).\n"
2079 "Extended Listen Timing can be cancelled with this "
2080 "command when used without parameters.\n");
2081 return -1;
2082 }
2083
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002084 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2085}
2086
2087#endif /* CONFIG_P2P */
2088
2089#ifdef CONFIG_WIFI_DISPLAY
2090
2091static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2092 char *argv[])
2093{
2094 char cmd[100];
2095 int res;
2096
2097 if (argc != 1 && argc != 2) {
2098 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2099 "arguments (subelem, hexdump)\n");
2100 return -1;
2101 }
2102
2103 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2104 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002105 if (res < 0 || (size_t) res >= sizeof(cmd))
2106 return -1;
2107 cmd[sizeof(cmd) - 1] = '\0';
2108 return wpa_ctrl_command(ctrl, cmd);
2109}
2110
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002111
2112static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2113 char *argv[])
2114{
2115 char cmd[100];
2116 int res;
2117
2118 if (argc != 1) {
2119 printf("Invalid WFD_SUBELEM_GET command: needs one "
2120 "argument (subelem)\n");
2121 return -1;
2122 }
2123
2124 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2125 argv[0]);
2126 if (res < 0 || (size_t) res >= sizeof(cmd))
2127 return -1;
2128 cmd[sizeof(cmd) - 1] = '\0';
2129 return wpa_ctrl_command(ctrl, cmd);
2130}
2131#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002132
2133
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002134#ifdef CONFIG_INTERWORKING
2135static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2136 char *argv[])
2137{
2138 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2139}
2140
2141
2142static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2143 char *argv[])
2144{
2145 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2146}
2147
2148
2149static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2150 char *argv[])
2151{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002152 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002153}
2154
2155
2156static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2157 char *argv[])
2158{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002159 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002160}
2161
2162
2163static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2164{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002165 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2166}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002167
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002168
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002169static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2170 char *argv[])
2171{
2172 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2173}
2174
2175
2176static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2177 char *argv[])
2178{
2179 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002180}
2181#endif /* CONFIG_INTERWORKING */
2182
2183
Dmitry Shmidt04949592012-07-19 12:16:46 -07002184#ifdef CONFIG_HS20
2185
2186static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2187 char *argv[])
2188{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002189 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002190}
2191
2192
2193static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2194 char *argv[])
2195{
2196 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002197
2198 if (argc == 0) {
2199 printf("Command needs one or two arguments (dst mac addr and "
2200 "optional home realm)\n");
2201 return -1;
2202 }
2203
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002204 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2205 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002206 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002207
2208 return wpa_ctrl_command(ctrl, cmd);
2209}
2210
2211#endif /* CONFIG_HS20 */
2212
2213
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002214static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2215 char *argv[])
2216{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002217 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002218}
2219
2220
2221static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2222 char *argv[])
2223{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002224 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002225}
2226
2227
2228static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2229 char *argv[])
2230{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002231 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002232}
2233
2234
2235static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2236 char *argv[])
2237{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002238 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002239}
2240
2241
2242static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2243 char *argv[])
2244{
2245 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2246}
2247
2248
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002249static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2250 char *argv[])
2251{
2252 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2253}
2254
2255
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002256static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2257 char *argv[])
2258{
2259 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2260}
2261
Dmitry Shmidt04949592012-07-19 12:16:46 -07002262
2263#ifdef CONFIG_AUTOSCAN
2264
2265static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2266{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002267 if (argc == 0)
2268 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2269
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002270 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002271}
2272
2273#endif /* CONFIG_AUTOSCAN */
2274
2275
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002276#ifdef CONFIG_WNM
2277
2278static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2279{
2280 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2281}
2282
2283#endif /* CONFIG_WNM */
2284
2285
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002286static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2287{
2288 if (argc == 0)
2289 return -1;
2290 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2291}
2292
2293
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002294#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002295static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2296{
2297 char cmd[256];
2298 int i;
2299 int len;
2300
2301 if (argc < 1) {
2302 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2303 return -1;
2304 }
2305
2306 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2307 for (i=1; i < argc; i++)
2308 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2309 cmd[sizeof(cmd) - 1] = '\0';
2310 printf("%s: %s\n", __func__, cmd);
2311 return wpa_ctrl_command(ctrl, cmd);
2312}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002313#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002314
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002315
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002316enum wpa_cli_cmd_flags {
2317 cli_cmd_flag_none = 0x00,
2318 cli_cmd_flag_sensitive = 0x01
2319};
2320
2321struct wpa_cli_cmd {
2322 const char *cmd;
2323 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002324 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002325 enum wpa_cli_cmd_flags flags;
2326 const char *usage;
2327};
2328
2329static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002330 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002331 cli_cmd_flag_none,
2332 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002333 { "ifname", wpa_cli_cmd_ifname, NULL,
2334 cli_cmd_flag_none,
2335 "= get current interface name" },
2336 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002337 cli_cmd_flag_none,
2338 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002339 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002340 cli_cmd_flag_none,
2341 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002342 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002343 cli_cmd_flag_none,
2344 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002345 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002346 cli_cmd_flag_none,
2347 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002348 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002349 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002350 "[command] = show usage help" },
2351 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002352 cli_cmd_flag_none,
2353 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002354 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002355 cli_cmd_flag_none,
2356 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002357 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002358 cli_cmd_flag_none,
2359 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002360 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002361 cli_cmd_flag_none,
2362 "= exit wpa_cli" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002363 { "set", wpa_cli_cmd_set, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002364 cli_cmd_flag_none,
2365 "= set variables (shows list of variables when run without "
2366 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002367 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002368 cli_cmd_flag_none,
2369 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002370 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002371 cli_cmd_flag_none,
2372 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002373 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002374 cli_cmd_flag_none,
2375 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002376 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002377 cli_cmd_flag_none,
2378 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002379 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002380 cli_cmd_flag_none,
2381 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002382 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002383 cli_cmd_flag_none,
2384 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002385 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002386 cli_cmd_flag_none,
2387 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002388 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002389 cli_cmd_flag_sensitive,
2390 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002391 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002392 cli_cmd_flag_sensitive,
2393 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002394 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002395 cli_cmd_flag_sensitive,
2396 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002397 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002398 cli_cmd_flag_sensitive,
2399 "<network id> <password> = configure one-time-password for an SSID"
2400 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002401 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002402 cli_cmd_flag_sensitive,
2403 "<network id> <passphrase> = configure private key passphrase\n"
2404 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002405 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002406 cli_cmd_flag_none,
2407 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002408 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002409 cli_cmd_flag_none,
2410 "<BSSID> = add a BSSID to the blacklist\n"
2411 "blacklist clear = clear the blacklist\n"
2412 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002413 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002414 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002415 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002416 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002417 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002418 cli_cmd_flag_none,
2419 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002420 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002421 cli_cmd_flag_none,
2422 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002423 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002424 cli_cmd_flag_none,
2425 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002426 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002427 cli_cmd_flag_none,
2428 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002429 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002430 cli_cmd_flag_none,
2431 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002432 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 cli_cmd_flag_none,
2434 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002435 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002436 cli_cmd_flag_sensitive,
2437 "<network id> <variable> <value> = set network variables (shows\n"
2438 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002439 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002440 cli_cmd_flag_none,
2441 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002442 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002443 cli_cmd_flag_none,
2444 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002445 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002446 cli_cmd_flag_none,
2447 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002448 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002449 cli_cmd_flag_none,
2450 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002451 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002452 cli_cmd_flag_sensitive,
2453 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002454 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002455 cli_cmd_flag_none,
2456 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002457 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002458 cli_cmd_flag_none,
2459 "= disconnect and wait for reassociate/reconnect command before\n"
2460 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002461 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002462 cli_cmd_flag_none,
2463 "= like reassociate, but only takes effect if already disconnected"
2464 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002465 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002466 cli_cmd_flag_none,
2467 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002468 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002469 cli_cmd_flag_none,
2470 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002471 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002472 cli_cmd_flag_none,
2473 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002474 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002475 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002476 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels> "
2477 "= get capabilies" },
2478 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002479 cli_cmd_flag_none,
2480 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002481 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002482 cli_cmd_flag_none,
2483 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002484 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002485 cli_cmd_flag_none,
2486 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2487 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2488 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002489 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002490 cli_cmd_flag_none,
2491 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002492 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002493 cli_cmd_flag_none,
2494 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002495 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002496 cli_cmd_flag_none,
2497 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002498 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002499 cli_cmd_flag_none,
2500 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002501 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 cli_cmd_flag_none,
2503 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002504 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002505 cli_cmd_flag_none,
2506 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002507 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002508 cli_cmd_flag_none,
2509 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002510 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002511 cli_cmd_flag_none,
2512 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002513 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514 cli_cmd_flag_none,
2515 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002516 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 cli_cmd_flag_none,
2518 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002519 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002520 cli_cmd_flag_sensitive,
2521 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2522 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002523 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002524 cli_cmd_flag_sensitive,
2525 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002526 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002527 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002528#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002529 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002530 cli_cmd_flag_none,
2531 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002532 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002533 cli_cmd_flag_none,
2534 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002535 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002536 cli_cmd_flag_sensitive,
2537 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002538 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2539 cli_cmd_flag_none,
2540 "<NDEF> <WPS> = create NFC handover request" },
2541 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2542 cli_cmd_flag_none,
2543 "<NDEF> <WPS> = create NFC handover select" },
2544 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2545 cli_cmd_flag_none,
2546 "<hexdump of payload> = report received NFC handover request" },
2547 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2548 cli_cmd_flag_none,
2549 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002550#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002551 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002552 cli_cmd_flag_sensitive,
2553 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002554 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555 cli_cmd_flag_sensitive,
2556 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002557 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558 cli_cmd_flag_none,
2559 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002560 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561 cli_cmd_flag_none,
2562 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002563 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002564 cli_cmd_flag_sensitive,
2565 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002566 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002567 cli_cmd_flag_none,
2568 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002569 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002570 cli_cmd_flag_sensitive,
2571 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002572 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002573 cli_cmd_flag_none,
2574 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002575 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002576 cli_cmd_flag_sensitive,
2577 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002578#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002579 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002580 cli_cmd_flag_none,
2581 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2582#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002583 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002584 cli_cmd_flag_none,
2585 "<addr> = request RSN authentication with <addr> in IBSS" },
2586#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002587 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002588 cli_cmd_flag_none,
2589 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002590 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002591 cli_cmd_flag_none,
2592 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002593 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002594 cli_cmd_flag_none,
2595 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002596 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002597 cli_cmd_flag_none,
2598 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002599#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002600 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002601 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002602 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002604 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002605 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002606 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002607 cli_cmd_flag_none,
2608 "<addr> = roam to the specified BSS" },
2609#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002610 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2611 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002612 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002613 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002614 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002615 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2616 cli_cmd_flag_none,
2617 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2618 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002619 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002620 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2621 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002622 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002623 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2624 "[ht40] = add a new P2P group (local end as GO)" },
2625 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2626 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002627 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002628 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002629 cli_cmd_flag_none,
2630 "= get the passphrase for a group (GO only)" },
2631 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002632 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002633 "<addr> <TLVs> = schedule service discovery request" },
2634 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002635 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002636 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002637 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638 cli_cmd_flag_none,
2639 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002640 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002641 cli_cmd_flag_none,
2642 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002643 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002644 cli_cmd_flag_none,
2645 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002646 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002647 cli_cmd_flag_none,
2648 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002649 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002650 cli_cmd_flag_none,
2651 "<bonjour|upnp> <query|version> <response|service> = add a local "
2652 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002653 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002654 cli_cmd_flag_none,
2655 "<bonjour|upnp> <query|version> [|service] = remove a local "
2656 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002657 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002658 cli_cmd_flag_none,
2659 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002660 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661 cli_cmd_flag_none,
2662 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002663 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002664 "[discovered] = list known (optionally, only fully discovered) P2P "
2665 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002666 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2667 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002668 "<address> = show information about known P2P peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002669 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002670 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002671 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002672 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002673 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002674 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002675 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2676 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002677 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002678 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2679 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002680 "[<duration> <interval>] [<duration> <interval>] = request GO "
2681 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002682 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2683 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002684 "[<period> <interval>] = set extended listen timing" },
2685#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002686#ifdef CONFIG_WIFI_DISPLAY
2687 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2688 cli_cmd_flag_none,
2689 "<subelem> [contents] = set Wi-Fi Display subelement" },
2690 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2691 cli_cmd_flag_none,
2692 "<subelem> = get Wi-Fi Display subelement" },
2693#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002694#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002695 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002696 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002697 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2698 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002699 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002700 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002701 cli_cmd_flag_none,
2702 "[auto] = perform Interworking network selection" },
2703 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002704 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002705 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002706 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2707 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002708 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002709 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2710 cli_cmd_flag_none,
2711 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2712 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2713 wpa_cli_complete_bss, cli_cmd_flag_none,
2714 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002715#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002716#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002717 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2718 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002719 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2720 },
2721 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002722 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002723 "<addr> <home realm> = get HS20 nai home realm list" },
2724#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002725 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2726 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002727 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002728 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002729 cli_cmd_flag_none,
2730 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002731 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002732 cli_cmd_flag_none,
2733 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002734 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002735 cli_cmd_flag_none,
2736 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002737 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002738 cli_cmd_flag_none,
2739 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002740 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002741 cli_cmd_flag_none,
2742 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002743 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2744 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002745 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002746#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002747 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002748 "[params] = Set or unset (if none) autoscan parameters" },
2749#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002750#ifdef CONFIG_WNM
2751 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2752 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
2753#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002754 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2755 "<params..> = Sent unprocessed command" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002756#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002757 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002758 cli_cmd_flag_none,
2759 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002760#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002761 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002762};
2763
2764
2765/*
2766 * Prints command usage, lines are padded with the specified string.
2767 */
2768static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2769{
2770 char c;
2771 size_t n;
2772
2773 printf("%s%s ", pad, cmd->cmd);
2774 for (n = 0; (c = cmd->usage[n]); n++) {
2775 printf("%c", c);
2776 if (c == '\n')
2777 printf("%s", pad);
2778 }
2779 printf("\n");
2780}
2781
2782
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002783static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002784{
2785 int n;
2786 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002787 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2788 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2789 print_cmd_help(&wpa_cli_commands[n], " ");
2790 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002791}
2792
2793
2794static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2795{
2796 const char *c, *delim;
2797 int n;
2798 size_t len;
2799
2800 delim = os_strchr(cmd, ' ');
2801 if (delim)
2802 len = delim - cmd;
2803 else
2804 len = os_strlen(cmd);
2805
2806 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2807 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2808 return (wpa_cli_commands[n].flags &
2809 cli_cmd_flag_sensitive);
2810 }
2811 return 0;
2812}
2813
2814
2815static char ** wpa_list_cmd_list(void)
2816{
2817 char **res;
2818 int i, count;
2819
2820 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002821 res = os_calloc(count, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002822 if (res == NULL)
2823 return NULL;
2824
2825 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2826 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2827 if (res[i] == NULL)
2828 break;
2829 }
2830
2831 return res;
2832}
2833
2834
2835static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2836 int pos)
2837{
2838 int i;
2839
2840 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2841 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002842 if (wpa_cli_commands[i].completion)
2843 return wpa_cli_commands[i].completion(str,
2844 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002845 edit_clear_line();
2846 printf("\r%s\n", wpa_cli_commands[i].usage);
2847 edit_redraw();
2848 break;
2849 }
2850 }
2851
2852 return NULL;
2853}
2854
2855
2856static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2857{
2858 char **res;
2859 const char *end;
2860 char *cmd;
2861
2862 end = os_strchr(str, ' ');
2863 if (end == NULL || str + pos < end)
2864 return wpa_list_cmd_list();
2865
2866 cmd = os_malloc(pos + 1);
2867 if (cmd == NULL)
2868 return NULL;
2869 os_memcpy(cmd, str, pos);
2870 cmd[end - str] = '\0';
2871 res = wpa_cli_cmd_completion(cmd, str, pos);
2872 os_free(cmd);
2873 return res;
2874}
2875
2876
2877static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2878{
2879 struct wpa_cli_cmd *cmd, *match = NULL;
2880 int count;
2881 int ret = 0;
2882
2883 count = 0;
2884 cmd = wpa_cli_commands;
2885 while (cmd->cmd) {
2886 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2887 {
2888 match = cmd;
2889 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2890 /* we have an exact match */
2891 count = 1;
2892 break;
2893 }
2894 count++;
2895 }
2896 cmd++;
2897 }
2898
2899 if (count > 1) {
2900 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2901 cmd = wpa_cli_commands;
2902 while (cmd->cmd) {
2903 if (os_strncasecmp(cmd->cmd, argv[0],
2904 os_strlen(argv[0])) == 0) {
2905 printf(" %s", cmd->cmd);
2906 }
2907 cmd++;
2908 }
2909 printf("\n");
2910 ret = 1;
2911 } else if (count == 0) {
2912 printf("Unknown command '%s'\n", argv[0]);
2913 ret = 1;
2914 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07002915#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
2916 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
2917 redirect_interface = os_strdup(argv[1]);
2918 ret = match->handler(ctrl, argc - 2, &argv[2]);
2919 }
2920 else
2921#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002922 ret = match->handler(ctrl, argc - 1, &argv[1]);
2923 }
2924
2925 return ret;
2926}
2927
2928
2929static int str_match(const char *a, const char *b)
2930{
2931 return os_strncmp(a, b, os_strlen(b)) == 0;
2932}
2933
2934
2935static int wpa_cli_exec(const char *program, const char *arg1,
2936 const char *arg2)
2937{
2938 char *cmd;
2939 size_t len;
2940 int res;
2941 int ret = 0;
2942
2943 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2944 cmd = os_malloc(len);
2945 if (cmd == NULL)
2946 return -1;
2947 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2948 if (res < 0 || (size_t) res >= len) {
2949 os_free(cmd);
2950 return -1;
2951 }
2952 cmd[len - 1] = '\0';
2953#ifndef _WIN32_WCE
2954 if (system(cmd) < 0)
2955 ret = -1;
2956#endif /* _WIN32_WCE */
2957 os_free(cmd);
2958
2959 return ret;
2960}
2961
2962
2963static void wpa_cli_action_process(const char *msg)
2964{
2965 const char *pos;
2966 char *copy = NULL, *id, *pos2;
2967
2968 pos = msg;
2969 if (*pos == '<') {
2970 /* skip priority */
2971 pos = os_strchr(pos, '>');
2972 if (pos)
2973 pos++;
2974 else
2975 pos = msg;
2976 }
2977
2978 if (str_match(pos, WPA_EVENT_CONNECTED)) {
2979 int new_id = -1;
2980 os_unsetenv("WPA_ID");
2981 os_unsetenv("WPA_ID_STR");
2982 os_unsetenv("WPA_CTRL_DIR");
2983
2984 pos = os_strstr(pos, "[id=");
2985 if (pos)
2986 copy = os_strdup(pos + 4);
2987
2988 if (copy) {
2989 pos2 = id = copy;
2990 while (*pos2 && *pos2 != ' ')
2991 pos2++;
2992 *pos2++ = '\0';
2993 new_id = atoi(id);
2994 os_setenv("WPA_ID", id, 1);
2995 while (*pos2 && *pos2 != '=')
2996 pos2++;
2997 if (*pos2 == '=')
2998 pos2++;
2999 id = pos2;
3000 while (*pos2 && *pos2 != ']')
3001 pos2++;
3002 *pos2 = '\0';
3003 os_setenv("WPA_ID_STR", id, 1);
3004 os_free(copy);
3005 }
3006
3007 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3008
3009 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3010 wpa_cli_connected = 1;
3011 wpa_cli_last_id = new_id;
3012 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3013 }
3014 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3015 if (wpa_cli_connected) {
3016 wpa_cli_connected = 0;
3017 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3018 }
3019 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3020 wpa_cli_exec(action_file, ctrl_ifname, pos);
3021 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3022 wpa_cli_exec(action_file, ctrl_ifname, pos);
3023 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3024 wpa_cli_exec(action_file, ctrl_ifname, pos);
3025 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3026 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003027 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3028 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003029 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3030 wpa_cli_exec(action_file, ctrl_ifname, pos);
3031 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3032 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003033 } else if (str_match(pos, AP_STA_CONNECTED)) {
3034 wpa_cli_exec(action_file, ctrl_ifname, pos);
3035 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3036 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003037 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3038 printf("wpa_supplicant is terminating - stop monitoring\n");
3039 wpa_cli_quit = 1;
3040 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003041}
3042
3043
3044#ifndef CONFIG_ANSI_C_EXTRA
3045static void wpa_cli_action_cb(char *msg, size_t len)
3046{
3047 wpa_cli_action_process(msg);
3048}
3049#endif /* CONFIG_ANSI_C_EXTRA */
3050
3051
3052static void wpa_cli_reconnect(void)
3053{
3054 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003055 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3056 return;
3057
3058 if (interactive) {
3059 edit_clear_line();
3060 printf("\rConnection to wpa_supplicant re-established\n");
3061 edit_redraw();
3062 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003063}
3064
3065
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003066static void cli_event(const char *str)
3067{
3068 const char *start, *s;
3069
3070 start = os_strchr(str, '>');
3071 if (start == NULL)
3072 return;
3073
3074 start++;
3075
3076 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3077 s = os_strchr(start, ' ');
3078 if (s == NULL)
3079 return;
3080 s = os_strchr(s + 1, ' ');
3081 if (s == NULL)
3082 return;
3083 cli_txt_list_add(&bsses, s + 1);
3084 return;
3085 }
3086
3087 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3088 s = os_strchr(start, ' ');
3089 if (s == NULL)
3090 return;
3091 s = os_strchr(s + 1, ' ');
3092 if (s == NULL)
3093 return;
3094 cli_txt_list_del_addr(&bsses, s + 1);
3095 return;
3096 }
3097
3098#ifdef CONFIG_P2P
3099 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3100 s = os_strstr(start, " p2p_dev_addr=");
3101 if (s == NULL)
3102 return;
3103 cli_txt_list_add_addr(&p2p_peers, s + 14);
3104 return;
3105 }
3106
3107 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3108 s = os_strstr(start, " p2p_dev_addr=");
3109 if (s == NULL)
3110 return;
3111 cli_txt_list_del_addr(&p2p_peers, s + 14);
3112 return;
3113 }
3114
3115 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3116 s = os_strchr(start, ' ');
3117 if (s == NULL)
3118 return;
3119 cli_txt_list_add_word(&p2p_groups, s + 1);
3120 return;
3121 }
3122
3123 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3124 s = os_strchr(start, ' ');
3125 if (s == NULL)
3126 return;
3127 cli_txt_list_del_word(&p2p_groups, s + 1);
3128 return;
3129 }
3130#endif /* CONFIG_P2P */
3131}
3132
3133
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003134static int check_terminating(const char *msg)
3135{
3136 const char *pos = msg;
3137
3138 if (*pos == '<') {
3139 /* skip priority */
3140 pos = os_strchr(pos, '>');
3141 if (pos)
3142 pos++;
3143 else
3144 pos = msg;
3145 }
3146
3147 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3148 edit_clear_line();
3149 printf("\rConnection to wpa_supplicant lost - trying to "
3150 "reconnect\n");
3151 edit_redraw();
3152 wpa_cli_attached = 0;
3153 wpa_cli_close_connection();
3154 return 1;
3155 }
3156
3157 return 0;
3158}
3159
3160
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003161static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3162{
3163 if (ctrl_conn == NULL) {
3164 wpa_cli_reconnect();
3165 return;
3166 }
3167 while (wpa_ctrl_pending(ctrl) > 0) {
3168 char buf[256];
3169 size_t len = sizeof(buf) - 1;
3170 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3171 buf[len] = '\0';
3172 if (action_monitor)
3173 wpa_cli_action_process(buf);
3174 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003175 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003176 if (wpa_cli_show_event(buf)) {
3177 edit_clear_line();
3178 printf("\r%s\n", buf);
3179 edit_redraw();
3180 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003181
3182 if (interactive && check_terminating(buf) > 0)
3183 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003184 }
3185 } else {
3186 printf("Could not read pending message.\n");
3187 break;
3188 }
3189 }
3190
3191 if (wpa_ctrl_pending(ctrl) < 0) {
3192 printf("Connection to wpa_supplicant lost - trying to "
3193 "reconnect\n");
3194 wpa_cli_reconnect();
3195 }
3196}
3197
3198#define max_args 10
3199
3200static int tokenize_cmd(char *cmd, char *argv[])
3201{
3202 char *pos;
3203 int argc = 0;
3204
3205 pos = cmd;
3206 for (;;) {
3207 while (*pos == ' ')
3208 pos++;
3209 if (*pos == '\0')
3210 break;
3211 argv[argc] = pos;
3212 argc++;
3213 if (argc == max_args)
3214 break;
3215 if (*pos == '"') {
3216 char *pos2 = os_strrchr(pos, '"');
3217 if (pos2)
3218 pos = pos2 + 1;
3219 }
3220 while (*pos != '\0' && *pos != ' ')
3221 pos++;
3222 if (*pos == ' ')
3223 *pos++ = '\0';
3224 }
3225
3226 return argc;
3227}
3228
3229
3230static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3231{
3232 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3233 printf("Connection to wpa_supplicant lost - trying to "
3234 "reconnect\n");
3235 wpa_cli_close_connection();
3236 }
3237 if (!ctrl_conn)
3238 wpa_cli_reconnect();
3239 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3240}
3241
3242
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003243static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3244{
3245 wpa_cli_recv_pending(mon_conn, 0);
3246}
3247
3248
3249static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3250{
3251 char *argv[max_args];
3252 int argc;
3253 argc = tokenize_cmd(cmd, argv);
3254 if (argc)
3255 wpa_request(ctrl_conn, argc, argv);
3256}
3257
3258
3259static void wpa_cli_edit_eof_cb(void *ctx)
3260{
3261 eloop_terminate();
3262}
3263
3264
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003265static int warning_displayed = 0;
3266static char *hfile = NULL;
3267static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003268
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003269static void start_edit(void)
3270{
3271 char *home;
3272 char *ps = NULL;
3273
3274#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3275 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3276#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003277
3278 home = getenv("HOME");
3279 if (home) {
3280 const char *fname = ".wpa_cli_history";
3281 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3282 hfile = os_malloc(hfile_len);
3283 if (hfile)
3284 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3285 }
3286
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003287 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3288 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3289 eloop_terminate();
3290 return;
3291 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003292
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003293 edit_started = 1;
3294 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3295}
3296
3297
3298static void try_connection(void *eloop_ctx, void *timeout_ctx)
3299{
3300 if (ctrl_ifname == NULL)
3301 ctrl_ifname = wpa_cli_get_default_ifname();
3302
3303 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3304 if (!warning_displayed) {
3305 printf("Could not connect to wpa_supplicant: "
3306 "%s - re-trying\n", ctrl_ifname);
3307 warning_displayed = 1;
3308 }
3309 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3310 return;
3311 }
3312
3313 if (warning_displayed)
3314 printf("Connection established.\n");
3315
3316 start_edit();
3317}
3318
3319
3320static void wpa_cli_interactive(void)
3321{
3322 printf("\nInteractive mode\n\n");
3323
3324 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003325 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003326 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003327
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003328 cli_txt_list_flush(&p2p_peers);
3329 cli_txt_list_flush(&p2p_groups);
3330 cli_txt_list_flush(&bsses);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003331 if (edit_started)
3332 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003333 os_free(hfile);
3334 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3335 wpa_cli_close_connection();
3336}
3337
3338
3339static void wpa_cli_action(struct wpa_ctrl *ctrl)
3340{
3341#ifdef CONFIG_ANSI_C_EXTRA
3342 /* TODO: ANSI C version(?) */
3343 printf("Action processing not supported in ANSI C build.\n");
3344#else /* CONFIG_ANSI_C_EXTRA */
3345 fd_set rfds;
3346 int fd, res;
3347 struct timeval tv;
3348 char buf[256]; /* note: large enough to fit in unsolicited messages */
3349 size_t len;
3350
3351 fd = wpa_ctrl_get_fd(ctrl);
3352
3353 while (!wpa_cli_quit) {
3354 FD_ZERO(&rfds);
3355 FD_SET(fd, &rfds);
3356 tv.tv_sec = ping_interval;
3357 tv.tv_usec = 0;
3358 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3359 if (res < 0 && errno != EINTR) {
3360 perror("select");
3361 break;
3362 }
3363
3364 if (FD_ISSET(fd, &rfds))
3365 wpa_cli_recv_pending(ctrl, 1);
3366 else {
3367 /* verify that connection is still working */
3368 len = sizeof(buf) - 1;
3369 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3370 wpa_cli_action_cb) < 0 ||
3371 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3372 printf("wpa_supplicant did not reply to PING "
3373 "command - exiting\n");
3374 break;
3375 }
3376 }
3377 }
3378#endif /* CONFIG_ANSI_C_EXTRA */
3379}
3380
3381
3382static void wpa_cli_cleanup(void)
3383{
3384 wpa_cli_close_connection();
3385 if (pid_file)
3386 os_daemonize_terminate(pid_file);
3387
3388 os_program_deinit();
3389}
3390
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003391
3392static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003393{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003394 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003395}
3396
3397
3398static char * wpa_cli_get_default_ifname(void)
3399{
3400 char *ifname = NULL;
3401
3402#ifdef CONFIG_CTRL_IFACE_UNIX
3403 struct dirent *dent;
3404 DIR *dir = opendir(ctrl_iface_dir);
3405 if (!dir) {
3406#ifdef ANDROID
3407 char ifprop[PROPERTY_VALUE_MAX];
3408 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3409 ifname = os_strdup(ifprop);
3410 printf("Using interface '%s'\n", ifname);
3411 return ifname;
3412 }
3413#endif /* ANDROID */
3414 return NULL;
3415 }
3416 while ((dent = readdir(dir))) {
3417#ifdef _DIRENT_HAVE_D_TYPE
3418 /*
3419 * Skip the file if it is not a socket. Also accept
3420 * DT_UNKNOWN (0) in case the C library or underlying
3421 * file system does not support d_type.
3422 */
3423 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3424 continue;
3425#endif /* _DIRENT_HAVE_D_TYPE */
3426 if (os_strcmp(dent->d_name, ".") == 0 ||
3427 os_strcmp(dent->d_name, "..") == 0)
3428 continue;
3429 printf("Selected interface '%s'\n", dent->d_name);
3430 ifname = os_strdup(dent->d_name);
3431 break;
3432 }
3433 closedir(dir);
3434#endif /* CONFIG_CTRL_IFACE_UNIX */
3435
3436#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003437#ifdef ANDROID
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -07003438 char buf[4096], *pos;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003439#else
3440 char buf[2048], *pos;
3441#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003442 size_t len;
3443 struct wpa_ctrl *ctrl;
3444 int ret;
3445
3446 ctrl = wpa_ctrl_open(NULL);
3447 if (ctrl == NULL)
3448 return NULL;
3449
3450 len = sizeof(buf) - 1;
3451 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3452 if (ret >= 0) {
3453 buf[len] = '\0';
3454 pos = os_strchr(buf, '\n');
3455 if (pos)
3456 *pos = '\0';
3457 ifname = os_strdup(buf);
3458 }
3459 wpa_ctrl_close(ctrl);
3460#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3461
3462 return ifname;
3463}
3464
3465
3466int main(int argc, char *argv[])
3467{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003468 int c;
3469 int daemonize = 0;
3470 int ret = 0;
3471 const char *global = NULL;
3472
3473 if (os_program_init())
3474 return -1;
3475
3476 for (;;) {
3477 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3478 if (c < 0)
3479 break;
3480 switch (c) {
3481 case 'a':
3482 action_file = optarg;
3483 break;
3484 case 'B':
3485 daemonize = 1;
3486 break;
3487 case 'g':
3488 global = optarg;
3489 break;
3490 case 'G':
3491 ping_interval = atoi(optarg);
3492 break;
3493 case 'h':
3494 usage();
3495 return 0;
3496 case 'v':
3497 printf("%s\n", wpa_cli_version);
3498 return 0;
3499 case 'i':
3500 os_free(ctrl_ifname);
3501 ctrl_ifname = os_strdup(optarg);
3502 break;
3503 case 'p':
3504 ctrl_iface_dir = optarg;
3505 break;
3506 case 'P':
3507 pid_file = optarg;
3508 break;
3509 default:
3510 usage();
3511 return -1;
3512 }
3513 }
3514
3515 interactive = (argc == optind) && (action_file == NULL);
3516
3517 if (interactive)
3518 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3519
3520 if (eloop_init())
3521 return -1;
3522
3523 if (global) {
3524#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3525 ctrl_conn = wpa_ctrl_open(NULL);
3526#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3527 ctrl_conn = wpa_ctrl_open(global);
3528#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3529 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003530 fprintf(stderr, "Failed to connect to wpa_supplicant "
3531 "global interface: %s error: %s\n",
3532 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003533 return -1;
3534 }
3535 }
3536
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003537 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003538
3539 if (ctrl_ifname == NULL)
3540 ctrl_ifname = wpa_cli_get_default_ifname();
3541
3542 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003543 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003544 } else {
3545 if (!global &&
3546 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003547 fprintf(stderr, "Failed to connect to non-global "
3548 "ctrl_ifname: %s error: %s\n",
3549 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003550 return -1;
3551 }
3552
3553 if (action_file) {
3554 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3555 wpa_cli_attached = 1;
3556 } else {
3557 printf("Warning: Failed to attach to "
3558 "wpa_supplicant.\n");
3559 return -1;
3560 }
3561 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003562
3563 if (daemonize && os_daemonize(pid_file))
3564 return -1;
3565
3566 if (action_file)
3567 wpa_cli_action(ctrl_conn);
3568 else
3569 ret = wpa_request(ctrl_conn, argc - optind,
3570 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003571 }
3572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003573 os_free(ctrl_ifname);
3574 eloop_destroy();
3575 wpa_cli_cleanup();
3576
3577 return ret;
3578}
3579
3580#else /* CONFIG_CTRL_IFACE */
3581int main(int argc, char *argv[])
3582{
3583 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3584 return -1;
3585}
3586#endif /* CONFIG_CTRL_IFACE */