blob: fe30b41458bcb2c923c9fade9d6be3aca99433c1 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003 * Copyright (c) 2004-2013, 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 Shmidtfb79edc2014-01-10 10:45:54 -080031"Copyright (c) 2004-2014, 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;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070073static int wpa_cli_connected = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074static 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 Shmidtf7e0a992013-05-23 11:03:10 -070084static char *ifname_prefix = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070085
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080086struct cli_txt_entry {
87 struct dl_list list;
88 char *txt;
89};
90
91static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
92static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
93static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070094static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070097static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070098static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070099static void wpa_cli_close_connection(void);
100static char * wpa_cli_get_default_ifname(void);
101static char ** wpa_list_cmd_list(void);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700102
103
104static void usage(void)
105{
106 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107 "[-a<action file>] \\\n"
108 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
109 "[command..]\n"
110 " -h = help (show this usage text)\n"
111 " -v = shown version information\n"
112 " -a = run in daemon mode executing the action file based on "
113 "events from\n"
114 " wpa_supplicant\n"
115 " -B = run a daemon in the background\n"
116 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
117 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700118 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700119}
120
121
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800122static void cli_txt_list_free(struct cli_txt_entry *e)
123{
124 dl_list_del(&e->list);
125 os_free(e->txt);
126 os_free(e);
127}
128
129
130static void cli_txt_list_flush(struct dl_list *list)
131{
132 struct cli_txt_entry *e;
133 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
134 cli_txt_list_free(e);
135}
136
137
138static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
139 const char *txt)
140{
141 struct cli_txt_entry *e;
142 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
143 if (os_strcmp(e->txt, txt) == 0)
144 return e;
145 }
146 return NULL;
147}
148
149
150static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
151{
152 struct cli_txt_entry *e;
153 e = cli_txt_list_get(txt_list, txt);
154 if (e)
155 cli_txt_list_free(e);
156}
157
158
159static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
160{
161 u8 addr[ETH_ALEN];
162 char buf[18];
163 if (hwaddr_aton(txt, addr) < 0)
164 return;
165 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
166 cli_txt_list_del(txt_list, buf);
167}
168
169
170#ifdef CONFIG_P2P
171static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
172{
173 const char *end;
174 char *buf;
175 end = os_strchr(txt, ' ');
176 if (end == NULL)
177 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700178 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800179 if (buf == NULL)
180 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800181 cli_txt_list_del(txt_list, buf);
182 os_free(buf);
183}
184#endif /* CONFIG_P2P */
185
186
187static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
188{
189 struct cli_txt_entry *e;
190 e = cli_txt_list_get(txt_list, txt);
191 if (e)
192 return 0;
193 e = os_zalloc(sizeof(*e));
194 if (e == NULL)
195 return -1;
196 e->txt = os_strdup(txt);
197 if (e->txt == NULL) {
198 os_free(e);
199 return -1;
200 }
201 dl_list_add(txt_list, &e->list);
202 return 0;
203}
204
205
206#ifdef CONFIG_P2P
207static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
208{
209 u8 addr[ETH_ALEN];
210 char buf[18];
211 if (hwaddr_aton(txt, addr) < 0)
212 return -1;
213 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
214 return cli_txt_list_add(txt_list, buf);
215}
216
217
218static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
219{
220 const char *end;
221 char *buf;
222 int ret;
223 end = os_strchr(txt, ' ');
224 if (end == NULL)
225 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700226 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800227 if (buf == NULL)
228 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800229 ret = cli_txt_list_add(txt_list, buf);
230 os_free(buf);
231 return ret;
232}
233#endif /* CONFIG_P2P */
234
235
236static char ** cli_txt_list_array(struct dl_list *txt_list)
237{
238 unsigned int i, count = dl_list_len(txt_list);
239 char **res;
240 struct cli_txt_entry *e;
241
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700242 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800243 if (res == NULL)
244 return NULL;
245
246 i = 0;
247 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
248 res[i] = os_strdup(e->txt);
249 if (res[i] == NULL)
250 break;
251 i++;
252 }
253
254 return res;
255}
256
257
258static int get_cmd_arg_num(const char *str, int pos)
259{
260 int arg = 0, i;
261
262 for (i = 0; i <= pos; i++) {
263 if (str[i] != ' ') {
264 arg++;
265 while (i <= pos && str[i] != ' ')
266 i++;
267 }
268 }
269
270 if (arg > 0)
271 arg--;
272 return arg;
273}
274
275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276static int str_starts(const char *src, const char *match)
277{
278 return os_strncmp(src, match, os_strlen(match)) == 0;
279}
280
281
282static int wpa_cli_show_event(const char *event)
283{
284 const char *start;
285
286 start = os_strchr(event, '>');
287 if (start == NULL)
288 return 1;
289
290 start++;
291 /*
292 * Skip BSS added/removed events since they can be relatively frequent
293 * and are likely of not much use for an interactive user.
294 */
295 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
296 str_starts(start, WPA_EVENT_BSS_REMOVED))
297 return 0;
298
299 return 1;
300}
301
302
303static int wpa_cli_open_connection(const char *ifname, int attach)
304{
305#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
306 ctrl_conn = wpa_ctrl_open(ifname);
307 if (ctrl_conn == NULL)
308 return -1;
309
310 if (attach && interactive)
311 mon_conn = wpa_ctrl_open(ifname);
312 else
313 mon_conn = NULL;
314#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
315 char *cfile = NULL;
316 int flen, res;
317
318 if (ifname == NULL)
319 return -1;
320
321#ifdef ANDROID
322 if (access(ctrl_iface_dir, F_OK) < 0) {
323 cfile = os_strdup(ifname);
324 if (cfile == NULL)
325 return -1;
326 }
327#endif /* ANDROID */
328
329 if (cfile == NULL) {
330 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
331 cfile = os_malloc(flen);
332 if (cfile == NULL)
333 return -1;
334 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
335 ifname);
336 if (res < 0 || res >= flen) {
337 os_free(cfile);
338 return -1;
339 }
340 }
341
342 ctrl_conn = wpa_ctrl_open(cfile);
343 if (ctrl_conn == NULL) {
344 os_free(cfile);
345 return -1;
346 }
347
348 if (attach && interactive)
349 mon_conn = wpa_ctrl_open(cfile);
350 else
351 mon_conn = NULL;
352 os_free(cfile);
353#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
354
355 if (mon_conn) {
356 if (wpa_ctrl_attach(mon_conn) == 0) {
357 wpa_cli_attached = 1;
358 if (interactive)
359 eloop_register_read_sock(
360 wpa_ctrl_get_fd(mon_conn),
361 wpa_cli_mon_receive, NULL, NULL);
362 } else {
363 printf("Warning: Failed to attach to "
364 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700365 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700366 return -1;
367 }
368 }
369
370 return 0;
371}
372
373
374static void wpa_cli_close_connection(void)
375{
376 if (ctrl_conn == NULL)
377 return;
378
379 if (wpa_cli_attached) {
380 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
381 wpa_cli_attached = 0;
382 }
383 wpa_ctrl_close(ctrl_conn);
384 ctrl_conn = NULL;
385 if (mon_conn) {
386 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
387 wpa_ctrl_close(mon_conn);
388 mon_conn = NULL;
389 }
390}
391
392
393static void wpa_cli_msg_cb(char *msg, size_t len)
394{
395 printf("%s\n", msg);
396}
397
398
399static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
400{
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700401 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700402 size_t len;
403 int ret;
404
405 if (ctrl_conn == NULL) {
406 printf("Not connected to wpa_supplicant - command dropped.\n");
407 return -1;
408 }
Dmitry Shmidtd3e385e2013-06-05 11:06:13 -0700409 if (ifname_prefix) {
410 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
411 ifname_prefix, cmd);
412 buf[sizeof(buf) - 1] = '\0';
413 cmd = buf;
414 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415 len = sizeof(buf) - 1;
416 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
417 wpa_cli_msg_cb);
418 if (ret == -2) {
419 printf("'%s' command timed out.\n", cmd);
420 return -2;
421 } else if (ret < 0) {
422 printf("'%s' command failed.\n", cmd);
423 return -1;
424 }
425 if (print) {
426 buf[len] = '\0';
427 printf("%s", buf);
428 if (interactive && len > 0 && buf[len - 1] != '\n')
429 printf("\n");
430 }
431 return 0;
432}
433
434
435static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
436{
437 return _wpa_ctrl_command(ctrl, cmd, 1);
438}
439
440
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700441static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
442 char *argv[])
443{
444 int i, res;
445 char *pos, *end;
446
447 pos = buf;
448 end = buf + buflen;
449
450 res = os_snprintf(pos, end - pos, "%s", cmd);
451 if (res < 0 || res >= end - pos)
452 goto fail;
453 pos += res;
454
455 for (i = 0; i < argc; i++) {
456 res = os_snprintf(pos, end - pos, " %s", argv[i]);
457 if (res < 0 || res >= end - pos)
458 goto fail;
459 pos += res;
460 }
461
462 buf[buflen - 1] = '\0';
463 return 0;
464
465fail:
466 printf("Too long command\n");
467 return -1;
468}
469
470
471static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
472 int argc, char *argv[])
473{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700474 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700475 if (argc < min_args) {
476 printf("Invalid %s command - at least %d argument%s "
477 "required.\n", cmd, min_args,
478 min_args > 1 ? "s are" : " is");
479 return -1;
480 }
481 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
482 return -1;
483 return wpa_ctrl_command(ctrl, buf);
484}
485
486
487static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
488{
489 return wpa_ctrl_command(ctrl, "IFNAME");
490}
491
492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700493static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
494{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800495 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
496 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
497 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
498 return wpa_ctrl_command(ctrl, "STATUS-WPS");
Dmitry Shmidt56052862013-10-04 10:23:25 -0700499 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
500 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800501 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502}
503
504
505static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
506{
507 return wpa_ctrl_command(ctrl, "PING");
508}
509
510
511static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
513 return wpa_ctrl_command(ctrl, "RELOG");
514}
515
516
517static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
518{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700519 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700520}
521
522
523static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
524{
525 return wpa_ctrl_command(ctrl, "MIB");
526}
527
528
529static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
530{
531 return wpa_ctrl_command(ctrl, "PMKSA");
532}
533
534
Dmitry Shmidt661b4f72014-09-29 14:58:27 -0700535static int wpa_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
536 char *argv[])
537{
538 return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
539}
540
541
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700542static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
543{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700544 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700545 return 0;
546}
547
548
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700549static char ** wpa_cli_complete_help(const char *str, int pos)
550{
551 int arg = get_cmd_arg_num(str, pos);
552 char **res = NULL;
553
554 switch (arg) {
555 case 1:
556 res = wpa_list_cmd_list();
557 break;
558 }
559
560 return res;
561}
562
563
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700564static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
565{
566 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
567 return 0;
568}
569
570
571static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
572{
573 wpa_cli_quit = 1;
574 if (interactive)
575 eloop_terminate();
576 return 0;
577}
578
579
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700580static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
581{
582 char cmd[256];
583 int res;
584
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700585 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800586 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700587 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
588 printf("Too long SET command.\n");
589 return -1;
590 }
591 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700592 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700593
594 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
595}
596
597
598static char ** wpa_cli_complete_set(const char *str, int pos)
599{
600 int arg = get_cmd_arg_num(str, pos);
601 const char *fields[] = {
602 /* runtime values */
603 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
604 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
605 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
606 "wps_fragment_size", "wps_version_number", "ampdu",
607 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
608 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
609 "no_keep_alive",
610 /* global configuration parameters */
611 "eapol_version", "ap_scan", "disable_scan_offload",
612 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
613 "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
614 "driver_param", "dot11RSNAConfigPMKLifetime",
615 "dot11RSNAConfigPMKReauthThreshold",
616 "dot11RSNAConfigSATimeout",
617 "update_config", "load_dynamic_eap", "uuid", "device_name",
618 "manufacturer", "model_name", "model_number", "serial_number",
619 "device_type", "os_version", "config_methods",
620 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
621 "p2p_listen_reg_class", "p2p_listen_channel",
622 "p2p_oper_reg_class", "p2p_oper_channel",
623 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
624 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700625 "p2p_no_go_freq",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700626 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700627 "p2p_go_vht",
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700628 "p2p_ignore_shared_freq", "country", "bss_max_count",
629 "bss_expiration_age", "bss_expiration_scan_count",
630 "filter_ssids", "filter_rssi", "max_num_sta",
631 "disassoc_low_ack", "hs20", "interworking", "hessid",
632 "access_network_type", "pbc_in_m1", "autoscan",
633 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
634 "wps_nfc_dev_pw", "ext_password_backend",
635 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
636 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
Dmitry Shmidt97672262014-02-03 13:02:54 -0800637 "ignore_old_scan_res", "freq_list", "external_sim",
Dmitry Shmidt09f57ba2014-06-10 16:07:13 -0700638 "tdls_external_control", "p2p_search_delay"
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700639 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -0700640 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700641
642 if (arg == 1) {
643 char **res = os_calloc(num_fields + 1, sizeof(char *));
644 if (res == NULL)
645 return NULL;
646 for (i = 0; i < num_fields; i++) {
647 res[i] = os_strdup(fields[i]);
648 if (res[i] == NULL)
649 return res;
650 }
651 return res;
652 }
653
654 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
655 return cli_txt_list_array(&bsses);
656
657 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700658}
659
660
661static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
662{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700663 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700664}
665
666
667static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
668{
669 return wpa_ctrl_command(ctrl, "LOGOFF");
670}
671
672
673static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
674{
675 return wpa_ctrl_command(ctrl, "LOGON");
676}
677
678
679static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
680 char *argv[])
681{
682 return wpa_ctrl_command(ctrl, "REASSOCIATE");
683}
684
685
Dmitry Shmidt98660862014-03-11 17:26:21 -0700686static int wpa_cli_cmd_reattach(struct wpa_ctrl *ctrl, int argc, char *argv[])
687{
688 return wpa_ctrl_command(ctrl, "REATTACH");
689}
690
691
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700692static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
693 char *argv[])
694{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700695 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700696}
697
698
699static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
700{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700701 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700702}
703
704
705static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
706 char *argv[])
707{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700708 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700709}
710
711
712static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
713 char *argv[])
714{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700715 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700716}
717
718
719static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
720 char *argv[])
721{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700722 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700723}
724
725
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700726static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
727{
728 char cmd[256];
729 int res;
730
731 if (argc < 1)
732 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
733 else
734 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
735 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
736 printf("Too long BSS_FLUSH command.\n");
737 return -1;
738 }
739 return wpa_ctrl_command(ctrl, cmd);
740}
741
742
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
744 char *argv[])
745{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700746 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700747}
748
749
750static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
751{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700752 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700753}
754
755
756static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
757{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700758 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700759}
760
761
762static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
763{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700764 if (argc == 0) {
765 printf("Invalid WPS_PIN command: need one or two arguments:\n"
766 "- BSSID: use 'any' to select any\n"
767 "- PIN: optional, used only with devices that have no "
768 "display\n");
769 return -1;
770 }
771
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700772 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700773}
774
775
776static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
777 char *argv[])
778{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700779 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700780}
781
782
783static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
784 char *argv[])
785{
786 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
787}
788
789
Dmitry Shmidt04949592012-07-19 12:16:46 -0700790#ifdef CONFIG_WPS_NFC
791
792static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
793{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700794 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700795}
796
797
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800798static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
799 char *argv[])
800{
801 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
802}
803
804
Dmitry Shmidt04949592012-07-19 12:16:46 -0700805static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
806 char *argv[])
807{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700808 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700809}
810
811
812static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
813 char *argv[])
814{
815 int ret;
816 char *buf;
817 size_t buflen;
818
819 if (argc != 1) {
820 printf("Invalid 'wps_nfc_tag_read' command - one argument "
821 "is required.\n");
822 return -1;
823 }
824
825 buflen = 18 + os_strlen(argv[0]);
826 buf = os_malloc(buflen);
827 if (buf == NULL)
828 return -1;
829 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
830
831 ret = wpa_ctrl_command(ctrl, buf);
832 os_free(buf);
833
834 return ret;
835}
836
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800837
838static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
839 char *argv[])
840{
841 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
842}
843
844
845static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
846 char *argv[])
847{
848 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
849}
850
851
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800852static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
853 char *argv[])
854{
855 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
856}
857
Dmitry Shmidt04949592012-07-19 12:16:46 -0700858#endif /* CONFIG_WPS_NFC */
859
860
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700861static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
862{
863 char cmd[256];
864 int res;
865
866 if (argc == 2)
867 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
868 argv[0], argv[1]);
869 else if (argc == 5 || argc == 6) {
870 char ssid_hex[2 * 32 + 1];
871 char key_hex[2 * 64 + 1];
872 int i;
873
874 ssid_hex[0] = '\0';
875 for (i = 0; i < 32; i++) {
876 if (argv[2][i] == '\0')
877 break;
878 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
879 }
880
881 key_hex[0] = '\0';
882 if (argc == 6) {
883 for (i = 0; i < 64; i++) {
884 if (argv[5][i] == '\0')
885 break;
886 os_snprintf(&key_hex[i * 2], 3, "%02x",
887 argv[5][i]);
888 }
889 }
890
891 res = os_snprintf(cmd, sizeof(cmd),
892 "WPS_REG %s %s %s %s %s %s",
893 argv[0], argv[1], ssid_hex, argv[3], argv[4],
894 key_hex);
895 } else {
896 printf("Invalid WPS_REG command: need two arguments:\n"
897 "- BSSID of the target AP\n"
898 "- AP PIN\n");
899 printf("Alternatively, six arguments can be used to "
900 "reconfigure the AP:\n"
901 "- BSSID of the target AP\n"
902 "- AP PIN\n"
903 "- new SSID\n"
904 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
905 "- new encr (NONE, WEP, TKIP, CCMP)\n"
906 "- new key\n");
907 return -1;
908 }
909
910 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
911 printf("Too long WPS_REG command.\n");
912 return -1;
913 }
914 return wpa_ctrl_command(ctrl, cmd);
915}
916
917
918static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
919 char *argv[])
920{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700921 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700922}
923
924
925static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
926 char *argv[])
927{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700928 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700929}
930
931
932static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
933 char *argv[])
934{
935 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
936
937}
938
939
940static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
941 char *argv[])
942{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700943 if (argc < 2) {
944 printf("Invalid WPS_ER_PIN command: need at least two "
945 "arguments:\n"
946 "- UUID: use 'any' to select any\n"
947 "- PIN: Enrollee PIN\n"
948 "optional: - Enrollee MAC address\n");
949 return -1;
950 }
951
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700952 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700953}
954
955
956static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
957 char *argv[])
958{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700959 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700960}
961
962
963static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
964 char *argv[])
965{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700966 if (argc != 2) {
967 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
968 "- UUID: specify which AP to use\n"
969 "- PIN: AP PIN\n");
970 return -1;
971 }
972
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700973 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700974}
975
976
977static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
978 char *argv[])
979{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700980 if (argc != 2) {
981 printf("Invalid WPS_ER_SET_CONFIG command: need two "
982 "arguments:\n"
983 "- UUID: specify which AP to use\n"
984 "- Network configuration id\n");
985 return -1;
986 }
987
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700988 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989}
990
991
992static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
993 char *argv[])
994{
995 char cmd[256];
996 int res;
997
998 if (argc == 5 || argc == 6) {
999 char ssid_hex[2 * 32 + 1];
1000 char key_hex[2 * 64 + 1];
1001 int i;
1002
1003 ssid_hex[0] = '\0';
1004 for (i = 0; i < 32; i++) {
1005 if (argv[2][i] == '\0')
1006 break;
1007 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1008 }
1009
1010 key_hex[0] = '\0';
1011 if (argc == 6) {
1012 for (i = 0; i < 64; i++) {
1013 if (argv[5][i] == '\0')
1014 break;
1015 os_snprintf(&key_hex[i * 2], 3, "%02x",
1016 argv[5][i]);
1017 }
1018 }
1019
1020 res = os_snprintf(cmd, sizeof(cmd),
1021 "WPS_ER_CONFIG %s %s %s %s %s %s",
1022 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1023 key_hex);
1024 } else {
1025 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1026 "- AP UUID\n"
1027 "- AP PIN\n"
1028 "- new SSID\n"
1029 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1030 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1031 "- new key\n");
1032 return -1;
1033 }
1034
1035 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1036 printf("Too long WPS_ER_CONFIG command.\n");
1037 return -1;
1038 }
1039 return wpa_ctrl_command(ctrl, cmd);
1040}
1041
1042
Dmitry Shmidt04949592012-07-19 12:16:46 -07001043#ifdef CONFIG_WPS_NFC
1044static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1045 char *argv[])
1046{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001047 if (argc != 2) {
1048 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1049 "arguments:\n"
1050 "- WPS/NDEF: token format\n"
1051 "- UUID: specify which AP to use\n");
1052 return -1;
1053 }
1054
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001055 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001056}
1057#endif /* CONFIG_WPS_NFC */
1058
1059
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001060static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1061{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001062 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001063}
1064
1065
1066static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1067{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001068 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001069}
1070
1071
1072static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1073{
1074 char cmd[256], *pos, *end;
1075 int i, ret;
1076
1077 if (argc < 2) {
1078 printf("Invalid IDENTITY command: needs two arguments "
1079 "(network id and identity)\n");
1080 return -1;
1081 }
1082
1083 end = cmd + sizeof(cmd);
1084 pos = cmd;
1085 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1086 argv[0], argv[1]);
1087 if (ret < 0 || ret >= end - pos) {
1088 printf("Too long IDENTITY command.\n");
1089 return -1;
1090 }
1091 pos += ret;
1092 for (i = 2; i < argc; i++) {
1093 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1094 if (ret < 0 || ret >= end - pos) {
1095 printf("Too long IDENTITY command.\n");
1096 return -1;
1097 }
1098 pos += ret;
1099 }
1100
1101 return wpa_ctrl_command(ctrl, cmd);
1102}
1103
1104
1105static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1106{
1107 char cmd[256], *pos, *end;
1108 int i, ret;
1109
1110 if (argc < 2) {
1111 printf("Invalid PASSWORD command: needs two arguments "
1112 "(network id and password)\n");
1113 return -1;
1114 }
1115
1116 end = cmd + sizeof(cmd);
1117 pos = cmd;
1118 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1119 argv[0], argv[1]);
1120 if (ret < 0 || ret >= end - pos) {
1121 printf("Too long PASSWORD command.\n");
1122 return -1;
1123 }
1124 pos += ret;
1125 for (i = 2; i < argc; i++) {
1126 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1127 if (ret < 0 || ret >= end - pos) {
1128 printf("Too long PASSWORD command.\n");
1129 return -1;
1130 }
1131 pos += ret;
1132 }
1133
1134 return wpa_ctrl_command(ctrl, cmd);
1135}
1136
1137
1138static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1139 char *argv[])
1140{
1141 char cmd[256], *pos, *end;
1142 int i, ret;
1143
1144 if (argc < 2) {
1145 printf("Invalid NEW_PASSWORD command: needs two arguments "
1146 "(network id and password)\n");
1147 return -1;
1148 }
1149
1150 end = cmd + sizeof(cmd);
1151 pos = cmd;
1152 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1153 argv[0], argv[1]);
1154 if (ret < 0 || ret >= end - pos) {
1155 printf("Too long NEW_PASSWORD command.\n");
1156 return -1;
1157 }
1158 pos += ret;
1159 for (i = 2; i < argc; i++) {
1160 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1161 if (ret < 0 || ret >= end - pos) {
1162 printf("Too long NEW_PASSWORD command.\n");
1163 return -1;
1164 }
1165 pos += ret;
1166 }
1167
1168 return wpa_ctrl_command(ctrl, cmd);
1169}
1170
1171
1172static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1173{
1174 char cmd[256], *pos, *end;
1175 int i, ret;
1176
1177 if (argc < 2) {
1178 printf("Invalid PIN command: needs two arguments "
1179 "(network id and pin)\n");
1180 return -1;
1181 }
1182
1183 end = cmd + sizeof(cmd);
1184 pos = cmd;
1185 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1186 argv[0], argv[1]);
1187 if (ret < 0 || ret >= end - pos) {
1188 printf("Too long PIN command.\n");
1189 return -1;
1190 }
1191 pos += ret;
1192 for (i = 2; i < argc; i++) {
1193 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1194 if (ret < 0 || ret >= end - pos) {
1195 printf("Too long PIN command.\n");
1196 return -1;
1197 }
1198 pos += ret;
1199 }
1200 return wpa_ctrl_command(ctrl, cmd);
1201}
1202
1203
1204static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1205{
1206 char cmd[256], *pos, *end;
1207 int i, ret;
1208
1209 if (argc < 2) {
1210 printf("Invalid OTP command: needs two arguments (network "
1211 "id and password)\n");
1212 return -1;
1213 }
1214
1215 end = cmd + sizeof(cmd);
1216 pos = cmd;
1217 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1218 argv[0], argv[1]);
1219 if (ret < 0 || ret >= end - pos) {
1220 printf("Too long OTP command.\n");
1221 return -1;
1222 }
1223 pos += ret;
1224 for (i = 2; i < argc; i++) {
1225 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1226 if (ret < 0 || ret >= end - pos) {
1227 printf("Too long OTP command.\n");
1228 return -1;
1229 }
1230 pos += ret;
1231 }
1232
1233 return wpa_ctrl_command(ctrl, cmd);
1234}
1235
1236
Dmitry Shmidt051af732013-10-22 13:52:46 -07001237static int wpa_cli_cmd_sim(struct wpa_ctrl *ctrl, int argc, char *argv[])
1238{
1239 char cmd[256], *pos, *end;
1240 int i, ret;
1241
1242 if (argc < 2) {
1243 printf("Invalid SIM command: needs two arguments "
1244 "(network id and SIM operation response)\n");
1245 return -1;
1246 }
1247
1248 end = cmd + sizeof(cmd);
1249 pos = cmd;
1250 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "SIM-%s:%s",
1251 argv[0], argv[1]);
1252 if (ret < 0 || ret >= end - pos) {
1253 printf("Too long SIM command.\n");
1254 return -1;
1255 }
1256 pos += ret;
1257 for (i = 2; i < argc; i++) {
1258 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1259 if (ret < 0 || ret >= end - pos) {
1260 printf("Too long SIM command.\n");
1261 return -1;
1262 }
1263 pos += ret;
1264 }
1265 return wpa_ctrl_command(ctrl, cmd);
1266}
1267
1268
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001269static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1270 char *argv[])
1271{
1272 char cmd[256], *pos, *end;
1273 int i, ret;
1274
1275 if (argc < 2) {
1276 printf("Invalid PASSPHRASE command: needs two arguments "
1277 "(network id and passphrase)\n");
1278 return -1;
1279 }
1280
1281 end = cmd + sizeof(cmd);
1282 pos = cmd;
1283 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1284 argv[0], argv[1]);
1285 if (ret < 0 || ret >= end - pos) {
1286 printf("Too long PASSPHRASE command.\n");
1287 return -1;
1288 }
1289 pos += ret;
1290 for (i = 2; i < argc; i++) {
1291 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1292 if (ret < 0 || ret >= end - pos) {
1293 printf("Too long PASSPHRASE command.\n");
1294 return -1;
1295 }
1296 pos += ret;
1297 }
1298
1299 return wpa_ctrl_command(ctrl, cmd);
1300}
1301
1302
1303static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1304{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001305 if (argc < 2) {
1306 printf("Invalid BSSID command: needs two arguments (network "
1307 "id and BSSID)\n");
1308 return -1;
1309 }
1310
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001311 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001312}
1313
1314
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001315static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1316{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001317 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001318}
1319
1320
1321static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1322{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001323 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001324}
1325
1326
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001327static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1328 char *argv[])
1329{
1330 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1331}
1332
1333
1334static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1335 char *argv[])
1336{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001337 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001338}
1339
1340
1341static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1342 char *argv[])
1343{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001344 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001345}
1346
1347
1348static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1349 char *argv[])
1350{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001351 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001352}
1353
1354
1355static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1356 char *argv[])
1357{
1358 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1359}
1360
1361
1362static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1363 char *argv[])
1364{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001365 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001366}
1367
1368
1369static void wpa_cli_show_network_variables(void)
1370{
1371 printf("set_network variables:\n"
1372 " ssid (network name, SSID)\n"
1373 " psk (WPA passphrase or pre-shared key)\n"
1374 " key_mgmt (key management protocol)\n"
1375 " identity (EAP identity)\n"
1376 " password (EAP password)\n"
1377 " ...\n"
1378 "\n"
1379 "Note: Values are entered in the same format as the "
1380 "configuration file is using,\n"
1381 "i.e., strings values need to be inside double quotation "
1382 "marks.\n"
1383 "For example: set_network 1 ssid \"network name\"\n"
1384 "\n"
1385 "Please see wpa_supplicant.conf documentation for full list "
1386 "of\navailable variables.\n");
1387}
1388
1389
1390static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1391 char *argv[])
1392{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001393 if (argc == 0) {
1394 wpa_cli_show_network_variables();
1395 return 0;
1396 }
1397
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001398 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001399 printf("Invalid SET_NETWORK command: needs three arguments\n"
1400 "(network id, variable name, and value)\n");
1401 return -1;
1402 }
1403
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001404 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001405}
1406
1407
1408static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1409 char *argv[])
1410{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001411 if (argc == 0) {
1412 wpa_cli_show_network_variables();
1413 return 0;
1414 }
1415
1416 if (argc != 2) {
1417 printf("Invalid GET_NETWORK command: needs two arguments\n"
1418 "(network id and variable name)\n");
1419 return -1;
1420 }
1421
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001422 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001423}
1424
1425
Dmitry Shmidt684785c2014-05-12 13:34:29 -07001426static int wpa_cli_cmd_dup_network(struct wpa_ctrl *ctrl, int argc,
1427 char *argv[])
1428{
1429 if (argc == 0) {
1430 wpa_cli_show_network_variables();
1431 return 0;
1432 }
1433
1434 if (argc < 3) {
1435 printf("Invalid DUP_NETWORK command: needs three arguments\n"
1436 "(src netid, dest netid, and variable name)\n");
1437 return -1;
1438 }
1439
1440 return wpa_cli_cmd(ctrl, "DUP_NETWORK", 3, argc, argv);
1441}
1442
1443
Dmitry Shmidt04949592012-07-19 12:16:46 -07001444static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1445 char *argv[])
1446{
1447 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1448}
1449
1450
1451static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1452{
1453 return wpa_ctrl_command(ctrl, "ADD_CRED");
1454}
1455
1456
1457static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1458 char *argv[])
1459{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001460 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001461}
1462
1463
1464static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1465{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001466 if (argc != 3) {
1467 printf("Invalid SET_CRED command: needs three arguments\n"
1468 "(cred id, variable name, and value)\n");
1469 return -1;
1470 }
1471
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001472 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001473}
1474
1475
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07001476static int wpa_cli_cmd_get_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1477{
1478 if (argc != 2) {
1479 printf("Invalid GET_CRED command: needs two arguments\n"
1480 "(cred id, variable name)\n");
1481 return -1;
1482 }
1483
1484 return wpa_cli_cmd(ctrl, "GET_CRED", 2, argc, argv);
1485}
1486
1487
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001488static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1489 char *argv[])
1490{
1491 return wpa_ctrl_command(ctrl, "DISCONNECT");
1492}
1493
1494
1495static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1496 char *argv[])
1497{
1498 return wpa_ctrl_command(ctrl, "RECONNECT");
1499}
1500
1501
1502static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1503 char *argv[])
1504{
1505 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1506}
1507
1508
1509static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1510{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001511 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001512}
1513
1514
1515static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1516 char *argv[])
1517{
1518 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1519}
1520
1521
1522static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1523{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001524 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001525}
1526
1527
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001528static char ** wpa_cli_complete_bss(const char *str, int pos)
1529{
1530 int arg = get_cmd_arg_num(str, pos);
1531 char **res = NULL;
1532
1533 switch (arg) {
1534 case 1:
1535 res = cli_txt_list_array(&bsses);
1536 break;
1537 }
1538
1539 return res;
1540}
1541
1542
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001543static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1544 char *argv[])
1545{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001546 if (argc < 1 || argc > 2) {
1547 printf("Invalid GET_CAPABILITY command: need either one or "
1548 "two arguments\n");
1549 return -1;
1550 }
1551
1552 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1553 printf("Invalid GET_CAPABILITY command: second argument, "
1554 "if any, must be 'strict'\n");
1555 return -1;
1556 }
1557
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001558 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001559}
1560
1561
1562static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1563{
1564 printf("Available interfaces:\n");
1565 return wpa_ctrl_command(ctrl, "INTERFACES");
1566}
1567
1568
1569static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1570{
1571 if (argc < 1) {
1572 wpa_cli_list_interfaces(ctrl);
1573 return 0;
1574 }
1575
1576 wpa_cli_close_connection();
1577 os_free(ctrl_ifname);
1578 ctrl_ifname = os_strdup(argv[0]);
1579
Dmitry Shmidt413dde72014-04-11 10:23:22 -07001580 if (wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001581 printf("Connected to interface '%s.\n", ctrl_ifname);
1582 } else {
1583 printf("Could not connect to interface '%s' - re-trying\n",
1584 ctrl_ifname);
1585 }
1586 return 0;
1587}
1588
1589
1590static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1591 char *argv[])
1592{
1593 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1594}
1595
1596
1597static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1598 char *argv[])
1599{
1600 return wpa_ctrl_command(ctrl, "TERMINATE");
1601}
1602
1603
1604static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1605 char *argv[])
1606{
1607 char cmd[256];
1608 int res;
1609
1610 if (argc < 1) {
1611 printf("Invalid INTERFACE_ADD command: needs at least one "
1612 "argument (interface name)\n"
1613 "All arguments: ifname confname driver ctrl_interface "
1614 "driver_param bridge_name\n");
1615 return -1;
1616 }
1617
1618 /*
1619 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1620 * <driver_param>TAB<bridge_name>
1621 */
1622 res = os_snprintf(cmd, sizeof(cmd),
1623 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1624 argv[0],
1625 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1626 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1627 argc > 5 ? argv[5] : "");
1628 if (res < 0 || (size_t) res >= sizeof(cmd))
1629 return -1;
1630 cmd[sizeof(cmd) - 1] = '\0';
1631 return wpa_ctrl_command(ctrl, cmd);
1632}
1633
1634
1635static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1636 char *argv[])
1637{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001638 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001639}
1640
1641
1642static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1643 char *argv[])
1644{
1645 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1646}
1647
1648
1649#ifdef CONFIG_AP
1650static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1651{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001652 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001653}
1654
1655
1656static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1657 char *addr, size_t addr_len)
1658{
1659 char buf[4096], *pos;
1660 size_t len;
1661 int ret;
1662
1663 if (ctrl_conn == NULL) {
1664 printf("Not connected to hostapd - command dropped.\n");
1665 return -1;
1666 }
1667 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001668 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001669 wpa_cli_msg_cb);
1670 if (ret == -2) {
1671 printf("'%s' command timed out.\n", cmd);
1672 return -2;
1673 } else if (ret < 0) {
1674 printf("'%s' command failed.\n", cmd);
1675 return -1;
1676 }
1677
1678 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001679 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001680 return -1;
1681 printf("%s", buf);
1682
1683 pos = buf;
1684 while (*pos != '\0' && *pos != '\n')
1685 pos++;
1686 *pos = '\0';
1687 os_strlcpy(addr, buf, addr_len);
1688 return 0;
1689}
1690
1691
1692static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1693{
1694 char addr[32], cmd[64];
1695
1696 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1697 return 0;
1698 do {
1699 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1700 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1701
1702 return -1;
1703}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001704
1705
1706static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1707 char *argv[])
1708{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001709 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001710}
1711
1712
1713static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1714 char *argv[])
1715{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001716 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001717}
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08001718
1719static int wpa_cli_cmd_chanswitch(struct wpa_ctrl *ctrl, int argc,
1720 char *argv[])
1721{
1722 return wpa_cli_cmd(ctrl, "CHAN_SWITCH", 2, argc, argv);
1723}
1724
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725#endif /* CONFIG_AP */
1726
1727
1728static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1729{
1730 return wpa_ctrl_command(ctrl, "SUSPEND");
1731}
1732
1733
1734static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1735{
1736 return wpa_ctrl_command(ctrl, "RESUME");
1737}
1738
1739
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001740#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001741static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1742{
1743 return wpa_ctrl_command(ctrl, "DROP_SA");
1744}
Dmitry Shmidt21de2142014-04-08 10:50:52 -07001745#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746
1747
1748static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1749{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001750 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001751}
1752
1753
1754#ifdef CONFIG_P2P
1755
1756static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1757{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001758 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1759}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001760
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001761
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001762static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1763{
1764 char **res = NULL;
1765 int arg = get_cmd_arg_num(str, pos);
1766
1767 res = os_calloc(6, sizeof(char *));
1768 if (res == NULL)
1769 return NULL;
1770 res[0] = os_strdup("type=social");
1771 if (res[0] == NULL) {
1772 os_free(res);
1773 return NULL;
1774 }
1775 res[1] = os_strdup("type=progressive");
1776 if (res[1] == NULL)
1777 return res;
1778 res[2] = os_strdup("delay=");
1779 if (res[2] == NULL)
1780 return res;
1781 res[3] = os_strdup("dev_id=");
1782 if (res[3] == NULL)
1783 return res;
1784 if (arg == 1)
1785 res[4] = os_strdup("[timeout]");
1786
1787 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001788}
1789
1790
1791static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1792 char *argv[])
1793{
1794 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1795}
1796
1797
1798static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1799 char *argv[])
1800{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001801 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001802}
1803
1804
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001805static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1806{
1807 int arg = get_cmd_arg_num(str, pos);
1808 char **res = NULL;
1809
1810 switch (arg) {
1811 case 1:
1812 res = cli_txt_list_array(&p2p_peers);
1813 break;
1814 }
1815
1816 return res;
1817}
1818
1819
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001820static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1821 char *argv[])
1822{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001823 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001824}
1825
1826
1827static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1828 char *argv[])
1829{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001830 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001831}
1832
1833
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001834static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1835{
1836 int arg = get_cmd_arg_num(str, pos);
1837 char **res = NULL;
1838
1839 switch (arg) {
1840 case 1:
1841 res = cli_txt_list_array(&p2p_groups);
1842 break;
1843 }
1844
1845 return res;
1846}
1847
1848
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001849static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1850 char *argv[])
1851{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001852 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001853}
1854
1855
1856static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1857 char *argv[])
1858{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001859 if (argc != 2 && argc != 3) {
1860 printf("Invalid P2P_PROV_DISC command: needs at least "
1861 "two arguments, address and config method\n"
1862 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001863 return -1;
1864 }
1865
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001866 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001867}
1868
1869
1870static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1871 char *argv[])
1872{
1873 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1874}
1875
1876
1877static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1878 char *argv[])
1879{
1880 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001881
1882 if (argc != 2 && argc != 4) {
1883 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1884 "arguments (address and TLVs) or four arguments "
1885 "(address, \"upnp\", version, search target "
1886 "(SSDP ST:)\n");
1887 return -1;
1888 }
1889
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001890 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001891 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001892 return wpa_ctrl_command(ctrl, cmd);
1893}
1894
1895
1896static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1897 int argc, char *argv[])
1898{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001899 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001900}
1901
1902
1903static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1904 char *argv[])
1905{
1906 char cmd[4096];
1907 int res;
1908
1909 if (argc != 4) {
1910 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1911 "arguments (freq, address, dialog token, and TLVs)\n");
1912 return -1;
1913 }
1914
1915 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1916 argv[0], argv[1], argv[2], argv[3]);
1917 if (res < 0 || (size_t) res >= sizeof(cmd))
1918 return -1;
1919 cmd[sizeof(cmd) - 1] = '\0';
1920 return wpa_ctrl_command(ctrl, cmd);
1921}
1922
1923
1924static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1925 char *argv[])
1926{
1927 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1928}
1929
1930
1931static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1932 int argc, char *argv[])
1933{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001934 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001935}
1936
1937
1938static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1939 char *argv[])
1940{
1941 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1942}
1943
1944
1945static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1946 char *argv[])
1947{
1948 char cmd[4096];
1949 int res;
1950
1951 if (argc != 3 && argc != 4) {
1952 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1953 "arguments\n");
1954 return -1;
1955 }
1956
1957 if (argc == 4)
1958 res = os_snprintf(cmd, sizeof(cmd),
1959 "P2P_SERVICE_ADD %s %s %s %s",
1960 argv[0], argv[1], argv[2], argv[3]);
1961 else
1962 res = os_snprintf(cmd, sizeof(cmd),
1963 "P2P_SERVICE_ADD %s %s %s",
1964 argv[0], argv[1], argv[2]);
1965 if (res < 0 || (size_t) res >= sizeof(cmd))
1966 return -1;
1967 cmd[sizeof(cmd) - 1] = '\0';
1968 return wpa_ctrl_command(ctrl, cmd);
1969}
1970
1971
1972static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1973 char *argv[])
1974{
1975 char cmd[4096];
1976 int res;
1977
1978 if (argc != 2 && argc != 3) {
1979 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1980 "arguments\n");
1981 return -1;
1982 }
1983
1984 if (argc == 3)
1985 res = os_snprintf(cmd, sizeof(cmd),
1986 "P2P_SERVICE_DEL %s %s %s",
1987 argv[0], argv[1], argv[2]);
1988 else
1989 res = os_snprintf(cmd, sizeof(cmd),
1990 "P2P_SERVICE_DEL %s %s",
1991 argv[0], argv[1]);
1992 if (res < 0 || (size_t) res >= sizeof(cmd))
1993 return -1;
1994 cmd[sizeof(cmd) - 1] = '\0';
1995 return wpa_ctrl_command(ctrl, cmd);
1996}
1997
1998
1999static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
2000 int argc, char *argv[])
2001{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002002 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002003}
2004
2005
2006static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
2007 int argc, char *argv[])
2008{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002009 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002010}
2011
2012
2013static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
2014{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002015 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002016}
2017
2018
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002019static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2020{
2021 int arg = get_cmd_arg_num(str, pos);
2022 char **res = NULL;
2023
2024 switch (arg) {
2025 case 1:
2026 res = cli_txt_list_array(&p2p_peers);
2027 break;
2028 }
2029
2030 return res;
2031}
2032
2033
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002034static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2035 char *addr, size_t addr_len,
2036 int discovered)
2037{
2038 char buf[4096], *pos;
2039 size_t len;
2040 int ret;
2041
2042 if (ctrl_conn == NULL)
2043 return -1;
2044 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002045 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002046 wpa_cli_msg_cb);
2047 if (ret == -2) {
2048 printf("'%s' command timed out.\n", cmd);
2049 return -2;
2050 } else if (ret < 0) {
2051 printf("'%s' command failed.\n", cmd);
2052 return -1;
2053 }
2054
2055 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002056 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002057 return -1;
2058
2059 pos = buf;
2060 while (*pos != '\0' && *pos != '\n')
2061 pos++;
2062 *pos++ = '\0';
2063 os_strlcpy(addr, buf, addr_len);
2064 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2065 printf("%s\n", addr);
2066 return 0;
2067}
2068
2069
2070static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2071{
2072 char addr[32], cmd[64];
2073 int discovered;
2074
2075 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2076
2077 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2078 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002079 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002080 do {
2081 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2082 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2083 discovered) == 0);
2084
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002085 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002086}
2087
2088
2089static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2090{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002091 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002092}
2093
2094
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002095static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2096{
2097 int arg = get_cmd_arg_num(str, pos);
2098 const char *fields[] = {
2099 "discoverability",
2100 "managed",
2101 "listen_channel",
2102 "ssid_postfix",
2103 "noa",
2104 "ps",
2105 "oppps",
2106 "ctwindow",
2107 "disabled",
2108 "conc_pref",
2109 "force_long_sd",
2110 "peer_filter",
2111 "cross_connect",
2112 "go_apsd",
2113 "client_apsd",
2114 "disallow_freq",
2115 "disc_int",
2116 "per_sta_psk",
2117 };
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07002118 int i, num_fields = ARRAY_SIZE(fields);
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002119
2120 if (arg == 1) {
2121 char **res = os_calloc(num_fields + 1, sizeof(char *));
2122 if (res == NULL)
2123 return NULL;
2124 for (i = 0; i < num_fields; i++) {
2125 res[i] = os_strdup(fields[i]);
2126 if (res[i] == NULL)
2127 return res;
2128 }
2129 return res;
2130 }
2131
2132 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2133 return cli_txt_list_array(&p2p_peers);
2134
2135 return NULL;
2136}
2137
2138
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002139static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2140{
2141 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2142}
2143
2144
2145static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2146 char *argv[])
2147{
2148 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2149}
2150
2151
2152static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2153 char *argv[])
2154{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002155 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002156}
2157
2158
2159static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2160 char *argv[])
2161{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002162 if (argc != 0 && argc != 2 && argc != 4) {
2163 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2164 "(preferred duration, interval; in microsecods).\n"
2165 "Optional second pair can be used to provide "
2166 "acceptable values.\n");
2167 return -1;
2168 }
2169
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002170 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002171}
2172
2173
2174static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2175 char *argv[])
2176{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002177 if (argc != 0 && argc != 2) {
2178 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2179 "(availability period, availability interval; in "
2180 "millisecods).\n"
2181 "Extended Listen Timing can be cancelled with this "
2182 "command when used without parameters.\n");
2183 return -1;
2184 }
2185
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002186 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2187}
2188
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002189
2190static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2191 char *argv[])
2192{
2193 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2194}
2195
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002196#endif /* CONFIG_P2P */
2197
2198#ifdef CONFIG_WIFI_DISPLAY
2199
2200static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2201 char *argv[])
2202{
2203 char cmd[100];
2204 int res;
2205
2206 if (argc != 1 && argc != 2) {
2207 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2208 "arguments (subelem, hexdump)\n");
2209 return -1;
2210 }
2211
2212 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2213 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002214 if (res < 0 || (size_t) res >= sizeof(cmd))
2215 return -1;
2216 cmd[sizeof(cmd) - 1] = '\0';
2217 return wpa_ctrl_command(ctrl, cmd);
2218}
2219
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002220
2221static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2222 char *argv[])
2223{
2224 char cmd[100];
2225 int res;
2226
2227 if (argc != 1) {
2228 printf("Invalid WFD_SUBELEM_GET command: needs one "
2229 "argument (subelem)\n");
2230 return -1;
2231 }
2232
2233 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2234 argv[0]);
2235 if (res < 0 || (size_t) res >= sizeof(cmd))
2236 return -1;
2237 cmd[sizeof(cmd) - 1] = '\0';
2238 return wpa_ctrl_command(ctrl, cmd);
2239}
2240#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002241
2242
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002243#ifdef CONFIG_INTERWORKING
2244static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2245 char *argv[])
2246{
2247 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2248}
2249
2250
2251static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2252 char *argv[])
2253{
2254 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2255}
2256
2257
2258static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2259 char *argv[])
2260{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002261 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002262}
2263
2264
2265static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2266 char *argv[])
2267{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002268 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002269}
2270
2271
2272static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2273{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002274 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2275}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002276
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002277
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002278static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2279 char *argv[])
2280{
2281 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2282}
2283
2284
2285static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2286 char *argv[])
2287{
2288 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002289}
2290#endif /* CONFIG_INTERWORKING */
2291
2292
Dmitry Shmidt04949592012-07-19 12:16:46 -07002293#ifdef CONFIG_HS20
2294
2295static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2296 char *argv[])
2297{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002298 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002299}
2300
2301
2302static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2303 char *argv[])
2304{
2305 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002306
2307 if (argc == 0) {
2308 printf("Command needs one or two arguments (dst mac addr and "
2309 "optional home realm)\n");
2310 return -1;
2311 }
2312
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002313 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2314 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002315 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002316
2317 return wpa_ctrl_command(ctrl, cmd);
2318}
2319
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002320
2321static int wpa_cli_cmd_hs20_icon_request(struct wpa_ctrl *ctrl, int argc,
2322 char *argv[])
2323{
2324 char cmd[512];
2325
2326 if (argc < 2) {
2327 printf("Command needs two arguments (dst mac addr and "
2328 "icon name)\n");
2329 return -1;
2330 }
2331
2332 if (write_cmd(cmd, sizeof(cmd), "HS20_ICON_REQUEST", argc, argv) < 0)
2333 return -1;
2334
2335 return wpa_ctrl_command(ctrl, cmd);
2336}
2337
2338
2339static int wpa_cli_cmd_fetch_osu(struct wpa_ctrl *ctrl, int argc, char *argv[])
2340{
2341 return wpa_ctrl_command(ctrl, "FETCH_OSU");
2342}
2343
2344
2345static int wpa_cli_cmd_cancel_fetch_osu(struct wpa_ctrl *ctrl, int argc,
2346 char *argv[])
2347{
2348 return wpa_ctrl_command(ctrl, "CANCEL_FETCH_OSU");
2349}
2350
Dmitry Shmidt04949592012-07-19 12:16:46 -07002351#endif /* CONFIG_HS20 */
2352
2353
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002354static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2355 char *argv[])
2356{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002357 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002358}
2359
2360
2361static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2362 char *argv[])
2363{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002364 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002365}
2366
2367
2368static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2369 char *argv[])
2370{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002371 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002372}
2373
2374
2375static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2376 char *argv[])
2377{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002378 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002379}
2380
2381
2382static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2383 char *argv[])
2384{
2385 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2386}
2387
2388
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002389static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2390 char *argv[])
2391{
2392 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2393}
2394
2395
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002396static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2397 char *argv[])
2398{
2399 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2400}
2401
Dmitry Shmidt04949592012-07-19 12:16:46 -07002402
2403#ifdef CONFIG_AUTOSCAN
2404
2405static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2406{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002407 if (argc == 0)
2408 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2409
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002410 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002411}
2412
2413#endif /* CONFIG_AUTOSCAN */
2414
2415
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002416#ifdef CONFIG_WNM
2417
2418static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2419{
2420 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2421}
2422
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002423
2424static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2425{
2426 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2427}
2428
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002429#endif /* CONFIG_WNM */
2430
2431
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002432static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2433{
2434 if (argc == 0)
2435 return -1;
2436 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2437}
2438
2439
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002440#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002441static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2442{
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002443 return wpa_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002444}
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002445#endif /* ANDROID */
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002446
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002447
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002448static int wpa_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
2449{
2450 return wpa_cli_cmd(ctrl, "VENDOR", 1, argc, argv);
2451}
2452
2453
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002454static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2455{
2456 return wpa_ctrl_command(ctrl, "FLUSH");
2457}
2458
2459
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002460static int wpa_cli_cmd_radio_work(struct wpa_ctrl *ctrl, int argc, char *argv[])
2461{
2462 return wpa_cli_cmd(ctrl, "RADIO_WORK", 1, argc, argv);
2463}
2464
2465
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002466enum wpa_cli_cmd_flags {
2467 cli_cmd_flag_none = 0x00,
2468 cli_cmd_flag_sensitive = 0x01
2469};
2470
2471struct wpa_cli_cmd {
2472 const char *cmd;
2473 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002474 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002475 enum wpa_cli_cmd_flags flags;
2476 const char *usage;
2477};
2478
2479static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002480 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002481 cli_cmd_flag_none,
2482 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002483 { "ifname", wpa_cli_cmd_ifname, NULL,
2484 cli_cmd_flag_none,
2485 "= get current interface name" },
2486 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002487 cli_cmd_flag_none,
2488 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002489 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002490 cli_cmd_flag_none,
2491 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002492 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002493 cli_cmd_flag_none,
2494 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002495 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002496 cli_cmd_flag_none,
2497 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002498 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002499 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002500 "[command] = show usage help" },
2501 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 cli_cmd_flag_none,
2503 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002504 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002505 cli_cmd_flag_none,
2506 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002507 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002508 cli_cmd_flag_none,
2509 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002510 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002511 cli_cmd_flag_none,
2512 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002513 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514 cli_cmd_flag_none,
2515 "= set variables (shows list of variables when run without "
2516 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002517 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002518 cli_cmd_flag_none,
2519 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002520 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521 cli_cmd_flag_none,
2522 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002523 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002524 cli_cmd_flag_none,
2525 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002526 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002527 cli_cmd_flag_none,
2528 "= show PMKSA cache" },
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07002529 { "pmksa_flush", wpa_cli_cmd_pmksa_flush, NULL,
2530 cli_cmd_flag_none,
2531 "= flush PMKSA cache entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002532 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002533 cli_cmd_flag_none,
2534 "= force reassociation" },
Dmitry Shmidt98660862014-03-11 17:26:21 -07002535 { "reattach", wpa_cli_cmd_reattach, NULL,
2536 cli_cmd_flag_none,
2537 "= force reassociation back to the same BSS" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002538 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002539 cli_cmd_flag_none,
2540 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002541 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002542 cli_cmd_flag_none,
2543 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002544 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002545 cli_cmd_flag_sensitive,
2546 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002547 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002548 cli_cmd_flag_sensitive,
2549 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002550 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002551 cli_cmd_flag_sensitive,
2552 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002553 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002554 cli_cmd_flag_sensitive,
2555 "<network id> <password> = configure one-time-password for an SSID"
2556 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002557 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558 cli_cmd_flag_sensitive,
2559 "<network id> <passphrase> = configure private key passphrase\n"
2560 " for an SSID" },
Dmitry Shmidt051af732013-10-22 13:52:46 -07002561 { "sim", wpa_cli_cmd_sim, NULL,
2562 cli_cmd_flag_sensitive,
2563 "<network id> <pin> = report SIM operation result" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002564 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002565 cli_cmd_flag_none,
2566 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002567 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002568 cli_cmd_flag_none,
2569 "<BSSID> = add a BSSID to the blacklist\n"
2570 "blacklist clear = clear the blacklist\n"
2571 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002572 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002573 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002574 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002575 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002576 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002577 cli_cmd_flag_none,
2578 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002579 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002580 cli_cmd_flag_none,
2581 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002582 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002583 cli_cmd_flag_none,
2584 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002585 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002586 cli_cmd_flag_none,
2587 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002588 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002589 cli_cmd_flag_none,
2590 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002591 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002592 cli_cmd_flag_none,
2593 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002594 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002595 cli_cmd_flag_sensitive,
2596 "<network id> <variable> <value> = set network variables (shows\n"
2597 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002598 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002599 cli_cmd_flag_none,
2600 "<network id> <variable> = get network variables" },
Dmitry Shmidt684785c2014-05-12 13:34:29 -07002601 { "dup_network", wpa_cli_cmd_dup_network, NULL,
2602 cli_cmd_flag_none,
2603 "<src network id> <dst network id> <variable> = duplicate network variables"
2604 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002605 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002606 cli_cmd_flag_none,
2607 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002608 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002609 cli_cmd_flag_none,
2610 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002611 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002612 cli_cmd_flag_none,
2613 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002614 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002615 cli_cmd_flag_sensitive,
2616 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt0cfd5f72014-04-04 14:48:05 -07002617 { "get_cred", wpa_cli_cmd_get_cred, NULL,
2618 cli_cmd_flag_none,
2619 "<cred id> <variable> = get credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002620 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002621 cli_cmd_flag_none,
2622 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002623 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 cli_cmd_flag_none,
2625 "= disconnect and wait for reassociate/reconnect command before\n"
2626 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002627 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002628 cli_cmd_flag_none,
2629 "= like reassociate, but only takes effect if already disconnected"
2630 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002631 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002632 cli_cmd_flag_none,
2633 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002634 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002635 cli_cmd_flag_none,
2636 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002637 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638 cli_cmd_flag_none,
2639 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002640 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002641 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002642 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002643 "= get capabilies" },
2644 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 cli_cmd_flag_none,
2646 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002647 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648 cli_cmd_flag_none,
2649 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002650 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651 cli_cmd_flag_none,
2652 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2653 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2654 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002655 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002656 cli_cmd_flag_none,
2657 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002658 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002659 cli_cmd_flag_none,
2660 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002661 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002662 cli_cmd_flag_none,
2663 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002664 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002665 cli_cmd_flag_none,
2666 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002667 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002668 cli_cmd_flag_none,
2669 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002670 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002671 cli_cmd_flag_none,
2672 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002673 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002674 cli_cmd_flag_none,
2675 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002676 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002677 cli_cmd_flag_none,
2678 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002679 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002680 cli_cmd_flag_none,
2681 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002682 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002683 cli_cmd_flag_none,
2684 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002685 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002686 cli_cmd_flag_sensitive,
2687 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2688 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002689 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002690 cli_cmd_flag_sensitive,
2691 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002692 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002694#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002695 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002696 cli_cmd_flag_none,
2697 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002698 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2699 cli_cmd_flag_none,
2700 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002701 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002702 cli_cmd_flag_none,
2703 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002704 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002705 cli_cmd_flag_sensitive,
2706 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002707 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2708 cli_cmd_flag_none,
2709 "<NDEF> <WPS> = create NFC handover request" },
2710 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2711 cli_cmd_flag_none,
2712 "<NDEF> <WPS> = create NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002713 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2714 cli_cmd_flag_none,
2715 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2716 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002717#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002718 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002719 cli_cmd_flag_sensitive,
2720 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002721 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722 cli_cmd_flag_sensitive,
2723 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002724 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002725 cli_cmd_flag_none,
2726 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002727 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002728 cli_cmd_flag_none,
2729 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002730 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002731 cli_cmd_flag_sensitive,
2732 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002733 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002734 cli_cmd_flag_none,
2735 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002736 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002737 cli_cmd_flag_sensitive,
2738 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002739 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002740 cli_cmd_flag_none,
2741 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002742 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002743 cli_cmd_flag_sensitive,
2744 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002745#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002746 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002747 cli_cmd_flag_none,
2748 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2749#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002750 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002751 cli_cmd_flag_none,
2752 "<addr> = request RSN authentication with <addr> in IBSS" },
2753#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002754 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002755 cli_cmd_flag_none,
2756 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002757 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002758 cli_cmd_flag_none,
2759 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002760 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002761 cli_cmd_flag_none,
2762 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002763 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002764 cli_cmd_flag_none,
2765 "<addr> = disassociate a station" },
Dmitry Shmidte0e48dc2013-11-18 12:00:06 -08002766 { "chan_switch", wpa_cli_cmd_chanswitch, NULL,
2767 cli_cmd_flag_none,
2768 "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]"
2769 " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]"
2770 " = CSA parameters" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002771#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002772 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002773 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002774 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002775 "= notification of resume/thaw" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07002776#ifdef CONFIG_TESTING_OPTIONS
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002777 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt21de2142014-04-08 10:50:52 -07002779#endif /* CONFIG_TESTING_OPTIONS */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002780 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002781 cli_cmd_flag_none,
2782 "<addr> = roam to the specified BSS" },
2783#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002784 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2785 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002786 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002787 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002788 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002789 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2790 cli_cmd_flag_none,
2791 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2792 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002793 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002794 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2795 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002796 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002797 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2798 "[ht40] = add a new P2P group (local end as GO)" },
2799 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2800 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002801 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002802 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002803 cli_cmd_flag_none,
2804 "= get the passphrase for a group (GO only)" },
2805 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002806 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002807 "<addr> <TLVs> = schedule service discovery request" },
2808 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002809 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002810 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002811 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002812 cli_cmd_flag_none,
2813 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002814 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002815 cli_cmd_flag_none,
2816 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002817 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002818 cli_cmd_flag_none,
2819 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002820 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002821 cli_cmd_flag_none,
2822 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002823 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002824 cli_cmd_flag_none,
2825 "<bonjour|upnp> <query|version> <response|service> = add a local "
2826 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002827 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002828 cli_cmd_flag_none,
2829 "<bonjour|upnp> <query|version> [|service] = remove a local "
2830 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002831 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002832 cli_cmd_flag_none,
2833 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002834 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002835 cli_cmd_flag_none,
2836 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002837 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002838 "[discovered] = list known (optionally, only fully discovered) P2P "
2839 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002840 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2841 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002842 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002843 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2844 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002845 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002846 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002847 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002848 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002849 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002850 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2851 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002852 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002853 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2854 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002855 "[<duration> <interval>] [<duration> <interval>] = request GO "
2856 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002857 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2858 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002859 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002860 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2861 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2862 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002863#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002864#ifdef CONFIG_WIFI_DISPLAY
2865 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2866 cli_cmd_flag_none,
2867 "<subelem> [contents] = set Wi-Fi Display subelement" },
2868 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2869 cli_cmd_flag_none,
2870 "<subelem> = get Wi-Fi Display subelement" },
2871#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002872#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002873 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002874 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002875 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2876 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002877 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002878 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002879 cli_cmd_flag_none,
2880 "[auto] = perform Interworking network selection" },
2881 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002882 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002883 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002884 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2885 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002886 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002887 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2888 cli_cmd_flag_none,
2889 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2890 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2891 wpa_cli_complete_bss, cli_cmd_flag_none,
2892 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002893#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002894#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002895 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2896 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002897 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2898 },
2899 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002900 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002901 "<addr> <home realm> = get HS20 nai home realm list" },
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08002902 { "hs20_icon_request", wpa_cli_cmd_hs20_icon_request,
2903 wpa_cli_complete_bss, cli_cmd_flag_none,
2904 "<addr> <icon name> = get Hotspot 2.0 OSU icon" },
2905 { "fetch_osu", wpa_cli_cmd_fetch_osu, NULL, cli_cmd_flag_none,
2906 "= fetch OSU provider information from all APs" },
2907 { "cancel_fetch_osu", wpa_cli_cmd_cancel_fetch_osu, NULL,
2908 cli_cmd_flag_none,
2909 "= cancel fetch_osu command" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002910#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002911 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2912 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002913 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002914 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002915 cli_cmd_flag_none,
2916 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002917 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002918 cli_cmd_flag_none,
2919 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002920 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002921 cli_cmd_flag_none,
2922 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002923 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002924 cli_cmd_flag_none,
2925 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002926 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002927 cli_cmd_flag_none,
2928 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002929 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2930 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002931 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002932#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002933 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002934 "[params] = Set or unset (if none) autoscan parameters" },
2935#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002936#ifdef CONFIG_WNM
2937 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2938 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002939 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2940 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002941#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002942 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2943 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002944 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2945 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002946#ifdef ANDROID
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002947 { "driver", wpa_cli_cmd_driver, NULL, cli_cmd_flag_none,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002948 "<command> = driver private commands" },
Dmitry Shmidt292b0c32013-11-22 12:54:42 -08002949#endif /* ANDROID */
Dmitry Shmidtfb79edc2014-01-10 10:45:54 -08002950 { "radio_work", wpa_cli_cmd_radio_work, NULL, cli_cmd_flag_none,
2951 "= radio_work <show/add/done>" },
Dmitry Shmidta38abf92014-03-06 13:38:44 -08002952 { "vendor", wpa_cli_cmd_vendor, NULL, cli_cmd_flag_none,
2953 "<vendor id> <command id> [<hex formatted command argument>] = Send vendor command"
2954 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002955 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002956};
2957
2958
2959/*
2960 * Prints command usage, lines are padded with the specified string.
2961 */
2962static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2963{
2964 char c;
2965 size_t n;
2966
2967 printf("%s%s ", pad, cmd->cmd);
2968 for (n = 0; (c = cmd->usage[n]); n++) {
2969 printf("%c", c);
2970 if (c == '\n')
2971 printf("%s", pad);
2972 }
2973 printf("\n");
2974}
2975
2976
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002977static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002978{
2979 int n;
2980 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002981 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2982 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2983 print_cmd_help(&wpa_cli_commands[n], " ");
2984 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002985}
2986
2987
2988static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2989{
2990 const char *c, *delim;
2991 int n;
2992 size_t len;
2993
2994 delim = os_strchr(cmd, ' ');
2995 if (delim)
2996 len = delim - cmd;
2997 else
2998 len = os_strlen(cmd);
2999
3000 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
3001 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
3002 return (wpa_cli_commands[n].flags &
3003 cli_cmd_flag_sensitive);
3004 }
3005 return 0;
3006}
3007
3008
3009static char ** wpa_list_cmd_list(void)
3010{
3011 char **res;
3012 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003013 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003014
Dmitry Shmidt68d0e3e2013-10-28 17:59:21 -07003015 count = ARRAY_SIZE(wpa_cli_commands);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003016 count += dl_list_len(&p2p_groups);
3017 count += dl_list_len(&ifnames);
3018 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003019 if (res == NULL)
3020 return NULL;
3021
3022 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3023 res[i] = os_strdup(wpa_cli_commands[i].cmd);
3024 if (res[i] == NULL)
3025 break;
3026 }
3027
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003028 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
3029 size_t len = 8 + os_strlen(e->txt);
3030 res[i] = os_malloc(len);
3031 if (res[i] == NULL)
3032 break;
3033 os_snprintf(res[i], len, "ifname=%s", e->txt);
3034 i++;
3035 }
3036
3037 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
3038 res[i] = os_strdup(e->txt);
3039 if (res[i] == NULL)
3040 break;
3041 i++;
3042 }
3043
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003044 return res;
3045}
3046
3047
3048static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
3049 int pos)
3050{
3051 int i;
3052
3053 for (i = 0; wpa_cli_commands[i].cmd; i++) {
3054 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003055 if (wpa_cli_commands[i].completion)
3056 return wpa_cli_commands[i].completion(str,
3057 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003058 edit_clear_line();
3059 printf("\r%s\n", wpa_cli_commands[i].usage);
3060 edit_redraw();
3061 break;
3062 }
3063 }
3064
3065 return NULL;
3066}
3067
3068
3069static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
3070{
3071 char **res;
3072 const char *end;
3073 char *cmd;
3074
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003075 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
3076 end = os_strchr(str, ' ');
3077 if (end && pos > end - str) {
3078 pos -= end - str + 1;
3079 str = end + 1;
3080 }
3081 }
3082
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003083 end = os_strchr(str, ' ');
3084 if (end == NULL || str + pos < end)
3085 return wpa_list_cmd_list();
3086
3087 cmd = os_malloc(pos + 1);
3088 if (cmd == NULL)
3089 return NULL;
3090 os_memcpy(cmd, str, pos);
3091 cmd[end - str] = '\0';
3092 res = wpa_cli_cmd_completion(cmd, str, pos);
3093 os_free(cmd);
3094 return res;
3095}
3096
3097
3098static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3099{
3100 struct wpa_cli_cmd *cmd, *match = NULL;
3101 int count;
3102 int ret = 0;
3103
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003104 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3105 ifname_prefix = argv[0] + 7;
3106 argv = &argv[1];
3107 argc--;
3108 } else
3109 ifname_prefix = NULL;
3110
3111 if (argc == 0)
3112 return -1;
3113
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003114 count = 0;
3115 cmd = wpa_cli_commands;
3116 while (cmd->cmd) {
3117 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3118 {
3119 match = cmd;
3120 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3121 /* we have an exact match */
3122 count = 1;
3123 break;
3124 }
3125 count++;
3126 }
3127 cmd++;
3128 }
3129
3130 if (count > 1) {
3131 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3132 cmd = wpa_cli_commands;
3133 while (cmd->cmd) {
3134 if (os_strncasecmp(cmd->cmd, argv[0],
3135 os_strlen(argv[0])) == 0) {
3136 printf(" %s", cmd->cmd);
3137 }
3138 cmd++;
3139 }
3140 printf("\n");
3141 ret = 1;
3142 } else if (count == 0) {
3143 printf("Unknown command '%s'\n", argv[0]);
3144 ret = 1;
3145 } else {
3146 ret = match->handler(ctrl, argc - 1, &argv[1]);
3147 }
3148
3149 return ret;
3150}
3151
3152
3153static int str_match(const char *a, const char *b)
3154{
3155 return os_strncmp(a, b, os_strlen(b)) == 0;
3156}
3157
3158
3159static int wpa_cli_exec(const char *program, const char *arg1,
3160 const char *arg2)
3161{
Jouni Malinen772e12c2014-10-07 10:29:35 -07003162 char *arg;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003163 size_t len;
3164 int res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003165
Jouni Malinen772e12c2014-10-07 10:29:35 -07003166 len = os_strlen(arg1) + os_strlen(arg2) + 2;
3167 arg = os_malloc(len);
3168 if (arg == NULL)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003169 return -1;
Jouni Malinen772e12c2014-10-07 10:29:35 -07003170 os_snprintf(arg, len, "%s %s", arg1, arg2);
3171 res = os_exec(program, arg, 1);
3172 os_free(arg);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003173
Jouni Malinen772e12c2014-10-07 10:29:35 -07003174 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003175}
3176
3177
3178static void wpa_cli_action_process(const char *msg)
3179{
3180 const char *pos;
3181 char *copy = NULL, *id, *pos2;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003182 const char *ifname = ctrl_ifname;
3183 char ifname_buf[100];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003184
3185 pos = msg;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003186 if (os_strncmp(pos, "IFNAME=", 7) == 0) {
3187 const char *end;
3188 end = os_strchr(pos + 7, ' ');
3189 if (end && (unsigned int) (end - pos) < sizeof(ifname_buf)) {
3190 pos += 7;
3191 os_memcpy(ifname_buf, pos, end - pos);
3192 ifname_buf[end - pos] = '\0';
3193 ifname = ifname_buf;
3194 pos = end + 1;
3195 }
3196 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003197 if (*pos == '<') {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003198 const char *prev = pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003199 /* skip priority */
3200 pos = os_strchr(pos, '>');
3201 if (pos)
3202 pos++;
3203 else
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003204 pos = prev;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003205 }
3206
3207 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3208 int new_id = -1;
3209 os_unsetenv("WPA_ID");
3210 os_unsetenv("WPA_ID_STR");
3211 os_unsetenv("WPA_CTRL_DIR");
3212
3213 pos = os_strstr(pos, "[id=");
3214 if (pos)
3215 copy = os_strdup(pos + 4);
3216
3217 if (copy) {
3218 pos2 = id = copy;
3219 while (*pos2 && *pos2 != ' ')
3220 pos2++;
3221 *pos2++ = '\0';
3222 new_id = atoi(id);
3223 os_setenv("WPA_ID", id, 1);
3224 while (*pos2 && *pos2 != '=')
3225 pos2++;
3226 if (*pos2 == '=')
3227 pos2++;
3228 id = pos2;
3229 while (*pos2 && *pos2 != ']')
3230 pos2++;
3231 *pos2 = '\0';
3232 os_setenv("WPA_ID_STR", id, 1);
3233 os_free(copy);
3234 }
3235
3236 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3237
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003238 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003239 wpa_cli_connected = 1;
3240 wpa_cli_last_id = new_id;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003241 wpa_cli_exec(action_file, ifname, "CONNECTED");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003242 }
3243 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3244 if (wpa_cli_connected) {
3245 wpa_cli_connected = 0;
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003246 wpa_cli_exec(action_file, ifname, "DISCONNECTED");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003247 }
3248 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003249 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003250 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003251 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003252 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003253 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003254 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003255 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003256 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003257 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003258 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003259 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003260 } else if (str_match(pos, WPS_EVENT_FAIL)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003261 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003262 } else if (str_match(pos, AP_STA_CONNECTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003263 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003264 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003265 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003266 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003267 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003268 } else if (str_match(pos, HS20_SUBSCRIPTION_REMEDIATION)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003269 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidtf21452a2014-02-26 10:55:25 -08003270 } else if (str_match(pos, HS20_DEAUTH_IMMINENT_NOTICE)) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003271 wpa_cli_exec(action_file, ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003272 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3273 printf("wpa_supplicant is terminating - stop monitoring\n");
3274 wpa_cli_quit = 1;
3275 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003276}
3277
3278
3279#ifndef CONFIG_ANSI_C_EXTRA
3280static void wpa_cli_action_cb(char *msg, size_t len)
3281{
3282 wpa_cli_action_process(msg);
3283}
3284#endif /* CONFIG_ANSI_C_EXTRA */
3285
3286
3287static void wpa_cli_reconnect(void)
3288{
3289 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003290 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3291 return;
3292
3293 if (interactive) {
3294 edit_clear_line();
3295 printf("\rConnection to wpa_supplicant re-established\n");
3296 edit_redraw();
3297 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003298}
3299
3300
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003301static void cli_event(const char *str)
3302{
3303 const char *start, *s;
3304
3305 start = os_strchr(str, '>');
3306 if (start == NULL)
3307 return;
3308
3309 start++;
3310
3311 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3312 s = os_strchr(start, ' ');
3313 if (s == NULL)
3314 return;
3315 s = os_strchr(s + 1, ' ');
3316 if (s == NULL)
3317 return;
3318 cli_txt_list_add(&bsses, s + 1);
3319 return;
3320 }
3321
3322 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3323 s = os_strchr(start, ' ');
3324 if (s == NULL)
3325 return;
3326 s = os_strchr(s + 1, ' ');
3327 if (s == NULL)
3328 return;
3329 cli_txt_list_del_addr(&bsses, s + 1);
3330 return;
3331 }
3332
3333#ifdef CONFIG_P2P
3334 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3335 s = os_strstr(start, " p2p_dev_addr=");
3336 if (s == NULL)
3337 return;
3338 cli_txt_list_add_addr(&p2p_peers, s + 14);
3339 return;
3340 }
3341
3342 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3343 s = os_strstr(start, " p2p_dev_addr=");
3344 if (s == NULL)
3345 return;
3346 cli_txt_list_del_addr(&p2p_peers, s + 14);
3347 return;
3348 }
3349
3350 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3351 s = os_strchr(start, ' ');
3352 if (s == NULL)
3353 return;
3354 cli_txt_list_add_word(&p2p_groups, s + 1);
3355 return;
3356 }
3357
3358 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3359 s = os_strchr(start, ' ');
3360 if (s == NULL)
3361 return;
3362 cli_txt_list_del_word(&p2p_groups, s + 1);
3363 return;
3364 }
3365#endif /* CONFIG_P2P */
3366}
3367
3368
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003369static int check_terminating(const char *msg)
3370{
3371 const char *pos = msg;
3372
3373 if (*pos == '<') {
3374 /* skip priority */
3375 pos = os_strchr(pos, '>');
3376 if (pos)
3377 pos++;
3378 else
3379 pos = msg;
3380 }
3381
3382 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3383 edit_clear_line();
3384 printf("\rConnection to wpa_supplicant lost - trying to "
3385 "reconnect\n");
3386 edit_redraw();
3387 wpa_cli_attached = 0;
3388 wpa_cli_close_connection();
3389 return 1;
3390 }
3391
3392 return 0;
3393}
3394
3395
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003396static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3397{
3398 if (ctrl_conn == NULL) {
3399 wpa_cli_reconnect();
3400 return;
3401 }
3402 while (wpa_ctrl_pending(ctrl) > 0) {
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003403 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003404 size_t len = sizeof(buf) - 1;
3405 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3406 buf[len] = '\0';
3407 if (action_monitor)
3408 wpa_cli_action_process(buf);
3409 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003410 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003411 if (wpa_cli_show_event(buf)) {
3412 edit_clear_line();
3413 printf("\r%s\n", buf);
3414 edit_redraw();
3415 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003416
3417 if (interactive && check_terminating(buf) > 0)
3418 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003419 }
3420 } else {
3421 printf("Could not read pending message.\n");
3422 break;
3423 }
3424 }
3425
3426 if (wpa_ctrl_pending(ctrl) < 0) {
3427 printf("Connection to wpa_supplicant lost - trying to "
3428 "reconnect\n");
3429 wpa_cli_reconnect();
3430 }
3431}
3432
3433#define max_args 10
3434
3435static int tokenize_cmd(char *cmd, char *argv[])
3436{
3437 char *pos;
3438 int argc = 0;
3439
3440 pos = cmd;
3441 for (;;) {
3442 while (*pos == ' ')
3443 pos++;
3444 if (*pos == '\0')
3445 break;
3446 argv[argc] = pos;
3447 argc++;
3448 if (argc == max_args)
3449 break;
3450 if (*pos == '"') {
3451 char *pos2 = os_strrchr(pos, '"');
3452 if (pos2)
3453 pos = pos2 + 1;
3454 }
3455 while (*pos != '\0' && *pos != ' ')
3456 pos++;
3457 if (*pos == ' ')
3458 *pos++ = '\0';
3459 }
3460
3461 return argc;
3462}
3463
3464
3465static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3466{
Dmitry Shmidt661b4f72014-09-29 14:58:27 -07003467 if (ctrl_conn) {
3468 int res;
3469 char *prefix = ifname_prefix;
3470
3471 ifname_prefix = NULL;
3472 res = _wpa_ctrl_command(ctrl_conn, "PING", 0);
3473 ifname_prefix = prefix;
3474 if (res) {
3475 printf("Connection to wpa_supplicant lost - trying to "
3476 "reconnect\n");
3477 wpa_cli_close_connection();
3478 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003479 }
3480 if (!ctrl_conn)
3481 wpa_cli_reconnect();
3482 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3483}
3484
3485
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003486static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3487{
3488 wpa_cli_recv_pending(mon_conn, 0);
3489}
3490
3491
3492static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3493{
3494 char *argv[max_args];
3495 int argc;
3496 argc = tokenize_cmd(cmd, argv);
3497 if (argc)
3498 wpa_request(ctrl_conn, argc, argv);
3499}
3500
3501
3502static void wpa_cli_edit_eof_cb(void *ctx)
3503{
3504 eloop_terminate();
3505}
3506
3507
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003508static int warning_displayed = 0;
3509static char *hfile = NULL;
3510static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003511
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003512static void start_edit(void)
3513{
3514 char *home;
3515 char *ps = NULL;
3516
3517#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3518 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3519#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003520
3521 home = getenv("HOME");
3522 if (home) {
3523 const char *fname = ".wpa_cli_history";
3524 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3525 hfile = os_malloc(hfile_len);
3526 if (hfile)
3527 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3528 }
3529
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003530 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3531 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3532 eloop_terminate();
3533 return;
3534 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003535
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003536 edit_started = 1;
3537 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3538}
3539
3540
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003541static void update_bssid_list(struct wpa_ctrl *ctrl)
3542{
3543 char buf[4096];
3544 size_t len = sizeof(buf);
3545 int ret;
3546 char *cmd = "BSS RANGE=ALL MASK=0x2";
3547 char *pos, *end;
3548
3549 if (ctrl == NULL)
3550 return;
3551 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3552 if (ret < 0)
3553 return;
3554 buf[len] = '\0';
3555
3556 pos = buf;
3557 while (pos) {
3558 pos = os_strstr(pos, "bssid=");
3559 if (pos == NULL)
3560 break;
3561 pos += 6;
3562 end = os_strchr(pos, '\n');
3563 if (end == NULL)
3564 break;
3565 *end = '\0';
3566 cli_txt_list_add(&bsses, pos);
3567 pos = end + 1;
3568 }
3569}
3570
3571
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003572static void update_ifnames(struct wpa_ctrl *ctrl)
3573{
3574 char buf[4096];
3575 size_t len = sizeof(buf);
3576 int ret;
3577 char *cmd = "INTERFACES";
3578 char *pos, *end;
3579 char txt[200];
3580
3581 cli_txt_list_flush(&ifnames);
3582
3583 if (ctrl == NULL)
3584 return;
3585 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3586 if (ret < 0)
3587 return;
3588 buf[len] = '\0';
3589
3590 pos = buf;
3591 while (pos) {
3592 end = os_strchr(pos, '\n');
3593 if (end == NULL)
3594 break;
3595 *end = '\0';
3596 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3597 if (ret > 0 && ret < (int) sizeof(txt))
3598 cli_txt_list_add(&ifnames, txt);
3599 pos = end + 1;
3600 }
3601}
3602
3603
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003604static void try_connection(void *eloop_ctx, void *timeout_ctx)
3605{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003606 if (ctrl_conn)
3607 goto done;
3608
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003609 if (ctrl_ifname == NULL)
3610 ctrl_ifname = wpa_cli_get_default_ifname();
3611
3612 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3613 if (!warning_displayed) {
3614 printf("Could not connect to wpa_supplicant: "
3615 "%s - re-trying\n", ctrl_ifname);
3616 warning_displayed = 1;
3617 }
3618 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3619 return;
3620 }
3621
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003622 update_bssid_list(ctrl_conn);
3623
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003624 if (warning_displayed)
3625 printf("Connection established.\n");
3626
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003627done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003628 start_edit();
3629}
3630
3631
3632static void wpa_cli_interactive(void)
3633{
3634 printf("\nInteractive mode\n\n");
3635
3636 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003637 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003638 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003639
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003640 cli_txt_list_flush(&p2p_peers);
3641 cli_txt_list_flush(&p2p_groups);
3642 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003643 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003644 if (edit_started)
3645 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003646 os_free(hfile);
3647 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3648 wpa_cli_close_connection();
3649}
3650
3651
3652static void wpa_cli_action(struct wpa_ctrl *ctrl)
3653{
3654#ifdef CONFIG_ANSI_C_EXTRA
3655 /* TODO: ANSI C version(?) */
3656 printf("Action processing not supported in ANSI C build.\n");
3657#else /* CONFIG_ANSI_C_EXTRA */
3658 fd_set rfds;
3659 int fd, res;
3660 struct timeval tv;
3661 char buf[256]; /* note: large enough to fit in unsolicited messages */
3662 size_t len;
3663
3664 fd = wpa_ctrl_get_fd(ctrl);
3665
3666 while (!wpa_cli_quit) {
3667 FD_ZERO(&rfds);
3668 FD_SET(fd, &rfds);
3669 tv.tv_sec = ping_interval;
3670 tv.tv_usec = 0;
3671 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3672 if (res < 0 && errno != EINTR) {
3673 perror("select");
3674 break;
3675 }
3676
3677 if (FD_ISSET(fd, &rfds))
3678 wpa_cli_recv_pending(ctrl, 1);
3679 else {
3680 /* verify that connection is still working */
3681 len = sizeof(buf) - 1;
3682 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3683 wpa_cli_action_cb) < 0 ||
3684 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3685 printf("wpa_supplicant did not reply to PING "
3686 "command - exiting\n");
3687 break;
3688 }
3689 }
3690 }
3691#endif /* CONFIG_ANSI_C_EXTRA */
3692}
3693
3694
3695static void wpa_cli_cleanup(void)
3696{
3697 wpa_cli_close_connection();
3698 if (pid_file)
3699 os_daemonize_terminate(pid_file);
3700
3701 os_program_deinit();
3702}
3703
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003704
3705static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003706{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003707 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003708}
3709
3710
3711static char * wpa_cli_get_default_ifname(void)
3712{
3713 char *ifname = NULL;
3714
3715#ifdef CONFIG_CTRL_IFACE_UNIX
3716 struct dirent *dent;
3717 DIR *dir = opendir(ctrl_iface_dir);
3718 if (!dir) {
3719#ifdef ANDROID
3720 char ifprop[PROPERTY_VALUE_MAX];
3721 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3722 ifname = os_strdup(ifprop);
3723 printf("Using interface '%s'\n", ifname);
3724 return ifname;
3725 }
3726#endif /* ANDROID */
3727 return NULL;
3728 }
3729 while ((dent = readdir(dir))) {
3730#ifdef _DIRENT_HAVE_D_TYPE
3731 /*
3732 * Skip the file if it is not a socket. Also accept
3733 * DT_UNKNOWN (0) in case the C library or underlying
3734 * file system does not support d_type.
3735 */
3736 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3737 continue;
3738#endif /* _DIRENT_HAVE_D_TYPE */
3739 if (os_strcmp(dent->d_name, ".") == 0 ||
3740 os_strcmp(dent->d_name, "..") == 0)
3741 continue;
3742 printf("Selected interface '%s'\n", dent->d_name);
3743 ifname = os_strdup(dent->d_name);
3744 break;
3745 }
3746 closedir(dir);
3747#endif /* CONFIG_CTRL_IFACE_UNIX */
3748
3749#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003750 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003751 size_t len;
3752 struct wpa_ctrl *ctrl;
3753 int ret;
3754
3755 ctrl = wpa_ctrl_open(NULL);
3756 if (ctrl == NULL)
3757 return NULL;
3758
3759 len = sizeof(buf) - 1;
3760 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3761 if (ret >= 0) {
3762 buf[len] = '\0';
3763 pos = os_strchr(buf, '\n');
3764 if (pos)
3765 *pos = '\0';
3766 ifname = os_strdup(buf);
3767 }
3768 wpa_ctrl_close(ctrl);
3769#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3770
3771 return ifname;
3772}
3773
3774
3775int main(int argc, char *argv[])
3776{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003777 int c;
3778 int daemonize = 0;
3779 int ret = 0;
3780 const char *global = NULL;
3781
3782 if (os_program_init())
3783 return -1;
3784
3785 for (;;) {
3786 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3787 if (c < 0)
3788 break;
3789 switch (c) {
3790 case 'a':
3791 action_file = optarg;
3792 break;
3793 case 'B':
3794 daemonize = 1;
3795 break;
3796 case 'g':
3797 global = optarg;
3798 break;
3799 case 'G':
3800 ping_interval = atoi(optarg);
3801 break;
3802 case 'h':
3803 usage();
3804 return 0;
3805 case 'v':
3806 printf("%s\n", wpa_cli_version);
3807 return 0;
3808 case 'i':
3809 os_free(ctrl_ifname);
3810 ctrl_ifname = os_strdup(optarg);
3811 break;
3812 case 'p':
3813 ctrl_iface_dir = optarg;
3814 break;
3815 case 'P':
3816 pid_file = optarg;
3817 break;
3818 default:
3819 usage();
3820 return -1;
3821 }
3822 }
3823
3824 interactive = (argc == optind) && (action_file == NULL);
3825
3826 if (interactive)
3827 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3828
3829 if (eloop_init())
3830 return -1;
3831
3832 if (global) {
3833#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3834 ctrl_conn = wpa_ctrl_open(NULL);
3835#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3836 ctrl_conn = wpa_ctrl_open(global);
3837#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3838 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003839 fprintf(stderr, "Failed to connect to wpa_supplicant "
3840 "global interface: %s error: %s\n",
3841 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003842 return -1;
3843 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003844
3845 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003846 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003847 mon_conn = wpa_ctrl_open(global);
3848 if (mon_conn) {
3849 if (wpa_ctrl_attach(mon_conn) == 0) {
3850 wpa_cli_attached = 1;
3851 eloop_register_read_sock(
3852 wpa_ctrl_get_fd(mon_conn),
3853 wpa_cli_mon_receive,
3854 NULL, NULL);
3855 } else {
3856 printf("Failed to open monitor "
3857 "connection through global "
3858 "control interface\n");
3859 }
3860 }
3861 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003862 }
3863
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003864 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003865
3866 if (ctrl_ifname == NULL)
3867 ctrl_ifname = wpa_cli_get_default_ifname();
3868
3869 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003870 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003871 } else {
3872 if (!global &&
3873 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003874 fprintf(stderr, "Failed to connect to non-global "
3875 "ctrl_ifname: %s error: %s\n",
3876 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003877 return -1;
3878 }
3879
3880 if (action_file) {
3881 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3882 wpa_cli_attached = 1;
3883 } else {
3884 printf("Warning: Failed to attach to "
3885 "wpa_supplicant.\n");
3886 return -1;
3887 }
3888 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003889
3890 if (daemonize && os_daemonize(pid_file))
3891 return -1;
3892
3893 if (action_file)
3894 wpa_cli_action(ctrl_conn);
3895 else
3896 ret = wpa_request(ctrl_conn, argc - optind,
3897 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003898 }
3899
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003900 os_free(ctrl_ifname);
3901 eloop_destroy();
3902 wpa_cli_cleanup();
3903
3904 return ret;
3905}
3906
3907#else /* CONFIG_CTRL_IFACE */
3908int main(int argc, char *argv[])
3909{
3910 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3911 return -1;
3912}
3913#endif /* CONFIG_CTRL_IFACE */