blob: 0630a4b3b1d0b75c913d99604677bcf25b52d07f [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
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800773static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
774 char *argv[])
775{
776 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
777}
778
779
Dmitry Shmidt04949592012-07-19 12:16:46 -0700780static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
781 char *argv[])
782{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700783 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700784}
785
786
787static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
788 char *argv[])
789{
790 int ret;
791 char *buf;
792 size_t buflen;
793
794 if (argc != 1) {
795 printf("Invalid 'wps_nfc_tag_read' command - one argument "
796 "is required.\n");
797 return -1;
798 }
799
800 buflen = 18 + os_strlen(argv[0]);
801 buf = os_malloc(buflen);
802 if (buf == NULL)
803 return -1;
804 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
805
806 ret = wpa_ctrl_command(ctrl, buf);
807 os_free(buf);
808
809 return ret;
810}
811
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800812
813static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
814 char *argv[])
815{
816 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
817}
818
819
820static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
821 char *argv[])
822{
823 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
824}
825
826
827static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
828 char *argv[])
829{
830 int ret;
831 char *buf;
832 size_t buflen;
833
834 if (argc != 1) {
835 printf("Invalid 'nfc_rx_handover_req' command - one argument "
836 "is required.\n");
837 return -1;
838 }
839
840 buflen = 21 + os_strlen(argv[0]);
841 buf = os_malloc(buflen);
842 if (buf == NULL)
843 return -1;
844 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
845
846 ret = wpa_ctrl_command(ctrl, buf);
847 os_free(buf);
848
849 return ret;
850}
851
852
853static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
854 char *argv[])
855{
856 int ret;
857 char *buf;
858 size_t buflen;
859
860 if (argc != 1) {
861 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
862 "is required.\n");
863 return -1;
864 }
865
866 buflen = 21 + os_strlen(argv[0]);
867 buf = os_malloc(buflen);
868 if (buf == NULL)
869 return -1;
870 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
871
872 ret = wpa_ctrl_command(ctrl, buf);
873 os_free(buf);
874
875 return ret;
876}
877
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800878
879static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
880 char *argv[])
881{
882 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
883}
884
Dmitry Shmidt04949592012-07-19 12:16:46 -0700885#endif /* CONFIG_WPS_NFC */
886
887
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700888static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
889{
890 char cmd[256];
891 int res;
892
893 if (argc == 2)
894 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
895 argv[0], argv[1]);
896 else if (argc == 5 || argc == 6) {
897 char ssid_hex[2 * 32 + 1];
898 char key_hex[2 * 64 + 1];
899 int i;
900
901 ssid_hex[0] = '\0';
902 for (i = 0; i < 32; i++) {
903 if (argv[2][i] == '\0')
904 break;
905 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
906 }
907
908 key_hex[0] = '\0';
909 if (argc == 6) {
910 for (i = 0; i < 64; i++) {
911 if (argv[5][i] == '\0')
912 break;
913 os_snprintf(&key_hex[i * 2], 3, "%02x",
914 argv[5][i]);
915 }
916 }
917
918 res = os_snprintf(cmd, sizeof(cmd),
919 "WPS_REG %s %s %s %s %s %s",
920 argv[0], argv[1], ssid_hex, argv[3], argv[4],
921 key_hex);
922 } else {
923 printf("Invalid WPS_REG command: need two arguments:\n"
924 "- BSSID of the target AP\n"
925 "- AP PIN\n");
926 printf("Alternatively, six arguments can be used to "
927 "reconfigure the AP:\n"
928 "- BSSID of the target AP\n"
929 "- AP PIN\n"
930 "- new SSID\n"
931 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
932 "- new encr (NONE, WEP, TKIP, CCMP)\n"
933 "- new key\n");
934 return -1;
935 }
936
937 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
938 printf("Too long WPS_REG command.\n");
939 return -1;
940 }
941 return wpa_ctrl_command(ctrl, cmd);
942}
943
944
945static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
946 char *argv[])
947{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700948 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700949}
950
951
952static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
953 char *argv[])
954{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700955 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700956}
957
958
959static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
960 char *argv[])
961{
962 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
963
964}
965
966
967static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
968 char *argv[])
969{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700970 if (argc < 2) {
971 printf("Invalid WPS_ER_PIN command: need at least two "
972 "arguments:\n"
973 "- UUID: use 'any' to select any\n"
974 "- PIN: Enrollee PIN\n"
975 "optional: - Enrollee MAC address\n");
976 return -1;
977 }
978
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700979 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700980}
981
982
983static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
984 char *argv[])
985{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700986 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700987}
988
989
990static int wpa_cli_cmd_wps_er_learn(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_LEARN command: need two arguments:\n"
995 "- UUID: specify which AP to use\n"
996 "- PIN: AP PIN\n");
997 return -1;
998 }
999
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001000 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001001}
1002
1003
1004static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1005 char *argv[])
1006{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001007 if (argc != 2) {
1008 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1009 "arguments:\n"
1010 "- UUID: specify which AP to use\n"
1011 "- Network configuration id\n");
1012 return -1;
1013 }
1014
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001015 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016}
1017
1018
1019static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1020 char *argv[])
1021{
1022 char cmd[256];
1023 int res;
1024
1025 if (argc == 5 || argc == 6) {
1026 char ssid_hex[2 * 32 + 1];
1027 char key_hex[2 * 64 + 1];
1028 int i;
1029
1030 ssid_hex[0] = '\0';
1031 for (i = 0; i < 32; i++) {
1032 if (argv[2][i] == '\0')
1033 break;
1034 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1035 }
1036
1037 key_hex[0] = '\0';
1038 if (argc == 6) {
1039 for (i = 0; i < 64; i++) {
1040 if (argv[5][i] == '\0')
1041 break;
1042 os_snprintf(&key_hex[i * 2], 3, "%02x",
1043 argv[5][i]);
1044 }
1045 }
1046
1047 res = os_snprintf(cmd, sizeof(cmd),
1048 "WPS_ER_CONFIG %s %s %s %s %s %s",
1049 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1050 key_hex);
1051 } else {
1052 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1053 "- AP UUID\n"
1054 "- AP PIN\n"
1055 "- new SSID\n"
1056 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1057 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1058 "- new key\n");
1059 return -1;
1060 }
1061
1062 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1063 printf("Too long WPS_ER_CONFIG command.\n");
1064 return -1;
1065 }
1066 return wpa_ctrl_command(ctrl, cmd);
1067}
1068
1069
Dmitry Shmidt04949592012-07-19 12:16:46 -07001070#ifdef CONFIG_WPS_NFC
1071static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1072 char *argv[])
1073{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001074 if (argc != 2) {
1075 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1076 "arguments:\n"
1077 "- WPS/NDEF: token format\n"
1078 "- UUID: specify which AP to use\n");
1079 return -1;
1080 }
1081
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001082 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001083}
1084#endif /* CONFIG_WPS_NFC */
1085
1086
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001087static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1088{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001089 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001090}
1091
1092
1093static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1094{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001095 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001096}
1097
1098
1099static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1100{
1101 char cmd[256], *pos, *end;
1102 int i, ret;
1103
1104 if (argc < 2) {
1105 printf("Invalid IDENTITY command: needs two arguments "
1106 "(network id and identity)\n");
1107 return -1;
1108 }
1109
1110 end = cmd + sizeof(cmd);
1111 pos = cmd;
1112 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1113 argv[0], argv[1]);
1114 if (ret < 0 || ret >= end - pos) {
1115 printf("Too long IDENTITY command.\n");
1116 return -1;
1117 }
1118 pos += ret;
1119 for (i = 2; i < argc; i++) {
1120 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1121 if (ret < 0 || ret >= end - pos) {
1122 printf("Too long IDENTITY command.\n");
1123 return -1;
1124 }
1125 pos += ret;
1126 }
1127
1128 return wpa_ctrl_command(ctrl, cmd);
1129}
1130
1131
1132static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1133{
1134 char cmd[256], *pos, *end;
1135 int i, ret;
1136
1137 if (argc < 2) {
1138 printf("Invalid PASSWORD command: needs two arguments "
1139 "(network id and password)\n");
1140 return -1;
1141 }
1142
1143 end = cmd + sizeof(cmd);
1144 pos = cmd;
1145 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1146 argv[0], argv[1]);
1147 if (ret < 0 || ret >= end - pos) {
1148 printf("Too long PASSWORD command.\n");
1149 return -1;
1150 }
1151 pos += ret;
1152 for (i = 2; i < argc; i++) {
1153 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1154 if (ret < 0 || ret >= end - pos) {
1155 printf("Too long PASSWORD command.\n");
1156 return -1;
1157 }
1158 pos += ret;
1159 }
1160
1161 return wpa_ctrl_command(ctrl, cmd);
1162}
1163
1164
1165static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1166 char *argv[])
1167{
1168 char cmd[256], *pos, *end;
1169 int i, ret;
1170
1171 if (argc < 2) {
1172 printf("Invalid NEW_PASSWORD command: needs two arguments "
1173 "(network id and password)\n");
1174 return -1;
1175 }
1176
1177 end = cmd + sizeof(cmd);
1178 pos = cmd;
1179 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1180 argv[0], argv[1]);
1181 if (ret < 0 || ret >= end - pos) {
1182 printf("Too long NEW_PASSWORD command.\n");
1183 return -1;
1184 }
1185 pos += ret;
1186 for (i = 2; i < argc; i++) {
1187 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1188 if (ret < 0 || ret >= end - pos) {
1189 printf("Too long NEW_PASSWORD command.\n");
1190 return -1;
1191 }
1192 pos += ret;
1193 }
1194
1195 return wpa_ctrl_command(ctrl, cmd);
1196}
1197
1198
1199static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1200{
1201 char cmd[256], *pos, *end;
1202 int i, ret;
1203
1204 if (argc < 2) {
1205 printf("Invalid PIN command: needs two arguments "
1206 "(network id and pin)\n");
1207 return -1;
1208 }
1209
1210 end = cmd + sizeof(cmd);
1211 pos = cmd;
1212 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1213 argv[0], argv[1]);
1214 if (ret < 0 || ret >= end - pos) {
1215 printf("Too long PIN command.\n");
1216 return -1;
1217 }
1218 pos += ret;
1219 for (i = 2; i < argc; i++) {
1220 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1221 if (ret < 0 || ret >= end - pos) {
1222 printf("Too long PIN command.\n");
1223 return -1;
1224 }
1225 pos += ret;
1226 }
1227 return wpa_ctrl_command(ctrl, cmd);
1228}
1229
1230
1231static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1232{
1233 char cmd[256], *pos, *end;
1234 int i, ret;
1235
1236 if (argc < 2) {
1237 printf("Invalid OTP command: needs two arguments (network "
1238 "id and password)\n");
1239 return -1;
1240 }
1241
1242 end = cmd + sizeof(cmd);
1243 pos = cmd;
1244 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1245 argv[0], argv[1]);
1246 if (ret < 0 || ret >= end - pos) {
1247 printf("Too long OTP command.\n");
1248 return -1;
1249 }
1250 pos += ret;
1251 for (i = 2; i < argc; i++) {
1252 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1253 if (ret < 0 || ret >= end - pos) {
1254 printf("Too long OTP command.\n");
1255 return -1;
1256 }
1257 pos += ret;
1258 }
1259
1260 return wpa_ctrl_command(ctrl, cmd);
1261}
1262
1263
1264static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1265 char *argv[])
1266{
1267 char cmd[256], *pos, *end;
1268 int i, ret;
1269
1270 if (argc < 2) {
1271 printf("Invalid PASSPHRASE command: needs two arguments "
1272 "(network id and passphrase)\n");
1273 return -1;
1274 }
1275
1276 end = cmd + sizeof(cmd);
1277 pos = cmd;
1278 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1279 argv[0], argv[1]);
1280 if (ret < 0 || ret >= end - pos) {
1281 printf("Too long PASSPHRASE command.\n");
1282 return -1;
1283 }
1284 pos += ret;
1285 for (i = 2; i < argc; i++) {
1286 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1287 if (ret < 0 || ret >= end - pos) {
1288 printf("Too long PASSPHRASE command.\n");
1289 return -1;
1290 }
1291 pos += ret;
1292 }
1293
1294 return wpa_ctrl_command(ctrl, cmd);
1295}
1296
1297
1298static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1299{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001300 if (argc < 2) {
1301 printf("Invalid BSSID command: needs two arguments (network "
1302 "id and BSSID)\n");
1303 return -1;
1304 }
1305
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001306 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001307}
1308
1309
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001310static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1311{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001312 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001313}
1314
1315
1316static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1317{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001318 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001319}
1320
1321
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001322static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1323 char *argv[])
1324{
1325 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1326}
1327
1328
1329static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1330 char *argv[])
1331{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001332 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001333}
1334
1335
1336static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1337 char *argv[])
1338{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001339 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001340}
1341
1342
1343static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1344 char *argv[])
1345{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001346 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001347}
1348
1349
1350static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1351 char *argv[])
1352{
1353 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1354}
1355
1356
1357static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1358 char *argv[])
1359{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001360 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001361}
1362
1363
1364static void wpa_cli_show_network_variables(void)
1365{
1366 printf("set_network variables:\n"
1367 " ssid (network name, SSID)\n"
1368 " psk (WPA passphrase or pre-shared key)\n"
1369 " key_mgmt (key management protocol)\n"
1370 " identity (EAP identity)\n"
1371 " password (EAP password)\n"
1372 " ...\n"
1373 "\n"
1374 "Note: Values are entered in the same format as the "
1375 "configuration file is using,\n"
1376 "i.e., strings values need to be inside double quotation "
1377 "marks.\n"
1378 "For example: set_network 1 ssid \"network name\"\n"
1379 "\n"
1380 "Please see wpa_supplicant.conf documentation for full list "
1381 "of\navailable variables.\n");
1382}
1383
1384
1385static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1386 char *argv[])
1387{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001388 if (argc == 0) {
1389 wpa_cli_show_network_variables();
1390 return 0;
1391 }
1392
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001393 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001394 printf("Invalid SET_NETWORK command: needs three arguments\n"
1395 "(network id, variable name, and value)\n");
1396 return -1;
1397 }
1398
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001399 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001400}
1401
1402
1403static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1404 char *argv[])
1405{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001406 if (argc == 0) {
1407 wpa_cli_show_network_variables();
1408 return 0;
1409 }
1410
1411 if (argc != 2) {
1412 printf("Invalid GET_NETWORK command: needs two arguments\n"
1413 "(network id and variable name)\n");
1414 return -1;
1415 }
1416
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001417 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001418}
1419
1420
Dmitry Shmidt04949592012-07-19 12:16:46 -07001421static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1422 char *argv[])
1423{
1424 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1425}
1426
1427
1428static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1429{
1430 return wpa_ctrl_command(ctrl, "ADD_CRED");
1431}
1432
1433
1434static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1435 char *argv[])
1436{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001437 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001438}
1439
1440
1441static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1442{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001443 if (argc != 3) {
1444 printf("Invalid SET_CRED command: needs three arguments\n"
1445 "(cred id, variable name, and value)\n");
1446 return -1;
1447 }
1448
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001449 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001450}
1451
1452
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001453static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1454 char *argv[])
1455{
1456 return wpa_ctrl_command(ctrl, "DISCONNECT");
1457}
1458
1459
1460static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1461 char *argv[])
1462{
1463 return wpa_ctrl_command(ctrl, "RECONNECT");
1464}
1465
1466
1467static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1468 char *argv[])
1469{
1470 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1471}
1472
1473
1474static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1475{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001476 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001477}
1478
1479
1480static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1481 char *argv[])
1482{
1483 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1484}
1485
1486
1487static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1488{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001489 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001490}
1491
1492
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001493static char ** wpa_cli_complete_bss(const char *str, int pos)
1494{
1495 int arg = get_cmd_arg_num(str, pos);
1496 char **res = NULL;
1497
1498 switch (arg) {
1499 case 1:
1500 res = cli_txt_list_array(&bsses);
1501 break;
1502 }
1503
1504 return res;
1505}
1506
1507
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001508static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1509 char *argv[])
1510{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001511 if (argc < 1 || argc > 2) {
1512 printf("Invalid GET_CAPABILITY command: need either one or "
1513 "two arguments\n");
1514 return -1;
1515 }
1516
1517 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1518 printf("Invalid GET_CAPABILITY command: second argument, "
1519 "if any, must be 'strict'\n");
1520 return -1;
1521 }
1522
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001523 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001524}
1525
1526
1527static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1528{
1529 printf("Available interfaces:\n");
1530 return wpa_ctrl_command(ctrl, "INTERFACES");
1531}
1532
1533
1534static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1535{
1536 if (argc < 1) {
1537 wpa_cli_list_interfaces(ctrl);
1538 return 0;
1539 }
1540
1541 wpa_cli_close_connection();
1542 os_free(ctrl_ifname);
1543 ctrl_ifname = os_strdup(argv[0]);
1544
1545 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1546 printf("Connected to interface '%s.\n", ctrl_ifname);
1547 } else {
1548 printf("Could not connect to interface '%s' - re-trying\n",
1549 ctrl_ifname);
1550 }
1551 return 0;
1552}
1553
1554
1555static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1556 char *argv[])
1557{
1558 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1559}
1560
1561
1562static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1563 char *argv[])
1564{
1565 return wpa_ctrl_command(ctrl, "TERMINATE");
1566}
1567
1568
1569static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1570 char *argv[])
1571{
1572 char cmd[256];
1573 int res;
1574
1575 if (argc < 1) {
1576 printf("Invalid INTERFACE_ADD command: needs at least one "
1577 "argument (interface name)\n"
1578 "All arguments: ifname confname driver ctrl_interface "
1579 "driver_param bridge_name\n");
1580 return -1;
1581 }
1582
1583 /*
1584 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1585 * <driver_param>TAB<bridge_name>
1586 */
1587 res = os_snprintf(cmd, sizeof(cmd),
1588 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1589 argv[0],
1590 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1591 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1592 argc > 5 ? argv[5] : "");
1593 if (res < 0 || (size_t) res >= sizeof(cmd))
1594 return -1;
1595 cmd[sizeof(cmd) - 1] = '\0';
1596 return wpa_ctrl_command(ctrl, cmd);
1597}
1598
1599
1600static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1601 char *argv[])
1602{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001603 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001604}
1605
1606
1607static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1608 char *argv[])
1609{
1610 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1611}
1612
1613
1614#ifdef CONFIG_AP
1615static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1616{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001617 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001618}
1619
1620
1621static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1622 char *addr, size_t addr_len)
1623{
1624 char buf[4096], *pos;
1625 size_t len;
1626 int ret;
1627
1628 if (ctrl_conn == NULL) {
1629 printf("Not connected to hostapd - command dropped.\n");
1630 return -1;
1631 }
1632 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001633 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001634 wpa_cli_msg_cb);
1635 if (ret == -2) {
1636 printf("'%s' command timed out.\n", cmd);
1637 return -2;
1638 } else if (ret < 0) {
1639 printf("'%s' command failed.\n", cmd);
1640 return -1;
1641 }
1642
1643 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001644 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001645 return -1;
1646 printf("%s", buf);
1647
1648 pos = buf;
1649 while (*pos != '\0' && *pos != '\n')
1650 pos++;
1651 *pos = '\0';
1652 os_strlcpy(addr, buf, addr_len);
1653 return 0;
1654}
1655
1656
1657static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1658{
1659 char addr[32], cmd[64];
1660
1661 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1662 return 0;
1663 do {
1664 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1665 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1666
1667 return -1;
1668}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001669
1670
1671static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1672 char *argv[])
1673{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001674 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001675}
1676
1677
1678static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1679 char *argv[])
1680{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001681 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001682}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001683#endif /* CONFIG_AP */
1684
1685
1686static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1687{
1688 return wpa_ctrl_command(ctrl, "SUSPEND");
1689}
1690
1691
1692static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1693{
1694 return wpa_ctrl_command(ctrl, "RESUME");
1695}
1696
1697
1698static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1699{
1700 return wpa_ctrl_command(ctrl, "DROP_SA");
1701}
1702
1703
1704static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1705{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001706 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001707}
1708
1709
1710#ifdef CONFIG_P2P
1711
1712static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1713{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001714 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1715}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001717
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001718static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1719{
1720 char **res = NULL;
1721 int arg = get_cmd_arg_num(str, pos);
1722
1723 res = os_calloc(6, sizeof(char *));
1724 if (res == NULL)
1725 return NULL;
1726 res[0] = os_strdup("type=social");
1727 if (res[0] == NULL) {
1728 os_free(res);
1729 return NULL;
1730 }
1731 res[1] = os_strdup("type=progressive");
1732 if (res[1] == NULL)
1733 return res;
1734 res[2] = os_strdup("delay=");
1735 if (res[2] == NULL)
1736 return res;
1737 res[3] = os_strdup("dev_id=");
1738 if (res[3] == NULL)
1739 return res;
1740 if (arg == 1)
1741 res[4] = os_strdup("[timeout]");
1742
1743 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001744}
1745
1746
1747static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1748 char *argv[])
1749{
1750 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1751}
1752
1753
1754static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1755 char *argv[])
1756{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001757 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001758}
1759
1760
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001761static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1762{
1763 int arg = get_cmd_arg_num(str, pos);
1764 char **res = NULL;
1765
1766 switch (arg) {
1767 case 1:
1768 res = cli_txt_list_array(&p2p_peers);
1769 break;
1770 }
1771
1772 return res;
1773}
1774
1775
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001776static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1777 char *argv[])
1778{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001779 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001780}
1781
1782
1783static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1784 char *argv[])
1785{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001786 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787}
1788
1789
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001790static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1791{
1792 int arg = get_cmd_arg_num(str, pos);
1793 char **res = NULL;
1794
1795 switch (arg) {
1796 case 1:
1797 res = cli_txt_list_array(&p2p_groups);
1798 break;
1799 }
1800
1801 return res;
1802}
1803
1804
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001805static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1806 char *argv[])
1807{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001808 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001809}
1810
1811
1812static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1813 char *argv[])
1814{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001815 if (argc != 2 && argc != 3) {
1816 printf("Invalid P2P_PROV_DISC command: needs at least "
1817 "two arguments, address and config method\n"
1818 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001819 return -1;
1820 }
1821
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001822 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001823}
1824
1825
1826static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1827 char *argv[])
1828{
1829 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1830}
1831
1832
1833static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1834 char *argv[])
1835{
1836 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001837
1838 if (argc != 2 && argc != 4) {
1839 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1840 "arguments (address and TLVs) or four arguments "
1841 "(address, \"upnp\", version, search target "
1842 "(SSDP ST:)\n");
1843 return -1;
1844 }
1845
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001846 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001847 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001848 return wpa_ctrl_command(ctrl, cmd);
1849}
1850
1851
1852static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1853 int argc, char *argv[])
1854{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001855 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856}
1857
1858
1859static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1860 char *argv[])
1861{
1862 char cmd[4096];
1863 int res;
1864
1865 if (argc != 4) {
1866 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1867 "arguments (freq, address, dialog token, and TLVs)\n");
1868 return -1;
1869 }
1870
1871 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1872 argv[0], argv[1], argv[2], argv[3]);
1873 if (res < 0 || (size_t) res >= sizeof(cmd))
1874 return -1;
1875 cmd[sizeof(cmd) - 1] = '\0';
1876 return wpa_ctrl_command(ctrl, cmd);
1877}
1878
1879
1880static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1881 char *argv[])
1882{
1883 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1884}
1885
1886
1887static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1888 int argc, char *argv[])
1889{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001890 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001891}
1892
1893
1894static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1895 char *argv[])
1896{
1897 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1898}
1899
1900
1901static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1902 char *argv[])
1903{
1904 char cmd[4096];
1905 int res;
1906
1907 if (argc != 3 && argc != 4) {
1908 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1909 "arguments\n");
1910 return -1;
1911 }
1912
1913 if (argc == 4)
1914 res = os_snprintf(cmd, sizeof(cmd),
1915 "P2P_SERVICE_ADD %s %s %s %s",
1916 argv[0], argv[1], argv[2], argv[3]);
1917 else
1918 res = os_snprintf(cmd, sizeof(cmd),
1919 "P2P_SERVICE_ADD %s %s %s",
1920 argv[0], argv[1], argv[2]);
1921 if (res < 0 || (size_t) res >= sizeof(cmd))
1922 return -1;
1923 cmd[sizeof(cmd) - 1] = '\0';
1924 return wpa_ctrl_command(ctrl, cmd);
1925}
1926
1927
1928static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1929 char *argv[])
1930{
1931 char cmd[4096];
1932 int res;
1933
1934 if (argc != 2 && argc != 3) {
1935 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1936 "arguments\n");
1937 return -1;
1938 }
1939
1940 if (argc == 3)
1941 res = os_snprintf(cmd, sizeof(cmd),
1942 "P2P_SERVICE_DEL %s %s %s",
1943 argv[0], argv[1], argv[2]);
1944 else
1945 res = os_snprintf(cmd, sizeof(cmd),
1946 "P2P_SERVICE_DEL %s %s",
1947 argv[0], argv[1]);
1948 if (res < 0 || (size_t) res >= sizeof(cmd))
1949 return -1;
1950 cmd[sizeof(cmd) - 1] = '\0';
1951 return wpa_ctrl_command(ctrl, cmd);
1952}
1953
1954
1955static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1956 int argc, char *argv[])
1957{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001958 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001959}
1960
1961
1962static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1963 int argc, char *argv[])
1964{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001965 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001966}
1967
1968
1969static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1970{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001971 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001972}
1973
1974
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001975static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1976{
1977 int arg = get_cmd_arg_num(str, pos);
1978 char **res = NULL;
1979
1980 switch (arg) {
1981 case 1:
1982 res = cli_txt_list_array(&p2p_peers);
1983 break;
1984 }
1985
1986 return res;
1987}
1988
1989
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001990static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1991 char *addr, size_t addr_len,
1992 int discovered)
1993{
1994 char buf[4096], *pos;
1995 size_t len;
1996 int ret;
1997
1998 if (ctrl_conn == NULL)
1999 return -1;
2000 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002001 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002002 wpa_cli_msg_cb);
2003 if (ret == -2) {
2004 printf("'%s' command timed out.\n", cmd);
2005 return -2;
2006 } else if (ret < 0) {
2007 printf("'%s' command failed.\n", cmd);
2008 return -1;
2009 }
2010
2011 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002012 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002013 return -1;
2014
2015 pos = buf;
2016 while (*pos != '\0' && *pos != '\n')
2017 pos++;
2018 *pos++ = '\0';
2019 os_strlcpy(addr, buf, addr_len);
2020 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2021 printf("%s\n", addr);
2022 return 0;
2023}
2024
2025
2026static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2027{
2028 char addr[32], cmd[64];
2029 int discovered;
2030
2031 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2032
2033 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2034 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002035 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002036 do {
2037 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2038 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2039 discovered) == 0);
2040
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002041 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002042}
2043
2044
2045static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2046{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002047 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002048}
2049
2050
2051static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2052{
2053 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2054}
2055
2056
2057static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2058 char *argv[])
2059{
2060 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2061}
2062
2063
2064static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2065 char *argv[])
2066{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002067 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002068}
2069
2070
2071static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2072 char *argv[])
2073{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002074 if (argc != 0 && argc != 2 && argc != 4) {
2075 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2076 "(preferred duration, interval; in microsecods).\n"
2077 "Optional second pair can be used to provide "
2078 "acceptable values.\n");
2079 return -1;
2080 }
2081
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002082 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002083}
2084
2085
2086static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2087 char *argv[])
2088{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002089 if (argc != 0 && argc != 2) {
2090 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2091 "(availability period, availability interval; in "
2092 "millisecods).\n"
2093 "Extended Listen Timing can be cancelled with this "
2094 "command when used without parameters.\n");
2095 return -1;
2096 }
2097
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002098 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2099}
2100
2101#endif /* CONFIG_P2P */
2102
2103#ifdef CONFIG_WIFI_DISPLAY
2104
2105static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2106 char *argv[])
2107{
2108 char cmd[100];
2109 int res;
2110
2111 if (argc != 1 && argc != 2) {
2112 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2113 "arguments (subelem, hexdump)\n");
2114 return -1;
2115 }
2116
2117 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2118 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002119 if (res < 0 || (size_t) res >= sizeof(cmd))
2120 return -1;
2121 cmd[sizeof(cmd) - 1] = '\0';
2122 return wpa_ctrl_command(ctrl, cmd);
2123}
2124
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002125
2126static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2127 char *argv[])
2128{
2129 char cmd[100];
2130 int res;
2131
2132 if (argc != 1) {
2133 printf("Invalid WFD_SUBELEM_GET command: needs one "
2134 "argument (subelem)\n");
2135 return -1;
2136 }
2137
2138 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2139 argv[0]);
2140 if (res < 0 || (size_t) res >= sizeof(cmd))
2141 return -1;
2142 cmd[sizeof(cmd) - 1] = '\0';
2143 return wpa_ctrl_command(ctrl, cmd);
2144}
2145#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002146
2147
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002148#ifdef CONFIG_INTERWORKING
2149static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2150 char *argv[])
2151{
2152 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2153}
2154
2155
2156static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2157 char *argv[])
2158{
2159 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2160}
2161
2162
2163static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2164 char *argv[])
2165{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002166 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002167}
2168
2169
2170static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2171 char *argv[])
2172{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002173 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002174}
2175
2176
2177static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2178{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002179 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2180}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002181
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002182
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002183static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2184 char *argv[])
2185{
2186 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2187}
2188
2189
2190static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2191 char *argv[])
2192{
2193 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002194}
2195#endif /* CONFIG_INTERWORKING */
2196
2197
Dmitry Shmidt04949592012-07-19 12:16:46 -07002198#ifdef CONFIG_HS20
2199
2200static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2201 char *argv[])
2202{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002203 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002204}
2205
2206
2207static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2208 char *argv[])
2209{
2210 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002211
2212 if (argc == 0) {
2213 printf("Command needs one or two arguments (dst mac addr and "
2214 "optional home realm)\n");
2215 return -1;
2216 }
2217
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002218 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2219 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002220 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002221
2222 return wpa_ctrl_command(ctrl, cmd);
2223}
2224
2225#endif /* CONFIG_HS20 */
2226
2227
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002228static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2229 char *argv[])
2230{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002231 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002232}
2233
2234
2235static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2236 char *argv[])
2237{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002238 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002239}
2240
2241
2242static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2243 char *argv[])
2244{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002245 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002246}
2247
2248
2249static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2250 char *argv[])
2251{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002252 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002253}
2254
2255
2256static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2257 char *argv[])
2258{
2259 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2260}
2261
2262
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002263static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2264 char *argv[])
2265{
2266 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2267}
2268
2269
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002270static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2271 char *argv[])
2272{
2273 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2274}
2275
Dmitry Shmidt04949592012-07-19 12:16:46 -07002276
2277#ifdef CONFIG_AUTOSCAN
2278
2279static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2280{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002281 if (argc == 0)
2282 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2283
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002284 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002285}
2286
2287#endif /* CONFIG_AUTOSCAN */
2288
2289
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002290#ifdef CONFIG_WNM
2291
2292static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2293{
2294 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2295}
2296
2297#endif /* CONFIG_WNM */
2298
2299
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002300static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2301{
2302 if (argc == 0)
2303 return -1;
2304 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2305}
2306
2307
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002308#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002309static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2310{
2311 char cmd[256];
2312 int i;
2313 int len;
2314
2315 if (argc < 1) {
2316 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2317 return -1;
2318 }
2319
2320 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2321 for (i=1; i < argc; i++)
2322 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2323 cmd[sizeof(cmd) - 1] = '\0';
2324 printf("%s: %s\n", __func__, cmd);
2325 return wpa_ctrl_command(ctrl, cmd);
2326}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002327#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002328
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002329
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002330enum wpa_cli_cmd_flags {
2331 cli_cmd_flag_none = 0x00,
2332 cli_cmd_flag_sensitive = 0x01
2333};
2334
2335struct wpa_cli_cmd {
2336 const char *cmd;
2337 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002338 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002339 enum wpa_cli_cmd_flags flags;
2340 const char *usage;
2341};
2342
2343static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002344 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002345 cli_cmd_flag_none,
2346 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002347 { "ifname", wpa_cli_cmd_ifname, NULL,
2348 cli_cmd_flag_none,
2349 "= get current interface name" },
2350 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002351 cli_cmd_flag_none,
2352 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002353 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002354 cli_cmd_flag_none,
2355 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002356 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002357 cli_cmd_flag_none,
2358 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002359 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002360 cli_cmd_flag_none,
2361 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002362 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002363 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002364 "[command] = show usage help" },
2365 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002366 cli_cmd_flag_none,
2367 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002368 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002369 cli_cmd_flag_none,
2370 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002371 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002372 cli_cmd_flag_none,
2373 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002374 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002375 cli_cmd_flag_none,
2376 "= exit wpa_cli" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002377 { "set", wpa_cli_cmd_set, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002378 cli_cmd_flag_none,
2379 "= set variables (shows list of variables when run without "
2380 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002381 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002382 cli_cmd_flag_none,
2383 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002384 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002385 cli_cmd_flag_none,
2386 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002387 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002388 cli_cmd_flag_none,
2389 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002390 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002391 cli_cmd_flag_none,
2392 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002393 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002394 cli_cmd_flag_none,
2395 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002396 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002397 cli_cmd_flag_none,
2398 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002399 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002400 cli_cmd_flag_none,
2401 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002402 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002403 cli_cmd_flag_sensitive,
2404 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002405 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002406 cli_cmd_flag_sensitive,
2407 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002408 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002409 cli_cmd_flag_sensitive,
2410 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002411 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002412 cli_cmd_flag_sensitive,
2413 "<network id> <password> = configure one-time-password for an SSID"
2414 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002415 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002416 cli_cmd_flag_sensitive,
2417 "<network id> <passphrase> = configure private key passphrase\n"
2418 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002419 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002420 cli_cmd_flag_none,
2421 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002422 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002423 cli_cmd_flag_none,
2424 "<BSSID> = add a BSSID to the blacklist\n"
2425 "blacklist clear = clear the blacklist\n"
2426 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002427 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002428 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002429 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002430 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002431 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002432 cli_cmd_flag_none,
2433 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002434 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002435 cli_cmd_flag_none,
2436 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002437 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002438 cli_cmd_flag_none,
2439 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002440 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002441 cli_cmd_flag_none,
2442 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002443 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002444 cli_cmd_flag_none,
2445 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002446 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002447 cli_cmd_flag_none,
2448 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002449 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002450 cli_cmd_flag_sensitive,
2451 "<network id> <variable> <value> = set network variables (shows\n"
2452 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002453 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002454 cli_cmd_flag_none,
2455 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002456 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002457 cli_cmd_flag_none,
2458 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002459 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002460 cli_cmd_flag_none,
2461 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002462 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002463 cli_cmd_flag_none,
2464 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002465 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002466 cli_cmd_flag_sensitive,
2467 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002468 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002469 cli_cmd_flag_none,
2470 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002471 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002472 cli_cmd_flag_none,
2473 "= disconnect and wait for reassociate/reconnect command before\n"
2474 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002475 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 cli_cmd_flag_none,
2477 "= like reassociate, but only takes effect if already disconnected"
2478 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002479 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002480 cli_cmd_flag_none,
2481 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002482 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002483 cli_cmd_flag_none,
2484 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002485 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002486 cli_cmd_flag_none,
2487 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002488 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002489 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002490 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels> "
2491 "= get capabilies" },
2492 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002493 cli_cmd_flag_none,
2494 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002495 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002496 cli_cmd_flag_none,
2497 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002498 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002499 cli_cmd_flag_none,
2500 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2501 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2502 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002503 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002504 cli_cmd_flag_none,
2505 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002506 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507 cli_cmd_flag_none,
2508 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002509 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002510 cli_cmd_flag_none,
2511 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002512 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 cli_cmd_flag_none,
2514 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002515 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002516 cli_cmd_flag_none,
2517 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002518 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002519 cli_cmd_flag_none,
2520 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002521 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002522 cli_cmd_flag_none,
2523 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002524 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002525 cli_cmd_flag_none,
2526 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002527 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002528 cli_cmd_flag_none,
2529 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002530 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002531 cli_cmd_flag_none,
2532 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002533 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002534 cli_cmd_flag_sensitive,
2535 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2536 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002537 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002538 cli_cmd_flag_sensitive,
2539 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002540 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002541 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002542#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002543 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002544 cli_cmd_flag_none,
2545 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002546 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2547 cli_cmd_flag_none,
2548 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002549 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002550 cli_cmd_flag_none,
2551 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002552 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002553 cli_cmd_flag_sensitive,
2554 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002555 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2556 cli_cmd_flag_none,
2557 "<NDEF> <WPS> = create NFC handover request" },
2558 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2559 cli_cmd_flag_none,
2560 "<NDEF> <WPS> = create NFC handover select" },
2561 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2562 cli_cmd_flag_none,
2563 "<hexdump of payload> = report received NFC handover request" },
2564 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2565 cli_cmd_flag_none,
2566 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002567 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2568 cli_cmd_flag_none,
2569 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2570 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002571#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002572 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002573 cli_cmd_flag_sensitive,
2574 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002575 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002576 cli_cmd_flag_sensitive,
2577 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002578 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002579 cli_cmd_flag_none,
2580 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002581 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002582 cli_cmd_flag_none,
2583 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002584 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002585 cli_cmd_flag_sensitive,
2586 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002587 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002588 cli_cmd_flag_none,
2589 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002590 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002591 cli_cmd_flag_sensitive,
2592 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002593 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002594 cli_cmd_flag_none,
2595 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002596 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002597 cli_cmd_flag_sensitive,
2598 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002599#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002600 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002601 cli_cmd_flag_none,
2602 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2603#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002604 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002605 cli_cmd_flag_none,
2606 "<addr> = request RSN authentication with <addr> in IBSS" },
2607#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002608 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002609 cli_cmd_flag_none,
2610 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002611 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002612 cli_cmd_flag_none,
2613 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002614 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002615 cli_cmd_flag_none,
2616 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002617 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002618 cli_cmd_flag_none,
2619 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002621 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002622 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002623 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002625 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002626 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002627 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628 cli_cmd_flag_none,
2629 "<addr> = roam to the specified BSS" },
2630#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002631 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2632 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002633 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002634 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002635 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002636 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2637 cli_cmd_flag_none,
2638 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2639 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002640 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002641 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2642 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002643 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002644 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2645 "[ht40] = add a new P2P group (local end as GO)" },
2646 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2647 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002649 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002650 cli_cmd_flag_none,
2651 "= get the passphrase for a group (GO only)" },
2652 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002653 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002654 "<addr> <TLVs> = schedule service discovery request" },
2655 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002656 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002657 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002658 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002659 cli_cmd_flag_none,
2660 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002661 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002662 cli_cmd_flag_none,
2663 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002664 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002665 cli_cmd_flag_none,
2666 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002667 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002668 cli_cmd_flag_none,
2669 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002670 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002671 cli_cmd_flag_none,
2672 "<bonjour|upnp> <query|version> <response|service> = add a local "
2673 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002674 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002675 cli_cmd_flag_none,
2676 "<bonjour|upnp> <query|version> [|service] = remove a local "
2677 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002678 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002679 cli_cmd_flag_none,
2680 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002681 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002682 cli_cmd_flag_none,
2683 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002684 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002685 "[discovered] = list known (optionally, only fully discovered) P2P "
2686 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002687 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2688 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002689 "<address> = show information about known P2P peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002690 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002691 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002692 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002694 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002695 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002696 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2697 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002699 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2700 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002701 "[<duration> <interval>] [<duration> <interval>] = request GO "
2702 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002703 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2704 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002705 "[<period> <interval>] = set extended listen timing" },
2706#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002707#ifdef CONFIG_WIFI_DISPLAY
2708 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2709 cli_cmd_flag_none,
2710 "<subelem> [contents] = set Wi-Fi Display subelement" },
2711 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2712 cli_cmd_flag_none,
2713 "<subelem> = get Wi-Fi Display subelement" },
2714#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002715#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002716 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002717 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002718 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2719 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002720 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002721 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002722 cli_cmd_flag_none,
2723 "[auto] = perform Interworking network selection" },
2724 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002725 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002726 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002727 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2728 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002729 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002730 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2731 cli_cmd_flag_none,
2732 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2733 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2734 wpa_cli_complete_bss, cli_cmd_flag_none,
2735 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002736#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002737#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002738 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2739 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002740 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2741 },
2742 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002743 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002744 "<addr> <home realm> = get HS20 nai home realm list" },
2745#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002746 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2747 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002749 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002750 cli_cmd_flag_none,
2751 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002752 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002753 cli_cmd_flag_none,
2754 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002755 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002756 cli_cmd_flag_none,
2757 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002758 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002759 cli_cmd_flag_none,
2760 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002761 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002762 cli_cmd_flag_none,
2763 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002764 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2765 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002766 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002767#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002768 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002769 "[params] = Set or unset (if none) autoscan parameters" },
2770#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002771#ifdef CONFIG_WNM
2772 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2773 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
2774#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002775 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2776 "<params..> = Sent unprocessed command" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002777#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002778 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002779 cli_cmd_flag_none,
2780 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002781#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002782 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783};
2784
2785
2786/*
2787 * Prints command usage, lines are padded with the specified string.
2788 */
2789static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2790{
2791 char c;
2792 size_t n;
2793
2794 printf("%s%s ", pad, cmd->cmd);
2795 for (n = 0; (c = cmd->usage[n]); n++) {
2796 printf("%c", c);
2797 if (c == '\n')
2798 printf("%s", pad);
2799 }
2800 printf("\n");
2801}
2802
2803
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002804static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002805{
2806 int n;
2807 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002808 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2809 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2810 print_cmd_help(&wpa_cli_commands[n], " ");
2811 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002812}
2813
2814
2815static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2816{
2817 const char *c, *delim;
2818 int n;
2819 size_t len;
2820
2821 delim = os_strchr(cmd, ' ');
2822 if (delim)
2823 len = delim - cmd;
2824 else
2825 len = os_strlen(cmd);
2826
2827 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2828 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2829 return (wpa_cli_commands[n].flags &
2830 cli_cmd_flag_sensitive);
2831 }
2832 return 0;
2833}
2834
2835
2836static char ** wpa_list_cmd_list(void)
2837{
2838 char **res;
2839 int i, count;
2840
2841 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002842 res = os_calloc(count, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002843 if (res == NULL)
2844 return NULL;
2845
2846 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2847 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2848 if (res[i] == NULL)
2849 break;
2850 }
2851
2852 return res;
2853}
2854
2855
2856static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2857 int pos)
2858{
2859 int i;
2860
2861 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2862 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002863 if (wpa_cli_commands[i].completion)
2864 return wpa_cli_commands[i].completion(str,
2865 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002866 edit_clear_line();
2867 printf("\r%s\n", wpa_cli_commands[i].usage);
2868 edit_redraw();
2869 break;
2870 }
2871 }
2872
2873 return NULL;
2874}
2875
2876
2877static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2878{
2879 char **res;
2880 const char *end;
2881 char *cmd;
2882
2883 end = os_strchr(str, ' ');
2884 if (end == NULL || str + pos < end)
2885 return wpa_list_cmd_list();
2886
2887 cmd = os_malloc(pos + 1);
2888 if (cmd == NULL)
2889 return NULL;
2890 os_memcpy(cmd, str, pos);
2891 cmd[end - str] = '\0';
2892 res = wpa_cli_cmd_completion(cmd, str, pos);
2893 os_free(cmd);
2894 return res;
2895}
2896
2897
2898static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2899{
2900 struct wpa_cli_cmd *cmd, *match = NULL;
2901 int count;
2902 int ret = 0;
2903
2904 count = 0;
2905 cmd = wpa_cli_commands;
2906 while (cmd->cmd) {
2907 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2908 {
2909 match = cmd;
2910 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2911 /* we have an exact match */
2912 count = 1;
2913 break;
2914 }
2915 count++;
2916 }
2917 cmd++;
2918 }
2919
2920 if (count > 1) {
2921 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2922 cmd = wpa_cli_commands;
2923 while (cmd->cmd) {
2924 if (os_strncasecmp(cmd->cmd, argv[0],
2925 os_strlen(argv[0])) == 0) {
2926 printf(" %s", cmd->cmd);
2927 }
2928 cmd++;
2929 }
2930 printf("\n");
2931 ret = 1;
2932 } else if (count == 0) {
2933 printf("Unknown command '%s'\n", argv[0]);
2934 ret = 1;
2935 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07002936#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
2937 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
2938 redirect_interface = os_strdup(argv[1]);
2939 ret = match->handler(ctrl, argc - 2, &argv[2]);
2940 }
2941 else
2942#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002943 ret = match->handler(ctrl, argc - 1, &argv[1]);
2944 }
2945
2946 return ret;
2947}
2948
2949
2950static int str_match(const char *a, const char *b)
2951{
2952 return os_strncmp(a, b, os_strlen(b)) == 0;
2953}
2954
2955
2956static int wpa_cli_exec(const char *program, const char *arg1,
2957 const char *arg2)
2958{
2959 char *cmd;
2960 size_t len;
2961 int res;
2962 int ret = 0;
2963
2964 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2965 cmd = os_malloc(len);
2966 if (cmd == NULL)
2967 return -1;
2968 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2969 if (res < 0 || (size_t) res >= len) {
2970 os_free(cmd);
2971 return -1;
2972 }
2973 cmd[len - 1] = '\0';
2974#ifndef _WIN32_WCE
2975 if (system(cmd) < 0)
2976 ret = -1;
2977#endif /* _WIN32_WCE */
2978 os_free(cmd);
2979
2980 return ret;
2981}
2982
2983
2984static void wpa_cli_action_process(const char *msg)
2985{
2986 const char *pos;
2987 char *copy = NULL, *id, *pos2;
2988
2989 pos = msg;
2990 if (*pos == '<') {
2991 /* skip priority */
2992 pos = os_strchr(pos, '>');
2993 if (pos)
2994 pos++;
2995 else
2996 pos = msg;
2997 }
2998
2999 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3000 int new_id = -1;
3001 os_unsetenv("WPA_ID");
3002 os_unsetenv("WPA_ID_STR");
3003 os_unsetenv("WPA_CTRL_DIR");
3004
3005 pos = os_strstr(pos, "[id=");
3006 if (pos)
3007 copy = os_strdup(pos + 4);
3008
3009 if (copy) {
3010 pos2 = id = copy;
3011 while (*pos2 && *pos2 != ' ')
3012 pos2++;
3013 *pos2++ = '\0';
3014 new_id = atoi(id);
3015 os_setenv("WPA_ID", id, 1);
3016 while (*pos2 && *pos2 != '=')
3017 pos2++;
3018 if (*pos2 == '=')
3019 pos2++;
3020 id = pos2;
3021 while (*pos2 && *pos2 != ']')
3022 pos2++;
3023 *pos2 = '\0';
3024 os_setenv("WPA_ID_STR", id, 1);
3025 os_free(copy);
3026 }
3027
3028 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3029
3030 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3031 wpa_cli_connected = 1;
3032 wpa_cli_last_id = new_id;
3033 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3034 }
3035 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3036 if (wpa_cli_connected) {
3037 wpa_cli_connected = 0;
3038 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3039 }
3040 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3041 wpa_cli_exec(action_file, ctrl_ifname, pos);
3042 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3043 wpa_cli_exec(action_file, ctrl_ifname, pos);
3044 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3045 wpa_cli_exec(action_file, ctrl_ifname, pos);
3046 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3047 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003048 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3049 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003050 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3051 wpa_cli_exec(action_file, ctrl_ifname, pos);
3052 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3053 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003054 } else if (str_match(pos, AP_STA_CONNECTED)) {
3055 wpa_cli_exec(action_file, ctrl_ifname, pos);
3056 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3057 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003058 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3059 printf("wpa_supplicant is terminating - stop monitoring\n");
3060 wpa_cli_quit = 1;
3061 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003062}
3063
3064
3065#ifndef CONFIG_ANSI_C_EXTRA
3066static void wpa_cli_action_cb(char *msg, size_t len)
3067{
3068 wpa_cli_action_process(msg);
3069}
3070#endif /* CONFIG_ANSI_C_EXTRA */
3071
3072
3073static void wpa_cli_reconnect(void)
3074{
3075 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003076 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3077 return;
3078
3079 if (interactive) {
3080 edit_clear_line();
3081 printf("\rConnection to wpa_supplicant re-established\n");
3082 edit_redraw();
3083 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003084}
3085
3086
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003087static void cli_event(const char *str)
3088{
3089 const char *start, *s;
3090
3091 start = os_strchr(str, '>');
3092 if (start == NULL)
3093 return;
3094
3095 start++;
3096
3097 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3098 s = os_strchr(start, ' ');
3099 if (s == NULL)
3100 return;
3101 s = os_strchr(s + 1, ' ');
3102 if (s == NULL)
3103 return;
3104 cli_txt_list_add(&bsses, s + 1);
3105 return;
3106 }
3107
3108 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3109 s = os_strchr(start, ' ');
3110 if (s == NULL)
3111 return;
3112 s = os_strchr(s + 1, ' ');
3113 if (s == NULL)
3114 return;
3115 cli_txt_list_del_addr(&bsses, s + 1);
3116 return;
3117 }
3118
3119#ifdef CONFIG_P2P
3120 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3121 s = os_strstr(start, " p2p_dev_addr=");
3122 if (s == NULL)
3123 return;
3124 cli_txt_list_add_addr(&p2p_peers, s + 14);
3125 return;
3126 }
3127
3128 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3129 s = os_strstr(start, " p2p_dev_addr=");
3130 if (s == NULL)
3131 return;
3132 cli_txt_list_del_addr(&p2p_peers, s + 14);
3133 return;
3134 }
3135
3136 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3137 s = os_strchr(start, ' ');
3138 if (s == NULL)
3139 return;
3140 cli_txt_list_add_word(&p2p_groups, s + 1);
3141 return;
3142 }
3143
3144 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3145 s = os_strchr(start, ' ');
3146 if (s == NULL)
3147 return;
3148 cli_txt_list_del_word(&p2p_groups, s + 1);
3149 return;
3150 }
3151#endif /* CONFIG_P2P */
3152}
3153
3154
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003155static int check_terminating(const char *msg)
3156{
3157 const char *pos = msg;
3158
3159 if (*pos == '<') {
3160 /* skip priority */
3161 pos = os_strchr(pos, '>');
3162 if (pos)
3163 pos++;
3164 else
3165 pos = msg;
3166 }
3167
3168 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3169 edit_clear_line();
3170 printf("\rConnection to wpa_supplicant lost - trying to "
3171 "reconnect\n");
3172 edit_redraw();
3173 wpa_cli_attached = 0;
3174 wpa_cli_close_connection();
3175 return 1;
3176 }
3177
3178 return 0;
3179}
3180
3181
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003182static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3183{
3184 if (ctrl_conn == NULL) {
3185 wpa_cli_reconnect();
3186 return;
3187 }
3188 while (wpa_ctrl_pending(ctrl) > 0) {
3189 char buf[256];
3190 size_t len = sizeof(buf) - 1;
3191 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3192 buf[len] = '\0';
3193 if (action_monitor)
3194 wpa_cli_action_process(buf);
3195 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003196 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003197 if (wpa_cli_show_event(buf)) {
3198 edit_clear_line();
3199 printf("\r%s\n", buf);
3200 edit_redraw();
3201 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003202
3203 if (interactive && check_terminating(buf) > 0)
3204 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003205 }
3206 } else {
3207 printf("Could not read pending message.\n");
3208 break;
3209 }
3210 }
3211
3212 if (wpa_ctrl_pending(ctrl) < 0) {
3213 printf("Connection to wpa_supplicant lost - trying to "
3214 "reconnect\n");
3215 wpa_cli_reconnect();
3216 }
3217}
3218
3219#define max_args 10
3220
3221static int tokenize_cmd(char *cmd, char *argv[])
3222{
3223 char *pos;
3224 int argc = 0;
3225
3226 pos = cmd;
3227 for (;;) {
3228 while (*pos == ' ')
3229 pos++;
3230 if (*pos == '\0')
3231 break;
3232 argv[argc] = pos;
3233 argc++;
3234 if (argc == max_args)
3235 break;
3236 if (*pos == '"') {
3237 char *pos2 = os_strrchr(pos, '"');
3238 if (pos2)
3239 pos = pos2 + 1;
3240 }
3241 while (*pos != '\0' && *pos != ' ')
3242 pos++;
3243 if (*pos == ' ')
3244 *pos++ = '\0';
3245 }
3246
3247 return argc;
3248}
3249
3250
3251static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3252{
3253 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3254 printf("Connection to wpa_supplicant lost - trying to "
3255 "reconnect\n");
3256 wpa_cli_close_connection();
3257 }
3258 if (!ctrl_conn)
3259 wpa_cli_reconnect();
3260 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3261}
3262
3263
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003264static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3265{
3266 wpa_cli_recv_pending(mon_conn, 0);
3267}
3268
3269
3270static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3271{
3272 char *argv[max_args];
3273 int argc;
3274 argc = tokenize_cmd(cmd, argv);
3275 if (argc)
3276 wpa_request(ctrl_conn, argc, argv);
3277}
3278
3279
3280static void wpa_cli_edit_eof_cb(void *ctx)
3281{
3282 eloop_terminate();
3283}
3284
3285
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003286static int warning_displayed = 0;
3287static char *hfile = NULL;
3288static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003289
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003290static void start_edit(void)
3291{
3292 char *home;
3293 char *ps = NULL;
3294
3295#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3296 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3297#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003298
3299 home = getenv("HOME");
3300 if (home) {
3301 const char *fname = ".wpa_cli_history";
3302 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3303 hfile = os_malloc(hfile_len);
3304 if (hfile)
3305 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3306 }
3307
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003308 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3309 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3310 eloop_terminate();
3311 return;
3312 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003313
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003314 edit_started = 1;
3315 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3316}
3317
3318
3319static void try_connection(void *eloop_ctx, void *timeout_ctx)
3320{
3321 if (ctrl_ifname == NULL)
3322 ctrl_ifname = wpa_cli_get_default_ifname();
3323
3324 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3325 if (!warning_displayed) {
3326 printf("Could not connect to wpa_supplicant: "
3327 "%s - re-trying\n", ctrl_ifname);
3328 warning_displayed = 1;
3329 }
3330 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3331 return;
3332 }
3333
3334 if (warning_displayed)
3335 printf("Connection established.\n");
3336
3337 start_edit();
3338}
3339
3340
3341static void wpa_cli_interactive(void)
3342{
3343 printf("\nInteractive mode\n\n");
3344
3345 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003346 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003347 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003348
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003349 cli_txt_list_flush(&p2p_peers);
3350 cli_txt_list_flush(&p2p_groups);
3351 cli_txt_list_flush(&bsses);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003352 if (edit_started)
3353 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003354 os_free(hfile);
3355 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3356 wpa_cli_close_connection();
3357}
3358
3359
3360static void wpa_cli_action(struct wpa_ctrl *ctrl)
3361{
3362#ifdef CONFIG_ANSI_C_EXTRA
3363 /* TODO: ANSI C version(?) */
3364 printf("Action processing not supported in ANSI C build.\n");
3365#else /* CONFIG_ANSI_C_EXTRA */
3366 fd_set rfds;
3367 int fd, res;
3368 struct timeval tv;
3369 char buf[256]; /* note: large enough to fit in unsolicited messages */
3370 size_t len;
3371
3372 fd = wpa_ctrl_get_fd(ctrl);
3373
3374 while (!wpa_cli_quit) {
3375 FD_ZERO(&rfds);
3376 FD_SET(fd, &rfds);
3377 tv.tv_sec = ping_interval;
3378 tv.tv_usec = 0;
3379 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3380 if (res < 0 && errno != EINTR) {
3381 perror("select");
3382 break;
3383 }
3384
3385 if (FD_ISSET(fd, &rfds))
3386 wpa_cli_recv_pending(ctrl, 1);
3387 else {
3388 /* verify that connection is still working */
3389 len = sizeof(buf) - 1;
3390 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3391 wpa_cli_action_cb) < 0 ||
3392 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3393 printf("wpa_supplicant did not reply to PING "
3394 "command - exiting\n");
3395 break;
3396 }
3397 }
3398 }
3399#endif /* CONFIG_ANSI_C_EXTRA */
3400}
3401
3402
3403static void wpa_cli_cleanup(void)
3404{
3405 wpa_cli_close_connection();
3406 if (pid_file)
3407 os_daemonize_terminate(pid_file);
3408
3409 os_program_deinit();
3410}
3411
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003412
3413static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003414{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003415 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003416}
3417
3418
3419static char * wpa_cli_get_default_ifname(void)
3420{
3421 char *ifname = NULL;
3422
3423#ifdef CONFIG_CTRL_IFACE_UNIX
3424 struct dirent *dent;
3425 DIR *dir = opendir(ctrl_iface_dir);
3426 if (!dir) {
3427#ifdef ANDROID
3428 char ifprop[PROPERTY_VALUE_MAX];
3429 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3430 ifname = os_strdup(ifprop);
3431 printf("Using interface '%s'\n", ifname);
3432 return ifname;
3433 }
3434#endif /* ANDROID */
3435 return NULL;
3436 }
3437 while ((dent = readdir(dir))) {
3438#ifdef _DIRENT_HAVE_D_TYPE
3439 /*
3440 * Skip the file if it is not a socket. Also accept
3441 * DT_UNKNOWN (0) in case the C library or underlying
3442 * file system does not support d_type.
3443 */
3444 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3445 continue;
3446#endif /* _DIRENT_HAVE_D_TYPE */
3447 if (os_strcmp(dent->d_name, ".") == 0 ||
3448 os_strcmp(dent->d_name, "..") == 0)
3449 continue;
3450 printf("Selected interface '%s'\n", dent->d_name);
3451 ifname = os_strdup(dent->d_name);
3452 break;
3453 }
3454 closedir(dir);
3455#endif /* CONFIG_CTRL_IFACE_UNIX */
3456
3457#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003458#ifdef ANDROID
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -07003459 char buf[4096], *pos;
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003460#else
3461 char buf[2048], *pos;
3462#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003463 size_t len;
3464 struct wpa_ctrl *ctrl;
3465 int ret;
3466
3467 ctrl = wpa_ctrl_open(NULL);
3468 if (ctrl == NULL)
3469 return NULL;
3470
3471 len = sizeof(buf) - 1;
3472 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3473 if (ret >= 0) {
3474 buf[len] = '\0';
3475 pos = os_strchr(buf, '\n');
3476 if (pos)
3477 *pos = '\0';
3478 ifname = os_strdup(buf);
3479 }
3480 wpa_ctrl_close(ctrl);
3481#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3482
3483 return ifname;
3484}
3485
3486
3487int main(int argc, char *argv[])
3488{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003489 int c;
3490 int daemonize = 0;
3491 int ret = 0;
3492 const char *global = NULL;
3493
3494 if (os_program_init())
3495 return -1;
3496
3497 for (;;) {
3498 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3499 if (c < 0)
3500 break;
3501 switch (c) {
3502 case 'a':
3503 action_file = optarg;
3504 break;
3505 case 'B':
3506 daemonize = 1;
3507 break;
3508 case 'g':
3509 global = optarg;
3510 break;
3511 case 'G':
3512 ping_interval = atoi(optarg);
3513 break;
3514 case 'h':
3515 usage();
3516 return 0;
3517 case 'v':
3518 printf("%s\n", wpa_cli_version);
3519 return 0;
3520 case 'i':
3521 os_free(ctrl_ifname);
3522 ctrl_ifname = os_strdup(optarg);
3523 break;
3524 case 'p':
3525 ctrl_iface_dir = optarg;
3526 break;
3527 case 'P':
3528 pid_file = optarg;
3529 break;
3530 default:
3531 usage();
3532 return -1;
3533 }
3534 }
3535
3536 interactive = (argc == optind) && (action_file == NULL);
3537
3538 if (interactive)
3539 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3540
3541 if (eloop_init())
3542 return -1;
3543
3544 if (global) {
3545#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3546 ctrl_conn = wpa_ctrl_open(NULL);
3547#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3548 ctrl_conn = wpa_ctrl_open(global);
3549#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3550 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003551 fprintf(stderr, "Failed to connect to wpa_supplicant "
3552 "global interface: %s error: %s\n",
3553 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003554 return -1;
3555 }
3556 }
3557
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003558 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003559
3560 if (ctrl_ifname == NULL)
3561 ctrl_ifname = wpa_cli_get_default_ifname();
3562
3563 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003564 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003565 } else {
3566 if (!global &&
3567 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003568 fprintf(stderr, "Failed to connect to non-global "
3569 "ctrl_ifname: %s error: %s\n",
3570 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003571 return -1;
3572 }
3573
3574 if (action_file) {
3575 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3576 wpa_cli_attached = 1;
3577 } else {
3578 printf("Warning: Failed to attach to "
3579 "wpa_supplicant.\n");
3580 return -1;
3581 }
3582 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003583
3584 if (daemonize && os_daemonize(pid_file))
3585 return -1;
3586
3587 if (action_file)
3588 wpa_cli_action(ctrl_conn);
3589 else
3590 ret = wpa_request(ctrl_conn, argc - optind,
3591 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003592 }
3593
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003594 os_free(ctrl_ifname);
3595 eloop_destroy();
3596 wpa_cli_cleanup();
3597
3598 return ret;
3599}
3600
3601#else /* CONFIG_CTRL_IFACE */
3602int main(int argc, char *argv[])
3603{
3604 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3605 return -1;
3606}
3607#endif /* CONFIG_CTRL_IFACE */