blob: 20cd45e3425bb5d42238e68c3bee6afef8942bd0 [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 Shmidta54fa5f2013-01-15 13:53:35 -080031"Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032
33
34static const char *wpa_cli_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080035"This software may be distributed under the terms of the BSD license.\n"
36"See README for more details.\n";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037
38static const char *wpa_cli_full_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080039"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040"\n"
41"Redistribution and use in source and binary forms, with or without\n"
42"modification, are permitted provided that the following conditions are\n"
43"met:\n"
44"\n"
45"1. Redistributions of source code must retain the above copyright\n"
46" notice, this list of conditions and the following disclaimer.\n"
47"\n"
48"2. Redistributions in binary form must reproduce the above copyright\n"
49" notice, this list of conditions and the following disclaimer in the\n"
50" documentation and/or other materials provided with the distribution.\n"
51"\n"
52"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53" names of its contributors may be used to endorse or promote products\n"
54" derived from this software without specific prior written permission.\n"
55"\n"
56"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67"\n";
68
69static struct wpa_ctrl *ctrl_conn;
70static struct wpa_ctrl *mon_conn;
71static int wpa_cli_quit = 0;
72static int wpa_cli_attached = 0;
73static int wpa_cli_connected = 0;
74static int wpa_cli_last_id = 0;
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
82static int ping_interval = 5;
83static int interactive = 0;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070084static char *ifname_prefix = NULL;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -070085#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
86static char* redirect_interface = NULL;
87#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070088
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080089struct cli_txt_entry {
90 struct dl_list list;
91 char *txt;
92};
93
94static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
95static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
96static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070097static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080098
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070099
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700100static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700101static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700102static void wpa_cli_close_connection(void);
103static char * wpa_cli_get_default_ifname(void);
104static char ** wpa_list_cmd_list(void);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700105
106
107static void usage(void)
108{
109 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
110 "[-a<action file>] \\\n"
111 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
112 "[command..]\n"
113 " -h = help (show this usage text)\n"
114 " -v = shown version information\n"
115 " -a = run in daemon mode executing the action file based on "
116 "events from\n"
117 " wpa_supplicant\n"
118 " -B = run a daemon in the background\n"
119 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
120 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700121 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700122}
123
124
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800125static void cli_txt_list_free(struct cli_txt_entry *e)
126{
127 dl_list_del(&e->list);
128 os_free(e->txt);
129 os_free(e);
130}
131
132
133static void cli_txt_list_flush(struct dl_list *list)
134{
135 struct cli_txt_entry *e;
136 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
137 cli_txt_list_free(e);
138}
139
140
141static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
142 const char *txt)
143{
144 struct cli_txt_entry *e;
145 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
146 if (os_strcmp(e->txt, txt) == 0)
147 return e;
148 }
149 return NULL;
150}
151
152
153static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
154{
155 struct cli_txt_entry *e;
156 e = cli_txt_list_get(txt_list, txt);
157 if (e)
158 cli_txt_list_free(e);
159}
160
161
162static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
163{
164 u8 addr[ETH_ALEN];
165 char buf[18];
166 if (hwaddr_aton(txt, addr) < 0)
167 return;
168 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
169 cli_txt_list_del(txt_list, buf);
170}
171
172
173#ifdef CONFIG_P2P
174static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
175{
176 const char *end;
177 char *buf;
178 end = os_strchr(txt, ' ');
179 if (end == NULL)
180 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700181 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800182 if (buf == NULL)
183 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800184 cli_txt_list_del(txt_list, buf);
185 os_free(buf);
186}
187#endif /* CONFIG_P2P */
188
189
190static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
191{
192 struct cli_txt_entry *e;
193 e = cli_txt_list_get(txt_list, txt);
194 if (e)
195 return 0;
196 e = os_zalloc(sizeof(*e));
197 if (e == NULL)
198 return -1;
199 e->txt = os_strdup(txt);
200 if (e->txt == NULL) {
201 os_free(e);
202 return -1;
203 }
204 dl_list_add(txt_list, &e->list);
205 return 0;
206}
207
208
209#ifdef CONFIG_P2P
210static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
211{
212 u8 addr[ETH_ALEN];
213 char buf[18];
214 if (hwaddr_aton(txt, addr) < 0)
215 return -1;
216 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
217 return cli_txt_list_add(txt_list, buf);
218}
219
220
221static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
222{
223 const char *end;
224 char *buf;
225 int ret;
226 end = os_strchr(txt, ' ');
227 if (end == NULL)
228 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700229 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800230 if (buf == NULL)
231 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800232 ret = cli_txt_list_add(txt_list, buf);
233 os_free(buf);
234 return ret;
235}
236#endif /* CONFIG_P2P */
237
238
239static char ** cli_txt_list_array(struct dl_list *txt_list)
240{
241 unsigned int i, count = dl_list_len(txt_list);
242 char **res;
243 struct cli_txt_entry *e;
244
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700245 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800246 if (res == NULL)
247 return NULL;
248
249 i = 0;
250 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
251 res[i] = os_strdup(e->txt);
252 if (res[i] == NULL)
253 break;
254 i++;
255 }
256
257 return res;
258}
259
260
261static int get_cmd_arg_num(const char *str, int pos)
262{
263 int arg = 0, i;
264
265 for (i = 0; i <= pos; i++) {
266 if (str[i] != ' ') {
267 arg++;
268 while (i <= pos && str[i] != ' ')
269 i++;
270 }
271 }
272
273 if (arg > 0)
274 arg--;
275 return arg;
276}
277
278
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700279static int str_starts(const char *src, const char *match)
280{
281 return os_strncmp(src, match, os_strlen(match)) == 0;
282}
283
284
285static int wpa_cli_show_event(const char *event)
286{
287 const char *start;
288
289 start = os_strchr(event, '>');
290 if (start == NULL)
291 return 1;
292
293 start++;
294 /*
295 * Skip BSS added/removed events since they can be relatively frequent
296 * and are likely of not much use for an interactive user.
297 */
298 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
299 str_starts(start, WPA_EVENT_BSS_REMOVED))
300 return 0;
301
302 return 1;
303}
304
305
306static int wpa_cli_open_connection(const char *ifname, int attach)
307{
308#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
309 ctrl_conn = wpa_ctrl_open(ifname);
310 if (ctrl_conn == NULL)
311 return -1;
312
313 if (attach && interactive)
314 mon_conn = wpa_ctrl_open(ifname);
315 else
316 mon_conn = NULL;
317#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
318 char *cfile = NULL;
319 int flen, res;
320
321 if (ifname == NULL)
322 return -1;
323
324#ifdef ANDROID
325 if (access(ctrl_iface_dir, F_OK) < 0) {
326 cfile = os_strdup(ifname);
327 if (cfile == NULL)
328 return -1;
329 }
330#endif /* ANDROID */
331
332 if (cfile == NULL) {
333 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
334 cfile = os_malloc(flen);
335 if (cfile == NULL)
336 return -1;
337 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
338 ifname);
339 if (res < 0 || res >= flen) {
340 os_free(cfile);
341 return -1;
342 }
343 }
344
345 ctrl_conn = wpa_ctrl_open(cfile);
346 if (ctrl_conn == NULL) {
347 os_free(cfile);
348 return -1;
349 }
350
351 if (attach && interactive)
352 mon_conn = wpa_ctrl_open(cfile);
353 else
354 mon_conn = NULL;
355 os_free(cfile);
356#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
357
358 if (mon_conn) {
359 if (wpa_ctrl_attach(mon_conn) == 0) {
360 wpa_cli_attached = 1;
361 if (interactive)
362 eloop_register_read_sock(
363 wpa_ctrl_get_fd(mon_conn),
364 wpa_cli_mon_receive, NULL, NULL);
365 } else {
366 printf("Warning: Failed to attach to "
367 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700368 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700369 return -1;
370 }
371 }
372
373 return 0;
374}
375
376
377static void wpa_cli_close_connection(void)
378{
379 if (ctrl_conn == NULL)
380 return;
381
382 if (wpa_cli_attached) {
383 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
384 wpa_cli_attached = 0;
385 }
386 wpa_ctrl_close(ctrl_conn);
387 ctrl_conn = NULL;
388 if (mon_conn) {
389 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
390 wpa_ctrl_close(mon_conn);
391 mon_conn = NULL;
392 }
393}
394
395
396static void wpa_cli_msg_cb(char *msg, size_t len)
397{
398 printf("%s\n", msg);
399}
400
401
402static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
403{
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700404 char buf[4096];
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -0700405#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
406 char _cmd[256];
407#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700408 size_t len;
409 int ret;
410
411 if (ctrl_conn == NULL) {
412 printf("Not connected to wpa_supplicant - command dropped.\n");
413 return -1;
414 }
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -0700415#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
416 if (redirect_interface) {
417 char *arg;
418 arg = os_strchr(cmd, ' ');
419 if (arg) {
420 *arg++ = '\0';
421 ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s %s", cmd, redirect_interface, arg);
422 }
423 else {
424 ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s", cmd, redirect_interface);
425 }
426 cmd = _cmd;
427 os_free(redirect_interface);
428 redirect_interface = NULL;
429 }
430#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700431 len = sizeof(buf) - 1;
432 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
433 wpa_cli_msg_cb);
434 if (ret == -2) {
435 printf("'%s' command timed out.\n", cmd);
436 return -2;
437 } else if (ret < 0) {
438 printf("'%s' command failed.\n", cmd);
439 return -1;
440 }
441 if (print) {
442 buf[len] = '\0';
443 printf("%s", buf);
444 if (interactive && len > 0 && buf[len - 1] != '\n')
445 printf("\n");
446 }
447 return 0;
448}
449
450
451static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
452{
453 return _wpa_ctrl_command(ctrl, cmd, 1);
454}
455
456
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700457static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
458 char *argv[])
459{
460 int i, res;
461 char *pos, *end;
462
463 pos = buf;
464 end = buf + buflen;
465
466 res = os_snprintf(pos, end - pos, "%s", cmd);
467 if (res < 0 || res >= end - pos)
468 goto fail;
469 pos += res;
470
471 for (i = 0; i < argc; i++) {
472 res = os_snprintf(pos, end - pos, " %s", argv[i]);
473 if (res < 0 || res >= end - pos)
474 goto fail;
475 pos += res;
476 }
477
478 buf[buflen - 1] = '\0';
479 return 0;
480
481fail:
482 printf("Too long command\n");
483 return -1;
484}
485
486
487static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
488 int argc, char *argv[])
489{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700490 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700491 if (argc < min_args) {
492 printf("Invalid %s command - at least %d argument%s "
493 "required.\n", cmd, min_args,
494 min_args > 1 ? "s are" : " is");
495 return -1;
496 }
497 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
498 return -1;
499 return wpa_ctrl_command(ctrl, buf);
500}
501
502
503static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
504{
505 return wpa_ctrl_command(ctrl, "IFNAME");
506}
507
508
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700509static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
510{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800511 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
512 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
513 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
514 return wpa_ctrl_command(ctrl, "STATUS-WPS");
515 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700516}
517
518
519static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
520{
521 return wpa_ctrl_command(ctrl, "PING");
522}
523
524
525static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
526{
527 return wpa_ctrl_command(ctrl, "RELOG");
528}
529
530
531static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
532{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700533 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700534}
535
536
537static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
538{
539 return wpa_ctrl_command(ctrl, "MIB");
540}
541
542
543static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
544{
545 return wpa_ctrl_command(ctrl, "PMKSA");
546}
547
548
549static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
550{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700551 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700552 return 0;
553}
554
555
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700556static char ** wpa_cli_complete_help(const char *str, int pos)
557{
558 int arg = get_cmd_arg_num(str, pos);
559 char **res = NULL;
560
561 switch (arg) {
562 case 1:
563 res = wpa_list_cmd_list();
564 break;
565 }
566
567 return res;
568}
569
570
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700571static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
572{
573 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
574 return 0;
575}
576
577
578static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
579{
580 wpa_cli_quit = 1;
581 if (interactive)
582 eloop_terminate();
583 return 0;
584}
585
586
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700587static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
588{
589 char cmd[256];
590 int res;
591
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700592 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800593 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700594 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
595 printf("Too long SET command.\n");
596 return -1;
597 }
598 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700599 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700600
601 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
602}
603
604
605static char ** wpa_cli_complete_set(const char *str, int pos)
606{
607 int arg = get_cmd_arg_num(str, pos);
608 const char *fields[] = {
609 /* runtime values */
610 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
611 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
612 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
613 "wps_fragment_size", "wps_version_number", "ampdu",
614 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
615 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
616 "no_keep_alive",
617 /* global configuration parameters */
618 "eapol_version", "ap_scan", "disable_scan_offload",
619 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
620 "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
621 "driver_param", "dot11RSNAConfigPMKLifetime",
622 "dot11RSNAConfigPMKReauthThreshold",
623 "dot11RSNAConfigSATimeout",
624 "update_config", "load_dynamic_eap", "uuid", "device_name",
625 "manufacturer", "model_name", "model_number", "serial_number",
626 "device_type", "os_version", "config_methods",
627 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
628 "p2p_listen_reg_class", "p2p_listen_channel",
629 "p2p_oper_reg_class", "p2p_oper_channel",
630 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
631 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
632 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
633 "p2p_ignore_shared_freq", "country", "bss_max_count",
634 "bss_expiration_age", "bss_expiration_scan_count",
635 "filter_ssids", "filter_rssi", "max_num_sta",
636 "disassoc_low_ack", "hs20", "interworking", "hessid",
637 "access_network_type", "pbc_in_m1", "autoscan",
638 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
639 "wps_nfc_dev_pw", "ext_password_backend",
640 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
641 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
642 "ignore_old_scan_res", "freq_list"
643 };
644 int i, num_fields = sizeof(fields) / sizeof(fields[0]);
645
646 if (arg == 1) {
647 char **res = os_calloc(num_fields + 1, sizeof(char *));
648 if (res == NULL)
649 return NULL;
650 for (i = 0; i < num_fields; i++) {
651 res[i] = os_strdup(fields[i]);
652 if (res[i] == NULL)
653 return res;
654 }
655 return res;
656 }
657
658 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
659 return cli_txt_list_array(&bsses);
660
661 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700662}
663
664
665static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
666{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700667 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700668}
669
670
671static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
672{
673 return wpa_ctrl_command(ctrl, "LOGOFF");
674}
675
676
677static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
678{
679 return wpa_ctrl_command(ctrl, "LOGON");
680}
681
682
683static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
684 char *argv[])
685{
686 return wpa_ctrl_command(ctrl, "REASSOCIATE");
687}
688
689
690static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
691 char *argv[])
692{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700693 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700694}
695
696
697static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
698{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700699 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700700}
701
702
703static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
704 char *argv[])
705{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700706 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707}
708
709
710static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
711 char *argv[])
712{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700713 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700714}
715
716
717static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
718 char *argv[])
719{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700720 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700721}
722
723
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700724static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
725{
726 char cmd[256];
727 int res;
728
729 if (argc < 1)
730 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
731 else
732 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
733 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
734 printf("Too long BSS_FLUSH command.\n");
735 return -1;
736 }
737 return wpa_ctrl_command(ctrl, cmd);
738}
739
740
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700741static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
742 char *argv[])
743{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700744 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700745}
746
747
748static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
749{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700750 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700751}
752
753
754static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
755{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700756 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700757}
758
759
760static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
761{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700762 if (argc == 0) {
763 printf("Invalid WPS_PIN command: need one or two arguments:\n"
764 "- BSSID: use 'any' to select any\n"
765 "- PIN: optional, used only with devices that have no "
766 "display\n");
767 return -1;
768 }
769
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700770 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700771}
772
773
774static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
775 char *argv[])
776{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700777 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700778}
779
780
781static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
782 char *argv[])
783{
784 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
785}
786
787
Dmitry Shmidt04949592012-07-19 12:16:46 -0700788#ifdef CONFIG_WPS_NFC
789
790static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
791{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700792 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700793}
794
795
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800796static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
797 char *argv[])
798{
799 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
800}
801
802
Dmitry Shmidt04949592012-07-19 12:16:46 -0700803static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
804 char *argv[])
805{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700806 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700807}
808
809
810static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
811 char *argv[])
812{
813 int ret;
814 char *buf;
815 size_t buflen;
816
817 if (argc != 1) {
818 printf("Invalid 'wps_nfc_tag_read' command - one argument "
819 "is required.\n");
820 return -1;
821 }
822
823 buflen = 18 + os_strlen(argv[0]);
824 buf = os_malloc(buflen);
825 if (buf == NULL)
826 return -1;
827 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
828
829 ret = wpa_ctrl_command(ctrl, buf);
830 os_free(buf);
831
832 return ret;
833}
834
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800835
836static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
837 char *argv[])
838{
839 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
840}
841
842
843static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
844 char *argv[])
845{
846 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
847}
848
849
850static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
851 char *argv[])
852{
853 int ret;
854 char *buf;
855 size_t buflen;
856
857 if (argc != 1) {
858 printf("Invalid 'nfc_rx_handover_req' command - one argument "
859 "is required.\n");
860 return -1;
861 }
862
863 buflen = 21 + os_strlen(argv[0]);
864 buf = os_malloc(buflen);
865 if (buf == NULL)
866 return -1;
867 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
868
869 ret = wpa_ctrl_command(ctrl, buf);
870 os_free(buf);
871
872 return ret;
873}
874
875
876static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
877 char *argv[])
878{
879 int ret;
880 char *buf;
881 size_t buflen;
882
883 if (argc != 1) {
884 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
885 "is required.\n");
886 return -1;
887 }
888
889 buflen = 21 + os_strlen(argv[0]);
890 buf = os_malloc(buflen);
891 if (buf == NULL)
892 return -1;
893 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
894
895 ret = wpa_ctrl_command(ctrl, buf);
896 os_free(buf);
897
898 return ret;
899}
900
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800901
902static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
903 char *argv[])
904{
905 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
906}
907
Dmitry Shmidt04949592012-07-19 12:16:46 -0700908#endif /* CONFIG_WPS_NFC */
909
910
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700911static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
912{
913 char cmd[256];
914 int res;
915
916 if (argc == 2)
917 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
918 argv[0], argv[1]);
919 else if (argc == 5 || argc == 6) {
920 char ssid_hex[2 * 32 + 1];
921 char key_hex[2 * 64 + 1];
922 int i;
923
924 ssid_hex[0] = '\0';
925 for (i = 0; i < 32; i++) {
926 if (argv[2][i] == '\0')
927 break;
928 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
929 }
930
931 key_hex[0] = '\0';
932 if (argc == 6) {
933 for (i = 0; i < 64; i++) {
934 if (argv[5][i] == '\0')
935 break;
936 os_snprintf(&key_hex[i * 2], 3, "%02x",
937 argv[5][i]);
938 }
939 }
940
941 res = os_snprintf(cmd, sizeof(cmd),
942 "WPS_REG %s %s %s %s %s %s",
943 argv[0], argv[1], ssid_hex, argv[3], argv[4],
944 key_hex);
945 } else {
946 printf("Invalid WPS_REG command: need two arguments:\n"
947 "- BSSID of the target AP\n"
948 "- AP PIN\n");
949 printf("Alternatively, six arguments can be used to "
950 "reconfigure the AP:\n"
951 "- BSSID of the target AP\n"
952 "- AP PIN\n"
953 "- new SSID\n"
954 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
955 "- new encr (NONE, WEP, TKIP, CCMP)\n"
956 "- new key\n");
957 return -1;
958 }
959
960 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
961 printf("Too long WPS_REG command.\n");
962 return -1;
963 }
964 return wpa_ctrl_command(ctrl, cmd);
965}
966
967
968static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
969 char *argv[])
970{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700971 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700972}
973
974
975static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
976 char *argv[])
977{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700978 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979}
980
981
982static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
983 char *argv[])
984{
985 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
986
987}
988
989
990static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
991 char *argv[])
992{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993 if (argc < 2) {
994 printf("Invalid WPS_ER_PIN command: need at least two "
995 "arguments:\n"
996 "- UUID: use 'any' to select any\n"
997 "- PIN: Enrollee PIN\n"
998 "optional: - Enrollee MAC address\n");
999 return -1;
1000 }
1001
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001002 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001003}
1004
1005
1006static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
1007 char *argv[])
1008{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001009 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001010}
1011
1012
1013static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
1014 char *argv[])
1015{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001016 if (argc != 2) {
1017 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1018 "- UUID: specify which AP to use\n"
1019 "- PIN: AP PIN\n");
1020 return -1;
1021 }
1022
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001023 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001024}
1025
1026
1027static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
1028 char *argv[])
1029{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001030 if (argc != 2) {
1031 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1032 "arguments:\n"
1033 "- UUID: specify which AP to use\n"
1034 "- Network configuration id\n");
1035 return -1;
1036 }
1037
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001038 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001039}
1040
1041
1042static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1043 char *argv[])
1044{
1045 char cmd[256];
1046 int res;
1047
1048 if (argc == 5 || argc == 6) {
1049 char ssid_hex[2 * 32 + 1];
1050 char key_hex[2 * 64 + 1];
1051 int i;
1052
1053 ssid_hex[0] = '\0';
1054 for (i = 0; i < 32; i++) {
1055 if (argv[2][i] == '\0')
1056 break;
1057 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1058 }
1059
1060 key_hex[0] = '\0';
1061 if (argc == 6) {
1062 for (i = 0; i < 64; i++) {
1063 if (argv[5][i] == '\0')
1064 break;
1065 os_snprintf(&key_hex[i * 2], 3, "%02x",
1066 argv[5][i]);
1067 }
1068 }
1069
1070 res = os_snprintf(cmd, sizeof(cmd),
1071 "WPS_ER_CONFIG %s %s %s %s %s %s",
1072 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1073 key_hex);
1074 } else {
1075 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1076 "- AP UUID\n"
1077 "- AP PIN\n"
1078 "- new SSID\n"
1079 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1080 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1081 "- new key\n");
1082 return -1;
1083 }
1084
1085 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1086 printf("Too long WPS_ER_CONFIG command.\n");
1087 return -1;
1088 }
1089 return wpa_ctrl_command(ctrl, cmd);
1090}
1091
1092
Dmitry Shmidt04949592012-07-19 12:16:46 -07001093#ifdef CONFIG_WPS_NFC
1094static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1095 char *argv[])
1096{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001097 if (argc != 2) {
1098 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1099 "arguments:\n"
1100 "- WPS/NDEF: token format\n"
1101 "- UUID: specify which AP to use\n");
1102 return -1;
1103 }
1104
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001105 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001106}
1107#endif /* CONFIG_WPS_NFC */
1108
1109
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001110static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1111{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001112 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001113}
1114
1115
1116static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1117{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001118 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001119}
1120
1121
1122static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1123{
1124 char cmd[256], *pos, *end;
1125 int i, ret;
1126
1127 if (argc < 2) {
1128 printf("Invalid IDENTITY command: needs two arguments "
1129 "(network id and identity)\n");
1130 return -1;
1131 }
1132
1133 end = cmd + sizeof(cmd);
1134 pos = cmd;
1135 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1136 argv[0], argv[1]);
1137 if (ret < 0 || ret >= end - pos) {
1138 printf("Too long IDENTITY command.\n");
1139 return -1;
1140 }
1141 pos += ret;
1142 for (i = 2; i < argc; i++) {
1143 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1144 if (ret < 0 || ret >= end - pos) {
1145 printf("Too long IDENTITY command.\n");
1146 return -1;
1147 }
1148 pos += ret;
1149 }
1150
1151 return wpa_ctrl_command(ctrl, cmd);
1152}
1153
1154
1155static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1156{
1157 char cmd[256], *pos, *end;
1158 int i, ret;
1159
1160 if (argc < 2) {
1161 printf("Invalid PASSWORD command: needs two arguments "
1162 "(network id and password)\n");
1163 return -1;
1164 }
1165
1166 end = cmd + sizeof(cmd);
1167 pos = cmd;
1168 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1169 argv[0], argv[1]);
1170 if (ret < 0 || ret >= end - pos) {
1171 printf("Too long PASSWORD command.\n");
1172 return -1;
1173 }
1174 pos += ret;
1175 for (i = 2; i < argc; i++) {
1176 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1177 if (ret < 0 || ret >= end - pos) {
1178 printf("Too long PASSWORD command.\n");
1179 return -1;
1180 }
1181 pos += ret;
1182 }
1183
1184 return wpa_ctrl_command(ctrl, cmd);
1185}
1186
1187
1188static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1189 char *argv[])
1190{
1191 char cmd[256], *pos, *end;
1192 int i, ret;
1193
1194 if (argc < 2) {
1195 printf("Invalid NEW_PASSWORD command: needs two arguments "
1196 "(network id and password)\n");
1197 return -1;
1198 }
1199
1200 end = cmd + sizeof(cmd);
1201 pos = cmd;
1202 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1203 argv[0], argv[1]);
1204 if (ret < 0 || ret >= end - pos) {
1205 printf("Too long NEW_PASSWORD command.\n");
1206 return -1;
1207 }
1208 pos += ret;
1209 for (i = 2; i < argc; i++) {
1210 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1211 if (ret < 0 || ret >= end - pos) {
1212 printf("Too long NEW_PASSWORD command.\n");
1213 return -1;
1214 }
1215 pos += ret;
1216 }
1217
1218 return wpa_ctrl_command(ctrl, cmd);
1219}
1220
1221
1222static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1223{
1224 char cmd[256], *pos, *end;
1225 int i, ret;
1226
1227 if (argc < 2) {
1228 printf("Invalid PIN command: needs two arguments "
1229 "(network id and pin)\n");
1230 return -1;
1231 }
1232
1233 end = cmd + sizeof(cmd);
1234 pos = cmd;
1235 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1236 argv[0], argv[1]);
1237 if (ret < 0 || ret >= end - pos) {
1238 printf("Too long PIN command.\n");
1239 return -1;
1240 }
1241 pos += ret;
1242 for (i = 2; i < argc; i++) {
1243 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1244 if (ret < 0 || ret >= end - pos) {
1245 printf("Too long PIN command.\n");
1246 return -1;
1247 }
1248 pos += ret;
1249 }
1250 return wpa_ctrl_command(ctrl, cmd);
1251}
1252
1253
1254static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1255{
1256 char cmd[256], *pos, *end;
1257 int i, ret;
1258
1259 if (argc < 2) {
1260 printf("Invalid OTP command: needs two arguments (network "
1261 "id and password)\n");
1262 return -1;
1263 }
1264
1265 end = cmd + sizeof(cmd);
1266 pos = cmd;
1267 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1268 argv[0], argv[1]);
1269 if (ret < 0 || ret >= end - pos) {
1270 printf("Too long OTP command.\n");
1271 return -1;
1272 }
1273 pos += ret;
1274 for (i = 2; i < argc; i++) {
1275 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1276 if (ret < 0 || ret >= end - pos) {
1277 printf("Too long OTP command.\n");
1278 return -1;
1279 }
1280 pos += ret;
1281 }
1282
1283 return wpa_ctrl_command(ctrl, cmd);
1284}
1285
1286
1287static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1288 char *argv[])
1289{
1290 char cmd[256], *pos, *end;
1291 int i, ret;
1292
1293 if (argc < 2) {
1294 printf("Invalid PASSPHRASE command: needs two arguments "
1295 "(network id and passphrase)\n");
1296 return -1;
1297 }
1298
1299 end = cmd + sizeof(cmd);
1300 pos = cmd;
1301 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1302 argv[0], argv[1]);
1303 if (ret < 0 || ret >= end - pos) {
1304 printf("Too long PASSPHRASE command.\n");
1305 return -1;
1306 }
1307 pos += ret;
1308 for (i = 2; i < argc; i++) {
1309 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1310 if (ret < 0 || ret >= end - pos) {
1311 printf("Too long PASSPHRASE command.\n");
1312 return -1;
1313 }
1314 pos += ret;
1315 }
1316
1317 return wpa_ctrl_command(ctrl, cmd);
1318}
1319
1320
1321static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1322{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001323 if (argc < 2) {
1324 printf("Invalid BSSID command: needs two arguments (network "
1325 "id and BSSID)\n");
1326 return -1;
1327 }
1328
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001329 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001330}
1331
1332
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001333static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1334{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001335 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001336}
1337
1338
1339static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1340{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001341 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001342}
1343
1344
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001345static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1346 char *argv[])
1347{
1348 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1349}
1350
1351
1352static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1353 char *argv[])
1354{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001355 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001356}
1357
1358
1359static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1360 char *argv[])
1361{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001362 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001363}
1364
1365
1366static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1367 char *argv[])
1368{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001369 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001370}
1371
1372
1373static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1374 char *argv[])
1375{
1376 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1377}
1378
1379
1380static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1381 char *argv[])
1382{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001383 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001384}
1385
1386
1387static void wpa_cli_show_network_variables(void)
1388{
1389 printf("set_network variables:\n"
1390 " ssid (network name, SSID)\n"
1391 " psk (WPA passphrase or pre-shared key)\n"
1392 " key_mgmt (key management protocol)\n"
1393 " identity (EAP identity)\n"
1394 " password (EAP password)\n"
1395 " ...\n"
1396 "\n"
1397 "Note: Values are entered in the same format as the "
1398 "configuration file is using,\n"
1399 "i.e., strings values need to be inside double quotation "
1400 "marks.\n"
1401 "For example: set_network 1 ssid \"network name\"\n"
1402 "\n"
1403 "Please see wpa_supplicant.conf documentation for full list "
1404 "of\navailable variables.\n");
1405}
1406
1407
1408static int wpa_cli_cmd_set_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
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001416 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001417 printf("Invalid SET_NETWORK command: needs three arguments\n"
1418 "(network id, variable name, and value)\n");
1419 return -1;
1420 }
1421
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001422 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001423}
1424
1425
1426static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1427 char *argv[])
1428{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001429 if (argc == 0) {
1430 wpa_cli_show_network_variables();
1431 return 0;
1432 }
1433
1434 if (argc != 2) {
1435 printf("Invalid GET_NETWORK command: needs two arguments\n"
1436 "(network id and variable name)\n");
1437 return -1;
1438 }
1439
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001440 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001441}
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 Shmidt8d520ff2011-05-09 14:06:53 -07001476static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1477 char *argv[])
1478{
1479 return wpa_ctrl_command(ctrl, "DISCONNECT");
1480}
1481
1482
1483static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1484 char *argv[])
1485{
1486 return wpa_ctrl_command(ctrl, "RECONNECT");
1487}
1488
1489
1490static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1491 char *argv[])
1492{
1493 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1494}
1495
1496
1497static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1498{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001499 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001500}
1501
1502
1503static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1504 char *argv[])
1505{
1506 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1507}
1508
1509
1510static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1511{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001512 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001513}
1514
1515
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001516static char ** wpa_cli_complete_bss(const char *str, int pos)
1517{
1518 int arg = get_cmd_arg_num(str, pos);
1519 char **res = NULL;
1520
1521 switch (arg) {
1522 case 1:
1523 res = cli_txt_list_array(&bsses);
1524 break;
1525 }
1526
1527 return res;
1528}
1529
1530
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001531static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1532 char *argv[])
1533{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001534 if (argc < 1 || argc > 2) {
1535 printf("Invalid GET_CAPABILITY command: need either one or "
1536 "two arguments\n");
1537 return -1;
1538 }
1539
1540 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1541 printf("Invalid GET_CAPABILITY command: second argument, "
1542 "if any, must be 'strict'\n");
1543 return -1;
1544 }
1545
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001546 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001547}
1548
1549
1550static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1551{
1552 printf("Available interfaces:\n");
1553 return wpa_ctrl_command(ctrl, "INTERFACES");
1554}
1555
1556
1557static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1558{
1559 if (argc < 1) {
1560 wpa_cli_list_interfaces(ctrl);
1561 return 0;
1562 }
1563
1564 wpa_cli_close_connection();
1565 os_free(ctrl_ifname);
1566 ctrl_ifname = os_strdup(argv[0]);
1567
1568 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1569 printf("Connected to interface '%s.\n", ctrl_ifname);
1570 } else {
1571 printf("Could not connect to interface '%s' - re-trying\n",
1572 ctrl_ifname);
1573 }
1574 return 0;
1575}
1576
1577
1578static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1579 char *argv[])
1580{
1581 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1582}
1583
1584
1585static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1586 char *argv[])
1587{
1588 return wpa_ctrl_command(ctrl, "TERMINATE");
1589}
1590
1591
1592static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1593 char *argv[])
1594{
1595 char cmd[256];
1596 int res;
1597
1598 if (argc < 1) {
1599 printf("Invalid INTERFACE_ADD command: needs at least one "
1600 "argument (interface name)\n"
1601 "All arguments: ifname confname driver ctrl_interface "
1602 "driver_param bridge_name\n");
1603 return -1;
1604 }
1605
1606 /*
1607 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1608 * <driver_param>TAB<bridge_name>
1609 */
1610 res = os_snprintf(cmd, sizeof(cmd),
1611 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1612 argv[0],
1613 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1614 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1615 argc > 5 ? argv[5] : "");
1616 if (res < 0 || (size_t) res >= sizeof(cmd))
1617 return -1;
1618 cmd[sizeof(cmd) - 1] = '\0';
1619 return wpa_ctrl_command(ctrl, cmd);
1620}
1621
1622
1623static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1624 char *argv[])
1625{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001626 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001627}
1628
1629
1630static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1631 char *argv[])
1632{
1633 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1634}
1635
1636
1637#ifdef CONFIG_AP
1638static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1639{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001640 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001641}
1642
1643
1644static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1645 char *addr, size_t addr_len)
1646{
1647 char buf[4096], *pos;
1648 size_t len;
1649 int ret;
1650
1651 if (ctrl_conn == NULL) {
1652 printf("Not connected to hostapd - command dropped.\n");
1653 return -1;
1654 }
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07001655 if (ifname_prefix) {
1656 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
1657 ifname_prefix, cmd);
1658 buf[sizeof(buf) - 1] = '\0';
1659 cmd = buf;
1660 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001661 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001662 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001663 wpa_cli_msg_cb);
1664 if (ret == -2) {
1665 printf("'%s' command timed out.\n", cmd);
1666 return -2;
1667 } else if (ret < 0) {
1668 printf("'%s' command failed.\n", cmd);
1669 return -1;
1670 }
1671
1672 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001673 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001674 return -1;
1675 printf("%s", buf);
1676
1677 pos = buf;
1678 while (*pos != '\0' && *pos != '\n')
1679 pos++;
1680 *pos = '\0';
1681 os_strlcpy(addr, buf, addr_len);
1682 return 0;
1683}
1684
1685
1686static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1687{
1688 char addr[32], cmd[64];
1689
1690 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1691 return 0;
1692 do {
1693 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1694 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1695
1696 return -1;
1697}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001698
1699
1700static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1701 char *argv[])
1702{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001703 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001704}
1705
1706
1707static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1708 char *argv[])
1709{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001710 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001711}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001712#endif /* CONFIG_AP */
1713
1714
1715static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1716{
1717 return wpa_ctrl_command(ctrl, "SUSPEND");
1718}
1719
1720
1721static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1722{
1723 return wpa_ctrl_command(ctrl, "RESUME");
1724}
1725
1726
1727static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1728{
1729 return wpa_ctrl_command(ctrl, "DROP_SA");
1730}
1731
1732
1733static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1734{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001735 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001736}
1737
1738
1739#ifdef CONFIG_P2P
1740
1741static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1742{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001743 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1744}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001745
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001746
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001747static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1748{
1749 char **res = NULL;
1750 int arg = get_cmd_arg_num(str, pos);
1751
1752 res = os_calloc(6, sizeof(char *));
1753 if (res == NULL)
1754 return NULL;
1755 res[0] = os_strdup("type=social");
1756 if (res[0] == NULL) {
1757 os_free(res);
1758 return NULL;
1759 }
1760 res[1] = os_strdup("type=progressive");
1761 if (res[1] == NULL)
1762 return res;
1763 res[2] = os_strdup("delay=");
1764 if (res[2] == NULL)
1765 return res;
1766 res[3] = os_strdup("dev_id=");
1767 if (res[3] == NULL)
1768 return res;
1769 if (arg == 1)
1770 res[4] = os_strdup("[timeout]");
1771
1772 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001773}
1774
1775
1776static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1777 char *argv[])
1778{
1779 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1780}
1781
1782
1783static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1784 char *argv[])
1785{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001786 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001787}
1788
1789
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001790static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1791{
1792 int arg = get_cmd_arg_num(str, pos);
1793 char **res = NULL;
1794
1795 switch (arg) {
1796 case 1:
1797 res = cli_txt_list_array(&p2p_peers);
1798 break;
1799 }
1800
1801 return res;
1802}
1803
1804
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001805static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1806 char *argv[])
1807{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001808 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001809}
1810
1811
1812static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1813 char *argv[])
1814{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001815 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001816}
1817
1818
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001819static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1820{
1821 int arg = get_cmd_arg_num(str, pos);
1822 char **res = NULL;
1823
1824 switch (arg) {
1825 case 1:
1826 res = cli_txt_list_array(&p2p_groups);
1827 break;
1828 }
1829
1830 return res;
1831}
1832
1833
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001834static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1835 char *argv[])
1836{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001837 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001838}
1839
1840
1841static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1842 char *argv[])
1843{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001844 if (argc != 2 && argc != 3) {
1845 printf("Invalid P2P_PROV_DISC command: needs at least "
1846 "two arguments, address and config method\n"
1847 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001848 return -1;
1849 }
1850
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001851 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001852}
1853
1854
1855static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1856 char *argv[])
1857{
1858 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1859}
1860
1861
1862static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1863 char *argv[])
1864{
1865 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001866
1867 if (argc != 2 && argc != 4) {
1868 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1869 "arguments (address and TLVs) or four arguments "
1870 "(address, \"upnp\", version, search target "
1871 "(SSDP ST:)\n");
1872 return -1;
1873 }
1874
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001875 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001876 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001877 return wpa_ctrl_command(ctrl, cmd);
1878}
1879
1880
1881static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1882 int argc, char *argv[])
1883{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001884 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001885}
1886
1887
1888static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1889 char *argv[])
1890{
1891 char cmd[4096];
1892 int res;
1893
1894 if (argc != 4) {
1895 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1896 "arguments (freq, address, dialog token, and TLVs)\n");
1897 return -1;
1898 }
1899
1900 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1901 argv[0], argv[1], argv[2], argv[3]);
1902 if (res < 0 || (size_t) res >= sizeof(cmd))
1903 return -1;
1904 cmd[sizeof(cmd) - 1] = '\0';
1905 return wpa_ctrl_command(ctrl, cmd);
1906}
1907
1908
1909static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1910 char *argv[])
1911{
1912 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1913}
1914
1915
1916static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1917 int argc, char *argv[])
1918{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001919 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001920}
1921
1922
1923static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1924 char *argv[])
1925{
1926 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1927}
1928
1929
1930static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1931 char *argv[])
1932{
1933 char cmd[4096];
1934 int res;
1935
1936 if (argc != 3 && argc != 4) {
1937 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1938 "arguments\n");
1939 return -1;
1940 }
1941
1942 if (argc == 4)
1943 res = os_snprintf(cmd, sizeof(cmd),
1944 "P2P_SERVICE_ADD %s %s %s %s",
1945 argv[0], argv[1], argv[2], argv[3]);
1946 else
1947 res = os_snprintf(cmd, sizeof(cmd),
1948 "P2P_SERVICE_ADD %s %s %s",
1949 argv[0], argv[1], argv[2]);
1950 if (res < 0 || (size_t) res >= sizeof(cmd))
1951 return -1;
1952 cmd[sizeof(cmd) - 1] = '\0';
1953 return wpa_ctrl_command(ctrl, cmd);
1954}
1955
1956
1957static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1958 char *argv[])
1959{
1960 char cmd[4096];
1961 int res;
1962
1963 if (argc != 2 && argc != 3) {
1964 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1965 "arguments\n");
1966 return -1;
1967 }
1968
1969 if (argc == 3)
1970 res = os_snprintf(cmd, sizeof(cmd),
1971 "P2P_SERVICE_DEL %s %s %s",
1972 argv[0], argv[1], argv[2]);
1973 else
1974 res = os_snprintf(cmd, sizeof(cmd),
1975 "P2P_SERVICE_DEL %s %s",
1976 argv[0], argv[1]);
1977 if (res < 0 || (size_t) res >= sizeof(cmd))
1978 return -1;
1979 cmd[sizeof(cmd) - 1] = '\0';
1980 return wpa_ctrl_command(ctrl, cmd);
1981}
1982
1983
1984static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1985 int argc, char *argv[])
1986{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001987 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001988}
1989
1990
1991static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1992 int argc, char *argv[])
1993{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001994 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001995}
1996
1997
1998static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1999{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002000 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002001}
2002
2003
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002004static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
2005{
2006 int arg = get_cmd_arg_num(str, pos);
2007 char **res = NULL;
2008
2009 switch (arg) {
2010 case 1:
2011 res = cli_txt_list_array(&p2p_peers);
2012 break;
2013 }
2014
2015 return res;
2016}
2017
2018
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002019static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2020 char *addr, size_t addr_len,
2021 int discovered)
2022{
2023 char buf[4096], *pos;
2024 size_t len;
2025 int ret;
2026
2027 if (ctrl_conn == NULL)
2028 return -1;
2029 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002030 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002031 wpa_cli_msg_cb);
2032 if (ret == -2) {
2033 printf("'%s' command timed out.\n", cmd);
2034 return -2;
2035 } else if (ret < 0) {
2036 printf("'%s' command failed.\n", cmd);
2037 return -1;
2038 }
2039
2040 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002041 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002042 return -1;
2043
2044 pos = buf;
2045 while (*pos != '\0' && *pos != '\n')
2046 pos++;
2047 *pos++ = '\0';
2048 os_strlcpy(addr, buf, addr_len);
2049 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2050 printf("%s\n", addr);
2051 return 0;
2052}
2053
2054
2055static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2056{
2057 char addr[32], cmd[64];
2058 int discovered;
2059
2060 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2061
2062 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2063 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002064 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002065 do {
2066 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2067 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2068 discovered) == 0);
2069
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002070 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002071}
2072
2073
2074static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2075{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002076 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002077}
2078
2079
2080static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2081{
2082 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2083}
2084
2085
2086static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2087 char *argv[])
2088{
2089 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2090}
2091
2092
2093static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2094 char *argv[])
2095{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002096 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002097}
2098
2099
2100static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2101 char *argv[])
2102{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002103 if (argc != 0 && argc != 2 && argc != 4) {
2104 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2105 "(preferred duration, interval; in microsecods).\n"
2106 "Optional second pair can be used to provide "
2107 "acceptable values.\n");
2108 return -1;
2109 }
2110
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002111 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002112}
2113
2114
2115static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2116 char *argv[])
2117{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002118 if (argc != 0 && argc != 2) {
2119 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2120 "(availability period, availability interval; in "
2121 "millisecods).\n"
2122 "Extended Listen Timing can be cancelled with this "
2123 "command when used without parameters.\n");
2124 return -1;
2125 }
2126
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002127 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2128}
2129
2130#endif /* CONFIG_P2P */
2131
2132#ifdef CONFIG_WIFI_DISPLAY
2133
2134static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2135 char *argv[])
2136{
2137 char cmd[100];
2138 int res;
2139
2140 if (argc != 1 && argc != 2) {
2141 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2142 "arguments (subelem, hexdump)\n");
2143 return -1;
2144 }
2145
2146 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2147 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002148 if (res < 0 || (size_t) res >= sizeof(cmd))
2149 return -1;
2150 cmd[sizeof(cmd) - 1] = '\0';
2151 return wpa_ctrl_command(ctrl, cmd);
2152}
2153
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002154
2155static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2156 char *argv[])
2157{
2158 char cmd[100];
2159 int res;
2160
2161 if (argc != 1) {
2162 printf("Invalid WFD_SUBELEM_GET command: needs one "
2163 "argument (subelem)\n");
2164 return -1;
2165 }
2166
2167 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2168 argv[0]);
2169 if (res < 0 || (size_t) res >= sizeof(cmd))
2170 return -1;
2171 cmd[sizeof(cmd) - 1] = '\0';
2172 return wpa_ctrl_command(ctrl, cmd);
2173}
2174#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002175
2176
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002177#ifdef CONFIG_INTERWORKING
2178static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2179 char *argv[])
2180{
2181 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2182}
2183
2184
2185static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2186 char *argv[])
2187{
2188 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2189}
2190
2191
2192static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2193 char *argv[])
2194{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002195 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002196}
2197
2198
2199static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2200 char *argv[])
2201{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002202 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002203}
2204
2205
2206static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2207{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002208 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2209}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002210
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002211
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002212static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2213 char *argv[])
2214{
2215 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2216}
2217
2218
2219static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2220 char *argv[])
2221{
2222 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002223}
2224#endif /* CONFIG_INTERWORKING */
2225
2226
Dmitry Shmidt04949592012-07-19 12:16:46 -07002227#ifdef CONFIG_HS20
2228
2229static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2230 char *argv[])
2231{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002232 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002233}
2234
2235
2236static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2237 char *argv[])
2238{
2239 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002240
2241 if (argc == 0) {
2242 printf("Command needs one or two arguments (dst mac addr and "
2243 "optional home realm)\n");
2244 return -1;
2245 }
2246
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002247 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2248 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002249 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002250
2251 return wpa_ctrl_command(ctrl, cmd);
2252}
2253
2254#endif /* CONFIG_HS20 */
2255
2256
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002257static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2258 char *argv[])
2259{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002260 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002261}
2262
2263
2264static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2265 char *argv[])
2266{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002267 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002268}
2269
2270
2271static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2272 char *argv[])
2273{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002274 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002275}
2276
2277
2278static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2279 char *argv[])
2280{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002281 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002282}
2283
2284
2285static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2286 char *argv[])
2287{
2288 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2289}
2290
2291
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002292static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2293 char *argv[])
2294{
2295 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2296}
2297
2298
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002299static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2300 char *argv[])
2301{
2302 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2303}
2304
Dmitry Shmidt04949592012-07-19 12:16:46 -07002305
2306#ifdef CONFIG_AUTOSCAN
2307
2308static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2309{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002310 if (argc == 0)
2311 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2312
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002313 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002314}
2315
2316#endif /* CONFIG_AUTOSCAN */
2317
2318
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002319#ifdef CONFIG_WNM
2320
2321static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2322{
2323 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2324}
2325
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002326
2327static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2328{
2329 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2330}
2331
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002332#endif /* CONFIG_WNM */
2333
2334
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002335static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2336{
2337 if (argc == 0)
2338 return -1;
2339 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2340}
2341
2342
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002343#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002344static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2345{
2346 char cmd[256];
2347 int i;
2348 int len;
2349
2350 if (argc < 1) {
2351 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2352 return -1;
2353 }
2354
2355 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2356 for (i=1; i < argc; i++)
2357 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2358 cmd[sizeof(cmd) - 1] = '\0';
2359 printf("%s: %s\n", __func__, cmd);
2360 return wpa_ctrl_command(ctrl, cmd);
2361}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002362#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002363
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002364
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002365static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2366{
2367 return wpa_ctrl_command(ctrl, "FLUSH");
2368}
2369
2370
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002371enum wpa_cli_cmd_flags {
2372 cli_cmd_flag_none = 0x00,
2373 cli_cmd_flag_sensitive = 0x01
2374};
2375
2376struct wpa_cli_cmd {
2377 const char *cmd;
2378 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002379 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002380 enum wpa_cli_cmd_flags flags;
2381 const char *usage;
2382};
2383
2384static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002385 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002386 cli_cmd_flag_none,
2387 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002388 { "ifname", wpa_cli_cmd_ifname, NULL,
2389 cli_cmd_flag_none,
2390 "= get current interface name" },
2391 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002392 cli_cmd_flag_none,
2393 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002394 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002395 cli_cmd_flag_none,
2396 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002397 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002398 cli_cmd_flag_none,
2399 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002400 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002401 cli_cmd_flag_none,
2402 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002403 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002404 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002405 "[command] = show usage help" },
2406 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002407 cli_cmd_flag_none,
2408 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002409 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002410 cli_cmd_flag_none,
2411 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002412 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002413 cli_cmd_flag_none,
2414 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002415 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002416 cli_cmd_flag_none,
2417 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002418 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002419 cli_cmd_flag_none,
2420 "= set variables (shows list of variables when run without "
2421 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002422 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002423 cli_cmd_flag_none,
2424 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002425 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002426 cli_cmd_flag_none,
2427 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002428 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002429 cli_cmd_flag_none,
2430 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002431 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002432 cli_cmd_flag_none,
2433 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002434 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002435 cli_cmd_flag_none,
2436 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002437 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002438 cli_cmd_flag_none,
2439 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002440 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002441 cli_cmd_flag_none,
2442 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002443 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002444 cli_cmd_flag_sensitive,
2445 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002446 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002447 cli_cmd_flag_sensitive,
2448 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002449 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002450 cli_cmd_flag_sensitive,
2451 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002452 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002453 cli_cmd_flag_sensitive,
2454 "<network id> <password> = configure one-time-password for an SSID"
2455 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002456 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002457 cli_cmd_flag_sensitive,
2458 "<network id> <passphrase> = configure private key passphrase\n"
2459 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002460 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002461 cli_cmd_flag_none,
2462 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002463 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002464 cli_cmd_flag_none,
2465 "<BSSID> = add a BSSID to the blacklist\n"
2466 "blacklist clear = clear the blacklist\n"
2467 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002468 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002469 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002470 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002471 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002472 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002473 cli_cmd_flag_none,
2474 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002475 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002476 cli_cmd_flag_none,
2477 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002478 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002479 cli_cmd_flag_none,
2480 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002481 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002482 cli_cmd_flag_none,
2483 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002484 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002485 cli_cmd_flag_none,
2486 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002487 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002488 cli_cmd_flag_none,
2489 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002490 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002491 cli_cmd_flag_sensitive,
2492 "<network id> <variable> <value> = set network variables (shows\n"
2493 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002494 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002495 cli_cmd_flag_none,
2496 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002497 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002498 cli_cmd_flag_none,
2499 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002500 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002501 cli_cmd_flag_none,
2502 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002503 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002504 cli_cmd_flag_none,
2505 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002506 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002507 cli_cmd_flag_sensitive,
2508 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002509 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002510 cli_cmd_flag_none,
2511 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002512 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 cli_cmd_flag_none,
2514 "= disconnect and wait for reassociate/reconnect command before\n"
2515 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002516 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 cli_cmd_flag_none,
2518 "= like reassociate, but only takes effect if already disconnected"
2519 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002520 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002521 cli_cmd_flag_none,
2522 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002523 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002524 cli_cmd_flag_none,
2525 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002526 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002527 cli_cmd_flag_none,
2528 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002529 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002530 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002531 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002532 "= get capabilies" },
2533 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002534 cli_cmd_flag_none,
2535 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002536 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002537 cli_cmd_flag_none,
2538 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002539 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002540 cli_cmd_flag_none,
2541 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2542 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2543 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002544 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002545 cli_cmd_flag_none,
2546 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002547 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002548 cli_cmd_flag_none,
2549 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002550 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002551 cli_cmd_flag_none,
2552 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002553 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002554 cli_cmd_flag_none,
2555 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002556 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002557 cli_cmd_flag_none,
2558 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002559 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002560 cli_cmd_flag_none,
2561 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002562 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002563 cli_cmd_flag_none,
2564 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002565 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002566 cli_cmd_flag_none,
2567 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002568 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002569 cli_cmd_flag_none,
2570 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002571 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002572 cli_cmd_flag_none,
2573 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002574 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002575 cli_cmd_flag_sensitive,
2576 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2577 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002578 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002579 cli_cmd_flag_sensitive,
2580 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002581 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002582 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002583#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002584 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002585 cli_cmd_flag_none,
2586 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002587 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2588 cli_cmd_flag_none,
2589 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002590 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002591 cli_cmd_flag_none,
2592 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002593 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002594 cli_cmd_flag_sensitive,
2595 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002596 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2597 cli_cmd_flag_none,
2598 "<NDEF> <WPS> = create NFC handover request" },
2599 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2600 cli_cmd_flag_none,
2601 "<NDEF> <WPS> = create NFC handover select" },
2602 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2603 cli_cmd_flag_none,
2604 "<hexdump of payload> = report received NFC handover request" },
2605 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2606 cli_cmd_flag_none,
2607 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002608 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2609 cli_cmd_flag_none,
2610 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2611 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002612#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002613 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002614 cli_cmd_flag_sensitive,
2615 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002616 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002617 cli_cmd_flag_sensitive,
2618 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002619 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620 cli_cmd_flag_none,
2621 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002622 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002623 cli_cmd_flag_none,
2624 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002625 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002626 cli_cmd_flag_sensitive,
2627 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002628 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002629 cli_cmd_flag_none,
2630 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002631 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002632 cli_cmd_flag_sensitive,
2633 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002634 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002635 cli_cmd_flag_none,
2636 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002637 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638 cli_cmd_flag_sensitive,
2639 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002640#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002641 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002642 cli_cmd_flag_none,
2643 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2644#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002645 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646 cli_cmd_flag_none,
2647 "<addr> = request RSN authentication with <addr> in IBSS" },
2648#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002649 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002650 cli_cmd_flag_none,
2651 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002652 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002653 cli_cmd_flag_none,
2654 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002655 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002656 cli_cmd_flag_none,
2657 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002658 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002659 cli_cmd_flag_none,
2660 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002661#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002662 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002663 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002664 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002665 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002666 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002667 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002668 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002669 cli_cmd_flag_none,
2670 "<addr> = roam to the specified BSS" },
2671#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002672 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2673 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002674 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002675 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002676 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002677 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2678 cli_cmd_flag_none,
2679 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2680 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002681 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002682 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2683 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002684 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002685 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2686 "[ht40] = add a new P2P group (local end as GO)" },
2687 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2688 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002689 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002690 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002691 cli_cmd_flag_none,
2692 "= get the passphrase for a group (GO only)" },
2693 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002694 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002695 "<addr> <TLVs> = schedule service discovery request" },
2696 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002697 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002699 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002700 cli_cmd_flag_none,
2701 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002702 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002703 cli_cmd_flag_none,
2704 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002705 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002706 cli_cmd_flag_none,
2707 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002708 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002709 cli_cmd_flag_none,
2710 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002711 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002712 cli_cmd_flag_none,
2713 "<bonjour|upnp> <query|version> <response|service> = add a local "
2714 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002715 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002716 cli_cmd_flag_none,
2717 "<bonjour|upnp> <query|version> [|service] = remove a local "
2718 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002719 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002720 cli_cmd_flag_none,
2721 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002722 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002723 cli_cmd_flag_none,
2724 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002725 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002726 "[discovered] = list known (optionally, only fully discovered) P2P "
2727 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002728 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2729 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002730 "<address> = show information about known P2P peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002731 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002732 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002733 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002734 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002735 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002736 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002737 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2738 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002739 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002740 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2741 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002742 "[<duration> <interval>] [<duration> <interval>] = request GO "
2743 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002744 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2745 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002746 "[<period> <interval>] = set extended listen timing" },
2747#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002748#ifdef CONFIG_WIFI_DISPLAY
2749 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2750 cli_cmd_flag_none,
2751 "<subelem> [contents] = set Wi-Fi Display subelement" },
2752 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2753 cli_cmd_flag_none,
2754 "<subelem> = get Wi-Fi Display subelement" },
2755#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002756#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002757 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002758 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002759 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2760 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002761 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002762 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002763 cli_cmd_flag_none,
2764 "[auto] = perform Interworking network selection" },
2765 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002766 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002767 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002768 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2769 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002770 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002771 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2772 cli_cmd_flag_none,
2773 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2774 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2775 wpa_cli_complete_bss, cli_cmd_flag_none,
2776 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002777#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002778#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002779 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2780 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002781 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2782 },
2783 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002784 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002785 "<addr> <home realm> = get HS20 nai home realm list" },
2786#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002787 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2788 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002789 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002790 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002791 cli_cmd_flag_none,
2792 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002793 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002794 cli_cmd_flag_none,
2795 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002796 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002797 cli_cmd_flag_none,
2798 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002799 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002800 cli_cmd_flag_none,
2801 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002802 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002803 cli_cmd_flag_none,
2804 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002805 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2806 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002807 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002808#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002809 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002810 "[params] = Set or unset (if none) autoscan parameters" },
2811#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002812#ifdef CONFIG_WNM
2813 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2814 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002815 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2816 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002817#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002818 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2819 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002820 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2821 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002822#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002823 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002824 cli_cmd_flag_none,
2825 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002826#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002827 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002828};
2829
2830
2831/*
2832 * Prints command usage, lines are padded with the specified string.
2833 */
2834static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2835{
2836 char c;
2837 size_t n;
2838
2839 printf("%s%s ", pad, cmd->cmd);
2840 for (n = 0; (c = cmd->usage[n]); n++) {
2841 printf("%c", c);
2842 if (c == '\n')
2843 printf("%s", pad);
2844 }
2845 printf("\n");
2846}
2847
2848
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002849static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002850{
2851 int n;
2852 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002853 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2854 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2855 print_cmd_help(&wpa_cli_commands[n], " ");
2856 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002857}
2858
2859
2860static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2861{
2862 const char *c, *delim;
2863 int n;
2864 size_t len;
2865
2866 delim = os_strchr(cmd, ' ');
2867 if (delim)
2868 len = delim - cmd;
2869 else
2870 len = os_strlen(cmd);
2871
2872 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2873 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2874 return (wpa_cli_commands[n].flags &
2875 cli_cmd_flag_sensitive);
2876 }
2877 return 0;
2878}
2879
2880
2881static char ** wpa_list_cmd_list(void)
2882{
2883 char **res;
2884 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002885 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002886
2887 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002888 count += dl_list_len(&p2p_groups);
2889 count += dl_list_len(&ifnames);
2890 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002891 if (res == NULL)
2892 return NULL;
2893
2894 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2895 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2896 if (res[i] == NULL)
2897 break;
2898 }
2899
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002900 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
2901 size_t len = 8 + os_strlen(e->txt);
2902 res[i] = os_malloc(len);
2903 if (res[i] == NULL)
2904 break;
2905 os_snprintf(res[i], len, "ifname=%s", e->txt);
2906 i++;
2907 }
2908
2909 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
2910 res[i] = os_strdup(e->txt);
2911 if (res[i] == NULL)
2912 break;
2913 i++;
2914 }
2915
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002916 return res;
2917}
2918
2919
2920static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2921 int pos)
2922{
2923 int i;
2924
2925 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2926 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002927 if (wpa_cli_commands[i].completion)
2928 return wpa_cli_commands[i].completion(str,
2929 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002930 edit_clear_line();
2931 printf("\r%s\n", wpa_cli_commands[i].usage);
2932 edit_redraw();
2933 break;
2934 }
2935 }
2936
2937 return NULL;
2938}
2939
2940
2941static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2942{
2943 char **res;
2944 const char *end;
2945 char *cmd;
2946
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002947 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
2948 end = os_strchr(str, ' ');
2949 if (end && pos > end - str) {
2950 pos -= end - str + 1;
2951 str = end + 1;
2952 }
2953 }
2954
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002955 end = os_strchr(str, ' ');
2956 if (end == NULL || str + pos < end)
2957 return wpa_list_cmd_list();
2958
2959 cmd = os_malloc(pos + 1);
2960 if (cmd == NULL)
2961 return NULL;
2962 os_memcpy(cmd, str, pos);
2963 cmd[end - str] = '\0';
2964 res = wpa_cli_cmd_completion(cmd, str, pos);
2965 os_free(cmd);
2966 return res;
2967}
2968
2969
2970static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2971{
2972 struct wpa_cli_cmd *cmd, *match = NULL;
2973 int count;
2974 int ret = 0;
2975
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002976 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
2977 ifname_prefix = argv[0] + 7;
2978 argv = &argv[1];
2979 argc--;
2980 } else
2981 ifname_prefix = NULL;
2982
2983 if (argc == 0)
2984 return -1;
2985
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002986 count = 0;
2987 cmd = wpa_cli_commands;
2988 while (cmd->cmd) {
2989 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2990 {
2991 match = cmd;
2992 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2993 /* we have an exact match */
2994 count = 1;
2995 break;
2996 }
2997 count++;
2998 }
2999 cmd++;
3000 }
3001
3002 if (count > 1) {
3003 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3004 cmd = wpa_cli_commands;
3005 while (cmd->cmd) {
3006 if (os_strncasecmp(cmd->cmd, argv[0],
3007 os_strlen(argv[0])) == 0) {
3008 printf(" %s", cmd->cmd);
3009 }
3010 cmd++;
3011 }
3012 printf("\n");
3013 ret = 1;
3014 } else if (count == 0) {
3015 printf("Unknown command '%s'\n", argv[0]);
3016 ret = 1;
3017 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07003018#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
3019 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
3020 redirect_interface = os_strdup(argv[1]);
3021 ret = match->handler(ctrl, argc - 2, &argv[2]);
3022 }
3023 else
3024#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003025 ret = match->handler(ctrl, argc - 1, &argv[1]);
3026 }
3027
3028 return ret;
3029}
3030
3031
3032static int str_match(const char *a, const char *b)
3033{
3034 return os_strncmp(a, b, os_strlen(b)) == 0;
3035}
3036
3037
3038static int wpa_cli_exec(const char *program, const char *arg1,
3039 const char *arg2)
3040{
3041 char *cmd;
3042 size_t len;
3043 int res;
3044 int ret = 0;
3045
3046 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3047 cmd = os_malloc(len);
3048 if (cmd == NULL)
3049 return -1;
3050 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3051 if (res < 0 || (size_t) res >= len) {
3052 os_free(cmd);
3053 return -1;
3054 }
3055 cmd[len - 1] = '\0';
3056#ifndef _WIN32_WCE
3057 if (system(cmd) < 0)
3058 ret = -1;
3059#endif /* _WIN32_WCE */
3060 os_free(cmd);
3061
3062 return ret;
3063}
3064
3065
3066static void wpa_cli_action_process(const char *msg)
3067{
3068 const char *pos;
3069 char *copy = NULL, *id, *pos2;
3070
3071 pos = msg;
3072 if (*pos == '<') {
3073 /* skip priority */
3074 pos = os_strchr(pos, '>');
3075 if (pos)
3076 pos++;
3077 else
3078 pos = msg;
3079 }
3080
3081 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3082 int new_id = -1;
3083 os_unsetenv("WPA_ID");
3084 os_unsetenv("WPA_ID_STR");
3085 os_unsetenv("WPA_CTRL_DIR");
3086
3087 pos = os_strstr(pos, "[id=");
3088 if (pos)
3089 copy = os_strdup(pos + 4);
3090
3091 if (copy) {
3092 pos2 = id = copy;
3093 while (*pos2 && *pos2 != ' ')
3094 pos2++;
3095 *pos2++ = '\0';
3096 new_id = atoi(id);
3097 os_setenv("WPA_ID", id, 1);
3098 while (*pos2 && *pos2 != '=')
3099 pos2++;
3100 if (*pos2 == '=')
3101 pos2++;
3102 id = pos2;
3103 while (*pos2 && *pos2 != ']')
3104 pos2++;
3105 *pos2 = '\0';
3106 os_setenv("WPA_ID_STR", id, 1);
3107 os_free(copy);
3108 }
3109
3110 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3111
3112 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3113 wpa_cli_connected = 1;
3114 wpa_cli_last_id = new_id;
3115 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3116 }
3117 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3118 if (wpa_cli_connected) {
3119 wpa_cli_connected = 0;
3120 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3121 }
3122 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3123 wpa_cli_exec(action_file, ctrl_ifname, pos);
3124 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3125 wpa_cli_exec(action_file, ctrl_ifname, pos);
3126 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3127 wpa_cli_exec(action_file, ctrl_ifname, pos);
3128 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3129 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003130 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3131 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003132 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3133 wpa_cli_exec(action_file, ctrl_ifname, pos);
3134 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3135 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003136 } else if (str_match(pos, AP_STA_CONNECTED)) {
3137 wpa_cli_exec(action_file, ctrl_ifname, pos);
3138 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3139 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003140 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3141 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003142 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3143 printf("wpa_supplicant is terminating - stop monitoring\n");
3144 wpa_cli_quit = 1;
3145 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003146}
3147
3148
3149#ifndef CONFIG_ANSI_C_EXTRA
3150static void wpa_cli_action_cb(char *msg, size_t len)
3151{
3152 wpa_cli_action_process(msg);
3153}
3154#endif /* CONFIG_ANSI_C_EXTRA */
3155
3156
3157static void wpa_cli_reconnect(void)
3158{
3159 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003160 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3161 return;
3162
3163 if (interactive) {
3164 edit_clear_line();
3165 printf("\rConnection to wpa_supplicant re-established\n");
3166 edit_redraw();
3167 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003168}
3169
3170
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003171static void cli_event(const char *str)
3172{
3173 const char *start, *s;
3174
3175 start = os_strchr(str, '>');
3176 if (start == NULL)
3177 return;
3178
3179 start++;
3180
3181 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3182 s = os_strchr(start, ' ');
3183 if (s == NULL)
3184 return;
3185 s = os_strchr(s + 1, ' ');
3186 if (s == NULL)
3187 return;
3188 cli_txt_list_add(&bsses, s + 1);
3189 return;
3190 }
3191
3192 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3193 s = os_strchr(start, ' ');
3194 if (s == NULL)
3195 return;
3196 s = os_strchr(s + 1, ' ');
3197 if (s == NULL)
3198 return;
3199 cli_txt_list_del_addr(&bsses, s + 1);
3200 return;
3201 }
3202
3203#ifdef CONFIG_P2P
3204 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3205 s = os_strstr(start, " p2p_dev_addr=");
3206 if (s == NULL)
3207 return;
3208 cli_txt_list_add_addr(&p2p_peers, s + 14);
3209 return;
3210 }
3211
3212 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3213 s = os_strstr(start, " p2p_dev_addr=");
3214 if (s == NULL)
3215 return;
3216 cli_txt_list_del_addr(&p2p_peers, s + 14);
3217 return;
3218 }
3219
3220 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3221 s = os_strchr(start, ' ');
3222 if (s == NULL)
3223 return;
3224 cli_txt_list_add_word(&p2p_groups, s + 1);
3225 return;
3226 }
3227
3228 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3229 s = os_strchr(start, ' ');
3230 if (s == NULL)
3231 return;
3232 cli_txt_list_del_word(&p2p_groups, s + 1);
3233 return;
3234 }
3235#endif /* CONFIG_P2P */
3236}
3237
3238
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003239static int check_terminating(const char *msg)
3240{
3241 const char *pos = msg;
3242
3243 if (*pos == '<') {
3244 /* skip priority */
3245 pos = os_strchr(pos, '>');
3246 if (pos)
3247 pos++;
3248 else
3249 pos = msg;
3250 }
3251
3252 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3253 edit_clear_line();
3254 printf("\rConnection to wpa_supplicant lost - trying to "
3255 "reconnect\n");
3256 edit_redraw();
3257 wpa_cli_attached = 0;
3258 wpa_cli_close_connection();
3259 return 1;
3260 }
3261
3262 return 0;
3263}
3264
3265
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003266static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3267{
3268 if (ctrl_conn == NULL) {
3269 wpa_cli_reconnect();
3270 return;
3271 }
3272 while (wpa_ctrl_pending(ctrl) > 0) {
3273 char buf[256];
3274 size_t len = sizeof(buf) - 1;
3275 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3276 buf[len] = '\0';
3277 if (action_monitor)
3278 wpa_cli_action_process(buf);
3279 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003280 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003281 if (wpa_cli_show_event(buf)) {
3282 edit_clear_line();
3283 printf("\r%s\n", buf);
3284 edit_redraw();
3285 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003286
3287 if (interactive && check_terminating(buf) > 0)
3288 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003289 }
3290 } else {
3291 printf("Could not read pending message.\n");
3292 break;
3293 }
3294 }
3295
3296 if (wpa_ctrl_pending(ctrl) < 0) {
3297 printf("Connection to wpa_supplicant lost - trying to "
3298 "reconnect\n");
3299 wpa_cli_reconnect();
3300 }
3301}
3302
3303#define max_args 10
3304
3305static int tokenize_cmd(char *cmd, char *argv[])
3306{
3307 char *pos;
3308 int argc = 0;
3309
3310 pos = cmd;
3311 for (;;) {
3312 while (*pos == ' ')
3313 pos++;
3314 if (*pos == '\0')
3315 break;
3316 argv[argc] = pos;
3317 argc++;
3318 if (argc == max_args)
3319 break;
3320 if (*pos == '"') {
3321 char *pos2 = os_strrchr(pos, '"');
3322 if (pos2)
3323 pos = pos2 + 1;
3324 }
3325 while (*pos != '\0' && *pos != ' ')
3326 pos++;
3327 if (*pos == ' ')
3328 *pos++ = '\0';
3329 }
3330
3331 return argc;
3332}
3333
3334
3335static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3336{
3337 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3338 printf("Connection to wpa_supplicant lost - trying to "
3339 "reconnect\n");
3340 wpa_cli_close_connection();
3341 }
3342 if (!ctrl_conn)
3343 wpa_cli_reconnect();
3344 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3345}
3346
3347
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003348static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3349{
3350 wpa_cli_recv_pending(mon_conn, 0);
3351}
3352
3353
3354static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3355{
3356 char *argv[max_args];
3357 int argc;
3358 argc = tokenize_cmd(cmd, argv);
3359 if (argc)
3360 wpa_request(ctrl_conn, argc, argv);
3361}
3362
3363
3364static void wpa_cli_edit_eof_cb(void *ctx)
3365{
3366 eloop_terminate();
3367}
3368
3369
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003370static int warning_displayed = 0;
3371static char *hfile = NULL;
3372static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003373
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003374static void start_edit(void)
3375{
3376 char *home;
3377 char *ps = NULL;
3378
3379#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3380 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3381#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003382
3383 home = getenv("HOME");
3384 if (home) {
3385 const char *fname = ".wpa_cli_history";
3386 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3387 hfile = os_malloc(hfile_len);
3388 if (hfile)
3389 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3390 }
3391
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003392 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3393 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3394 eloop_terminate();
3395 return;
3396 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003397
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003398 edit_started = 1;
3399 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3400}
3401
3402
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003403static void update_bssid_list(struct wpa_ctrl *ctrl)
3404{
3405 char buf[4096];
3406 size_t len = sizeof(buf);
3407 int ret;
3408 char *cmd = "BSS RANGE=ALL MASK=0x2";
3409 char *pos, *end;
3410
3411 if (ctrl == NULL)
3412 return;
3413 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3414 if (ret < 0)
3415 return;
3416 buf[len] = '\0';
3417
3418 pos = buf;
3419 while (pos) {
3420 pos = os_strstr(pos, "bssid=");
3421 if (pos == NULL)
3422 break;
3423 pos += 6;
3424 end = os_strchr(pos, '\n');
3425 if (end == NULL)
3426 break;
3427 *end = '\0';
3428 cli_txt_list_add(&bsses, pos);
3429 pos = end + 1;
3430 }
3431}
3432
3433
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003434static void update_ifnames(struct wpa_ctrl *ctrl)
3435{
3436 char buf[4096];
3437 size_t len = sizeof(buf);
3438 int ret;
3439 char *cmd = "INTERFACES";
3440 char *pos, *end;
3441 char txt[200];
3442
3443 cli_txt_list_flush(&ifnames);
3444
3445 if (ctrl == NULL)
3446 return;
3447 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3448 if (ret < 0)
3449 return;
3450 buf[len] = '\0';
3451
3452 pos = buf;
3453 while (pos) {
3454 end = os_strchr(pos, '\n');
3455 if (end == NULL)
3456 break;
3457 *end = '\0';
3458 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3459 if (ret > 0 && ret < (int) sizeof(txt))
3460 cli_txt_list_add(&ifnames, txt);
3461 pos = end + 1;
3462 }
3463}
3464
3465
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003466static void try_connection(void *eloop_ctx, void *timeout_ctx)
3467{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003468 if (ctrl_conn)
3469 goto done;
3470
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003471 if (ctrl_ifname == NULL)
3472 ctrl_ifname = wpa_cli_get_default_ifname();
3473
3474 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3475 if (!warning_displayed) {
3476 printf("Could not connect to wpa_supplicant: "
3477 "%s - re-trying\n", ctrl_ifname);
3478 warning_displayed = 1;
3479 }
3480 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3481 return;
3482 }
3483
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003484 update_bssid_list(ctrl_conn);
3485
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003486 if (warning_displayed)
3487 printf("Connection established.\n");
3488
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003489done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003490 start_edit();
3491}
3492
3493
3494static void wpa_cli_interactive(void)
3495{
3496 printf("\nInteractive mode\n\n");
3497
3498 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003499 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003500 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003501
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003502 cli_txt_list_flush(&p2p_peers);
3503 cli_txt_list_flush(&p2p_groups);
3504 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003505 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003506 if (edit_started)
3507 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003508 os_free(hfile);
3509 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3510 wpa_cli_close_connection();
3511}
3512
3513
3514static void wpa_cli_action(struct wpa_ctrl *ctrl)
3515{
3516#ifdef CONFIG_ANSI_C_EXTRA
3517 /* TODO: ANSI C version(?) */
3518 printf("Action processing not supported in ANSI C build.\n");
3519#else /* CONFIG_ANSI_C_EXTRA */
3520 fd_set rfds;
3521 int fd, res;
3522 struct timeval tv;
3523 char buf[256]; /* note: large enough to fit in unsolicited messages */
3524 size_t len;
3525
3526 fd = wpa_ctrl_get_fd(ctrl);
3527
3528 while (!wpa_cli_quit) {
3529 FD_ZERO(&rfds);
3530 FD_SET(fd, &rfds);
3531 tv.tv_sec = ping_interval;
3532 tv.tv_usec = 0;
3533 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3534 if (res < 0 && errno != EINTR) {
3535 perror("select");
3536 break;
3537 }
3538
3539 if (FD_ISSET(fd, &rfds))
3540 wpa_cli_recv_pending(ctrl, 1);
3541 else {
3542 /* verify that connection is still working */
3543 len = sizeof(buf) - 1;
3544 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3545 wpa_cli_action_cb) < 0 ||
3546 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3547 printf("wpa_supplicant did not reply to PING "
3548 "command - exiting\n");
3549 break;
3550 }
3551 }
3552 }
3553#endif /* CONFIG_ANSI_C_EXTRA */
3554}
3555
3556
3557static void wpa_cli_cleanup(void)
3558{
3559 wpa_cli_close_connection();
3560 if (pid_file)
3561 os_daemonize_terminate(pid_file);
3562
3563 os_program_deinit();
3564}
3565
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003566
3567static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003568{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003569 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003570}
3571
3572
3573static char * wpa_cli_get_default_ifname(void)
3574{
3575 char *ifname = NULL;
3576
3577#ifdef CONFIG_CTRL_IFACE_UNIX
3578 struct dirent *dent;
3579 DIR *dir = opendir(ctrl_iface_dir);
3580 if (!dir) {
3581#ifdef ANDROID
3582 char ifprop[PROPERTY_VALUE_MAX];
3583 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3584 ifname = os_strdup(ifprop);
3585 printf("Using interface '%s'\n", ifname);
3586 return ifname;
3587 }
3588#endif /* ANDROID */
3589 return NULL;
3590 }
3591 while ((dent = readdir(dir))) {
3592#ifdef _DIRENT_HAVE_D_TYPE
3593 /*
3594 * Skip the file if it is not a socket. Also accept
3595 * DT_UNKNOWN (0) in case the C library or underlying
3596 * file system does not support d_type.
3597 */
3598 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3599 continue;
3600#endif /* _DIRENT_HAVE_D_TYPE */
3601 if (os_strcmp(dent->d_name, ".") == 0 ||
3602 os_strcmp(dent->d_name, "..") == 0)
3603 continue;
3604 printf("Selected interface '%s'\n", dent->d_name);
3605 ifname = os_strdup(dent->d_name);
3606 break;
3607 }
3608 closedir(dir);
3609#endif /* CONFIG_CTRL_IFACE_UNIX */
3610
3611#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003612 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003613 size_t len;
3614 struct wpa_ctrl *ctrl;
3615 int ret;
3616
3617 ctrl = wpa_ctrl_open(NULL);
3618 if (ctrl == NULL)
3619 return NULL;
3620
3621 len = sizeof(buf) - 1;
3622 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3623 if (ret >= 0) {
3624 buf[len] = '\0';
3625 pos = os_strchr(buf, '\n');
3626 if (pos)
3627 *pos = '\0';
3628 ifname = os_strdup(buf);
3629 }
3630 wpa_ctrl_close(ctrl);
3631#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3632
3633 return ifname;
3634}
3635
3636
3637int main(int argc, char *argv[])
3638{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003639 int c;
3640 int daemonize = 0;
3641 int ret = 0;
3642 const char *global = NULL;
3643
3644 if (os_program_init())
3645 return -1;
3646
3647 for (;;) {
3648 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3649 if (c < 0)
3650 break;
3651 switch (c) {
3652 case 'a':
3653 action_file = optarg;
3654 break;
3655 case 'B':
3656 daemonize = 1;
3657 break;
3658 case 'g':
3659 global = optarg;
3660 break;
3661 case 'G':
3662 ping_interval = atoi(optarg);
3663 break;
3664 case 'h':
3665 usage();
3666 return 0;
3667 case 'v':
3668 printf("%s\n", wpa_cli_version);
3669 return 0;
3670 case 'i':
3671 os_free(ctrl_ifname);
3672 ctrl_ifname = os_strdup(optarg);
3673 break;
3674 case 'p':
3675 ctrl_iface_dir = optarg;
3676 break;
3677 case 'P':
3678 pid_file = optarg;
3679 break;
3680 default:
3681 usage();
3682 return -1;
3683 }
3684 }
3685
3686 interactive = (argc == optind) && (action_file == NULL);
3687
3688 if (interactive)
3689 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3690
3691 if (eloop_init())
3692 return -1;
3693
3694 if (global) {
3695#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3696 ctrl_conn = wpa_ctrl_open(NULL);
3697#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3698 ctrl_conn = wpa_ctrl_open(global);
3699#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3700 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003701 fprintf(stderr, "Failed to connect to wpa_supplicant "
3702 "global interface: %s error: %s\n",
3703 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003704 return -1;
3705 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003706
3707 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003708 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003709 mon_conn = wpa_ctrl_open(global);
3710 if (mon_conn) {
3711 if (wpa_ctrl_attach(mon_conn) == 0) {
3712 wpa_cli_attached = 1;
3713 eloop_register_read_sock(
3714 wpa_ctrl_get_fd(mon_conn),
3715 wpa_cli_mon_receive,
3716 NULL, NULL);
3717 } else {
3718 printf("Failed to open monitor "
3719 "connection through global "
3720 "control interface\n");
3721 }
3722 }
3723 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003724 }
3725
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003726 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003727
3728 if (ctrl_ifname == NULL)
3729 ctrl_ifname = wpa_cli_get_default_ifname();
3730
3731 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003732 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003733 } else {
3734 if (!global &&
3735 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003736 fprintf(stderr, "Failed to connect to non-global "
3737 "ctrl_ifname: %s error: %s\n",
3738 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003739 return -1;
3740 }
3741
3742 if (action_file) {
3743 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3744 wpa_cli_attached = 1;
3745 } else {
3746 printf("Warning: Failed to attach to "
3747 "wpa_supplicant.\n");
3748 return -1;
3749 }
3750 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003751
3752 if (daemonize && os_daemonize(pid_file))
3753 return -1;
3754
3755 if (action_file)
3756 wpa_cli_action(ctrl_conn);
3757 else
3758 ret = wpa_request(ctrl_conn, argc - optind,
3759 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003760 }
3761
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003762 os_free(ctrl_ifname);
3763 eloop_destroy();
3764 wpa_cli_cleanup();
3765
3766 return ret;
3767}
3768
3769#else /* CONFIG_CTRL_IFACE */
3770int main(int argc, char *argv[])
3771{
3772 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3773 return -1;
3774}
3775#endif /* CONFIG_CTRL_IFACE */