blob: 672752658ee0849e52babcf7feb6b0f9eb8c5d23 [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;
Dmitry Shmidt391c59f2013-09-03 12:16:28 -070073static int wpa_cli_connected = -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070074static int wpa_cli_last_id = 0;
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
82static int ping_interval = 5;
83static int interactive = 0;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070084static char *ifname_prefix = NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070085
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080086struct cli_txt_entry {
87 struct dl_list list;
88 char *txt;
89};
90
91static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
92static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
93static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -070094static DEFINE_DL_LIST(ifnames); /* struct cli_txt_entry */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070096
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070097static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070098static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070099static void wpa_cli_close_connection(void);
100static char * wpa_cli_get_default_ifname(void);
101static char ** wpa_list_cmd_list(void);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700102
103
104static void usage(void)
105{
106 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
107 "[-a<action file>] \\\n"
108 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
109 "[command..]\n"
110 " -h = help (show this usage text)\n"
111 " -v = shown version information\n"
112 " -a = run in daemon mode executing the action file based on "
113 "events from\n"
114 " wpa_supplicant\n"
115 " -B = run a daemon in the background\n"
116 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
117 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700118 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700119}
120
121
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800122static void cli_txt_list_free(struct cli_txt_entry *e)
123{
124 dl_list_del(&e->list);
125 os_free(e->txt);
126 os_free(e);
127}
128
129
130static void cli_txt_list_flush(struct dl_list *list)
131{
132 struct cli_txt_entry *e;
133 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
134 cli_txt_list_free(e);
135}
136
137
138static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
139 const char *txt)
140{
141 struct cli_txt_entry *e;
142 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
143 if (os_strcmp(e->txt, txt) == 0)
144 return e;
145 }
146 return NULL;
147}
148
149
150static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
151{
152 struct cli_txt_entry *e;
153 e = cli_txt_list_get(txt_list, txt);
154 if (e)
155 cli_txt_list_free(e);
156}
157
158
159static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
160{
161 u8 addr[ETH_ALEN];
162 char buf[18];
163 if (hwaddr_aton(txt, addr) < 0)
164 return;
165 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
166 cli_txt_list_del(txt_list, buf);
167}
168
169
170#ifdef CONFIG_P2P
171static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
172{
173 const char *end;
174 char *buf;
175 end = os_strchr(txt, ' ');
176 if (end == NULL)
177 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700178 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800179 if (buf == NULL)
180 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800181 cli_txt_list_del(txt_list, buf);
182 os_free(buf);
183}
184#endif /* CONFIG_P2P */
185
186
187static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
188{
189 struct cli_txt_entry *e;
190 e = cli_txt_list_get(txt_list, txt);
191 if (e)
192 return 0;
193 e = os_zalloc(sizeof(*e));
194 if (e == NULL)
195 return -1;
196 e->txt = os_strdup(txt);
197 if (e->txt == NULL) {
198 os_free(e);
199 return -1;
200 }
201 dl_list_add(txt_list, &e->list);
202 return 0;
203}
204
205
206#ifdef CONFIG_P2P
207static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
208{
209 u8 addr[ETH_ALEN];
210 char buf[18];
211 if (hwaddr_aton(txt, addr) < 0)
212 return -1;
213 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
214 return cli_txt_list_add(txt_list, buf);
215}
216
217
218static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
219{
220 const char *end;
221 char *buf;
222 int ret;
223 end = os_strchr(txt, ' ');
224 if (end == NULL)
225 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700226 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800227 if (buf == NULL)
228 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800229 ret = cli_txt_list_add(txt_list, buf);
230 os_free(buf);
231 return ret;
232}
233#endif /* CONFIG_P2P */
234
235
236static char ** cli_txt_list_array(struct dl_list *txt_list)
237{
238 unsigned int i, count = dl_list_len(txt_list);
239 char **res;
240 struct cli_txt_entry *e;
241
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700242 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800243 if (res == NULL)
244 return NULL;
245
246 i = 0;
247 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
248 res[i] = os_strdup(e->txt);
249 if (res[i] == NULL)
250 break;
251 i++;
252 }
253
254 return res;
255}
256
257
258static int get_cmd_arg_num(const char *str, int pos)
259{
260 int arg = 0, i;
261
262 for (i = 0; i <= pos; i++) {
263 if (str[i] != ' ') {
264 arg++;
265 while (i <= pos && str[i] != ' ')
266 i++;
267 }
268 }
269
270 if (arg > 0)
271 arg--;
272 return arg;
273}
274
275
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700276static int str_starts(const char *src, const char *match)
277{
278 return os_strncmp(src, match, os_strlen(match)) == 0;
279}
280
281
282static int wpa_cli_show_event(const char *event)
283{
284 const char *start;
285
286 start = os_strchr(event, '>');
287 if (start == NULL)
288 return 1;
289
290 start++;
291 /*
292 * Skip BSS added/removed events since they can be relatively frequent
293 * and are likely of not much use for an interactive user.
294 */
295 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
296 str_starts(start, WPA_EVENT_BSS_REMOVED))
297 return 0;
298
299 return 1;
300}
301
302
303static int wpa_cli_open_connection(const char *ifname, int attach)
304{
305#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
306 ctrl_conn = wpa_ctrl_open(ifname);
307 if (ctrl_conn == NULL)
308 return -1;
309
310 if (attach && interactive)
311 mon_conn = wpa_ctrl_open(ifname);
312 else
313 mon_conn = NULL;
314#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
315 char *cfile = NULL;
316 int flen, res;
317
318 if (ifname == NULL)
319 return -1;
320
321#ifdef ANDROID
322 if (access(ctrl_iface_dir, F_OK) < 0) {
323 cfile = os_strdup(ifname);
324 if (cfile == NULL)
325 return -1;
326 }
327#endif /* ANDROID */
328
329 if (cfile == NULL) {
330 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
331 cfile = os_malloc(flen);
332 if (cfile == NULL)
333 return -1;
334 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
335 ifname);
336 if (res < 0 || res >= flen) {
337 os_free(cfile);
338 return -1;
339 }
340 }
341
342 ctrl_conn = wpa_ctrl_open(cfile);
343 if (ctrl_conn == NULL) {
344 os_free(cfile);
345 return -1;
346 }
347
348 if (attach && interactive)
349 mon_conn = wpa_ctrl_open(cfile);
350 else
351 mon_conn = NULL;
352 os_free(cfile);
353#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
354
355 if (mon_conn) {
356 if (wpa_ctrl_attach(mon_conn) == 0) {
357 wpa_cli_attached = 1;
358 if (interactive)
359 eloop_register_read_sock(
360 wpa_ctrl_get_fd(mon_conn),
361 wpa_cli_mon_receive, NULL, NULL);
362 } else {
363 printf("Warning: Failed to attach to "
364 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700365 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700366 return -1;
367 }
368 }
369
370 return 0;
371}
372
373
374static void wpa_cli_close_connection(void)
375{
376 if (ctrl_conn == NULL)
377 return;
378
379 if (wpa_cli_attached) {
380 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
381 wpa_cli_attached = 0;
382 }
383 wpa_ctrl_close(ctrl_conn);
384 ctrl_conn = NULL;
385 if (mon_conn) {
386 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
387 wpa_ctrl_close(mon_conn);
388 mon_conn = NULL;
389 }
390}
391
392
393static void wpa_cli_msg_cb(char *msg, size_t len)
394{
395 printf("%s\n", msg);
396}
397
398
399static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
400{
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700401 char buf[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700402 size_t len;
403 int ret;
404
405 if (ctrl_conn == NULL) {
406 printf("Not connected to wpa_supplicant - command dropped.\n");
407 return -1;
408 }
Dmitry Shmidtd3e385e2013-06-05 11:06:13 -0700409 if (ifname_prefix) {
410 os_snprintf(buf, sizeof(buf), "IFNAME=%s %s",
411 ifname_prefix, cmd);
412 buf[sizeof(buf) - 1] = '\0';
413 cmd = buf;
414 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700415 len = sizeof(buf) - 1;
416 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
417 wpa_cli_msg_cb);
418 if (ret == -2) {
419 printf("'%s' command timed out.\n", cmd);
420 return -2;
421 } else if (ret < 0) {
422 printf("'%s' command failed.\n", cmd);
423 return -1;
424 }
425 if (print) {
426 buf[len] = '\0';
427 printf("%s", buf);
428 if (interactive && len > 0 && buf[len - 1] != '\n')
429 printf("\n");
430 }
431 return 0;
432}
433
434
435static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
436{
437 return _wpa_ctrl_command(ctrl, cmd, 1);
438}
439
440
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700441static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
442 char *argv[])
443{
444 int i, res;
445 char *pos, *end;
446
447 pos = buf;
448 end = buf + buflen;
449
450 res = os_snprintf(pos, end - pos, "%s", cmd);
451 if (res < 0 || res >= end - pos)
452 goto fail;
453 pos += res;
454
455 for (i = 0; i < argc; i++) {
456 res = os_snprintf(pos, end - pos, " %s", argv[i]);
457 if (res < 0 || res >= end - pos)
458 goto fail;
459 pos += res;
460 }
461
462 buf[buflen - 1] = '\0';
463 return 0;
464
465fail:
466 printf("Too long command\n");
467 return -1;
468}
469
470
471static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
472 int argc, char *argv[])
473{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700474 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700475 if (argc < min_args) {
476 printf("Invalid %s command - at least %d argument%s "
477 "required.\n", cmd, min_args,
478 min_args > 1 ? "s are" : " is");
479 return -1;
480 }
481 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
482 return -1;
483 return wpa_ctrl_command(ctrl, buf);
484}
485
486
487static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
488{
489 return wpa_ctrl_command(ctrl, "IFNAME");
490}
491
492
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700493static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
494{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800495 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
496 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
497 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
498 return wpa_ctrl_command(ctrl, "STATUS-WPS");
Dmitry Shmidt56052862013-10-04 10:23:25 -0700499 if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
500 return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800501 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700502}
503
504
505static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
506{
507 return wpa_ctrl_command(ctrl, "PING");
508}
509
510
511static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
512{
513 return wpa_ctrl_command(ctrl, "RELOG");
514}
515
516
517static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
518{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700519 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700520}
521
522
523static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
524{
525 return wpa_ctrl_command(ctrl, "MIB");
526}
527
528
529static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
530{
531 return wpa_ctrl_command(ctrl, "PMKSA");
532}
533
534
535static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
536{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700537 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700538 return 0;
539}
540
541
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700542static char ** wpa_cli_complete_help(const char *str, int pos)
543{
544 int arg = get_cmd_arg_num(str, pos);
545 char **res = NULL;
546
547 switch (arg) {
548 case 1:
549 res = wpa_list_cmd_list();
550 break;
551 }
552
553 return res;
554}
555
556
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700557static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
558{
559 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
560 return 0;
561}
562
563
564static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
565{
566 wpa_cli_quit = 1;
567 if (interactive)
568 eloop_terminate();
569 return 0;
570}
571
572
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700573static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
574{
575 char cmd[256];
576 int res;
577
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700578 if (argc == 1) {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800579 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700580 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
581 printf("Too long SET command.\n");
582 return -1;
583 }
584 return wpa_ctrl_command(ctrl, cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700585 }
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -0700586
587 return wpa_cli_cmd(ctrl, "SET", 2, argc, argv);
588}
589
590
591static char ** wpa_cli_complete_set(const char *str, int pos)
592{
593 int arg = get_cmd_arg_num(str, pos);
594 const char *fields[] = {
595 /* runtime values */
596 "EAPOL::heldPeriod", "EAPOL::authPeriod", "EAPOL::startPeriod",
597 "EAPOL::maxStart", "dot11RSNAConfigPMKLifetime",
598 "dot11RSNAConfigPMKReauthThreshold", "dot11RSNAConfigSATimeout",
599 "wps_fragment_size", "wps_version_number", "ampdu",
600 "tdls_testing", "tdls_disabled", "pno", "radio_disabled",
601 "uapsd", "ps", "wifi_display", "bssid_filter", "disallow_aps",
602 "no_keep_alive",
603 /* global configuration parameters */
604 "eapol_version", "ap_scan", "disable_scan_offload",
605 "fast_reauth", "opensc_engine_path", "pkcs11_engine_path",
606 "pkcs11_module_path", "pcsc_reader", "pcsc_pin",
607 "driver_param", "dot11RSNAConfigPMKLifetime",
608 "dot11RSNAConfigPMKReauthThreshold",
609 "dot11RSNAConfigSATimeout",
610 "update_config", "load_dynamic_eap", "uuid", "device_name",
611 "manufacturer", "model_name", "model_number", "serial_number",
612 "device_type", "os_version", "config_methods",
613 "wps_cred_processing", "wps_vendor_ext_m1", "sec_device_type",
614 "p2p_listen_reg_class", "p2p_listen_channel",
615 "p2p_oper_reg_class", "p2p_oper_channel",
616 "p2p_go_intent", "p2p_ssid_postfix", "persistent_reconnect",
617 "p2p_intra_bss", "p2p_group_idle", "p2p_pref_chan",
618 "p2p_go_ht40", "p2p_disabled", "p2p_no_group_iface",
619 "p2p_ignore_shared_freq", "country", "bss_max_count",
620 "bss_expiration_age", "bss_expiration_scan_count",
621 "filter_ssids", "filter_rssi", "max_num_sta",
622 "disassoc_low_ack", "hs20", "interworking", "hessid",
623 "access_network_type", "pbc_in_m1", "autoscan",
624 "wps_nfc_dev_pw_id", "wps_nfc_dh_pubkey", "wps_nfc_dh_privkey",
625 "wps_nfc_dev_pw", "ext_password_backend",
626 "p2p_go_max_inactivity", "auto_interworking", "okc", "pmf",
627 "sae_groups", "dtim_period", "beacon_int", "ap_vendor_elements",
628 "ignore_old_scan_res", "freq_list"
629 };
630 int i, num_fields = sizeof(fields) / sizeof(fields[0]);
631
632 if (arg == 1) {
633 char **res = os_calloc(num_fields + 1, sizeof(char *));
634 if (res == NULL)
635 return NULL;
636 for (i = 0; i < num_fields; i++) {
637 res[i] = os_strdup(fields[i]);
638 if (res[i] == NULL)
639 return res;
640 }
641 return res;
642 }
643
644 if (arg > 1 && os_strncasecmp(str, "set bssid_filter ", 17) == 0)
645 return cli_txt_list_array(&bsses);
646
647 return NULL;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700648}
649
650
651static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
652{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700653 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700654}
655
656
657static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
658{
659 return wpa_ctrl_command(ctrl, "LOGOFF");
660}
661
662
663static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
664{
665 return wpa_ctrl_command(ctrl, "LOGON");
666}
667
668
669static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
670 char *argv[])
671{
672 return wpa_ctrl_command(ctrl, "REASSOCIATE");
673}
674
675
676static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
677 char *argv[])
678{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700679 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700680}
681
682
683static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
684{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700685 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700686}
687
688
689static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
690 char *argv[])
691{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700692 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700693}
694
695
696static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
697 char *argv[])
698{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700699 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700700}
701
702
703static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
704 char *argv[])
705{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700706 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700707}
708
709
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700710static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
711{
712 char cmd[256];
713 int res;
714
715 if (argc < 1)
716 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
717 else
718 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
719 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
720 printf("Too long BSS_FLUSH command.\n");
721 return -1;
722 }
723 return wpa_ctrl_command(ctrl, cmd);
724}
725
726
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700727static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
728 char *argv[])
729{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700730 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700731}
732
733
734static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
735{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700736 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700737}
738
739
740static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
741{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700742 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700743}
744
745
746static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
747{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700748 if (argc == 0) {
749 printf("Invalid WPS_PIN command: need one or two arguments:\n"
750 "- BSSID: use 'any' to select any\n"
751 "- PIN: optional, used only with devices that have no "
752 "display\n");
753 return -1;
754 }
755
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700756 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700757}
758
759
760static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
761 char *argv[])
762{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700763 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700764}
765
766
767static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
768 char *argv[])
769{
770 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
771}
772
773
Dmitry Shmidt04949592012-07-19 12:16:46 -0700774#ifdef CONFIG_WPS_NFC
775
776static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
777{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700778 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700779}
780
781
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800782static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
783 char *argv[])
784{
785 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
786}
787
788
Dmitry Shmidt04949592012-07-19 12:16:46 -0700789static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
790 char *argv[])
791{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700792 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700793}
794
795
796static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
797 char *argv[])
798{
799 int ret;
800 char *buf;
801 size_t buflen;
802
803 if (argc != 1) {
804 printf("Invalid 'wps_nfc_tag_read' command - one argument "
805 "is required.\n");
806 return -1;
807 }
808
809 buflen = 18 + os_strlen(argv[0]);
810 buf = os_malloc(buflen);
811 if (buf == NULL)
812 return -1;
813 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
814
815 ret = wpa_ctrl_command(ctrl, buf);
816 os_free(buf);
817
818 return ret;
819}
820
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800821
822static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
823 char *argv[])
824{
825 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
826}
827
828
829static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
830 char *argv[])
831{
832 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
833}
834
835
836static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
837 char *argv[])
838{
839 int ret;
840 char *buf;
841 size_t buflen;
842
843 if (argc != 1) {
844 printf("Invalid 'nfc_rx_handover_req' command - one argument "
845 "is required.\n");
846 return -1;
847 }
848
849 buflen = 21 + os_strlen(argv[0]);
850 buf = os_malloc(buflen);
851 if (buf == NULL)
852 return -1;
853 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
854
855 ret = wpa_ctrl_command(ctrl, buf);
856 os_free(buf);
857
858 return ret;
859}
860
861
862static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
863 char *argv[])
864{
865 int ret;
866 char *buf;
867 size_t buflen;
868
869 if (argc != 1) {
870 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
871 "is required.\n");
872 return -1;
873 }
874
875 buflen = 21 + os_strlen(argv[0]);
876 buf = os_malloc(buflen);
877 if (buf == NULL)
878 return -1;
879 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
880
881 ret = wpa_ctrl_command(ctrl, buf);
882 os_free(buf);
883
884 return ret;
885}
886
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800887
888static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
889 char *argv[])
890{
891 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
892}
893
Dmitry Shmidt04949592012-07-19 12:16:46 -0700894#endif /* CONFIG_WPS_NFC */
895
896
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700897static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
898{
899 char cmd[256];
900 int res;
901
902 if (argc == 2)
903 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
904 argv[0], argv[1]);
905 else if (argc == 5 || argc == 6) {
906 char ssid_hex[2 * 32 + 1];
907 char key_hex[2 * 64 + 1];
908 int i;
909
910 ssid_hex[0] = '\0';
911 for (i = 0; i < 32; i++) {
912 if (argv[2][i] == '\0')
913 break;
914 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
915 }
916
917 key_hex[0] = '\0';
918 if (argc == 6) {
919 for (i = 0; i < 64; i++) {
920 if (argv[5][i] == '\0')
921 break;
922 os_snprintf(&key_hex[i * 2], 3, "%02x",
923 argv[5][i]);
924 }
925 }
926
927 res = os_snprintf(cmd, sizeof(cmd),
928 "WPS_REG %s %s %s %s %s %s",
929 argv[0], argv[1], ssid_hex, argv[3], argv[4],
930 key_hex);
931 } else {
932 printf("Invalid WPS_REG command: need two arguments:\n"
933 "- BSSID of the target AP\n"
934 "- AP PIN\n");
935 printf("Alternatively, six arguments can be used to "
936 "reconfigure the AP:\n"
937 "- BSSID of the target AP\n"
938 "- AP PIN\n"
939 "- new SSID\n"
940 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
941 "- new encr (NONE, WEP, TKIP, CCMP)\n"
942 "- new key\n");
943 return -1;
944 }
945
946 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
947 printf("Too long WPS_REG command.\n");
948 return -1;
949 }
950 return wpa_ctrl_command(ctrl, cmd);
951}
952
953
954static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
955 char *argv[])
956{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700957 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700958}
959
960
961static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
962 char *argv[])
963{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700964 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700965}
966
967
968static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
969 char *argv[])
970{
971 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
972
973}
974
975
976static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
977 char *argv[])
978{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979 if (argc < 2) {
980 printf("Invalid WPS_ER_PIN command: need at least two "
981 "arguments:\n"
982 "- UUID: use 'any' to select any\n"
983 "- PIN: Enrollee PIN\n"
984 "optional: - Enrollee MAC address\n");
985 return -1;
986 }
987
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700988 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700989}
990
991
992static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
993 char *argv[])
994{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700995 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700996}
997
998
999static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
1000 char *argv[])
1001{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001002 if (argc != 2) {
1003 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
1004 "- UUID: specify which AP to use\n"
1005 "- PIN: AP PIN\n");
1006 return -1;
1007 }
1008
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001009 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001010}
1011
1012
1013static int wpa_cli_cmd_wps_er_set_config(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_SET_CONFIG command: need two "
1018 "arguments:\n"
1019 "- UUID: specify which AP to use\n"
1020 "- Network configuration id\n");
1021 return -1;
1022 }
1023
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001024 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001025}
1026
1027
1028static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1029 char *argv[])
1030{
1031 char cmd[256];
1032 int res;
1033
1034 if (argc == 5 || argc == 6) {
1035 char ssid_hex[2 * 32 + 1];
1036 char key_hex[2 * 64 + 1];
1037 int i;
1038
1039 ssid_hex[0] = '\0';
1040 for (i = 0; i < 32; i++) {
1041 if (argv[2][i] == '\0')
1042 break;
1043 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1044 }
1045
1046 key_hex[0] = '\0';
1047 if (argc == 6) {
1048 for (i = 0; i < 64; i++) {
1049 if (argv[5][i] == '\0')
1050 break;
1051 os_snprintf(&key_hex[i * 2], 3, "%02x",
1052 argv[5][i]);
1053 }
1054 }
1055
1056 res = os_snprintf(cmd, sizeof(cmd),
1057 "WPS_ER_CONFIG %s %s %s %s %s %s",
1058 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1059 key_hex);
1060 } else {
1061 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1062 "- AP UUID\n"
1063 "- AP PIN\n"
1064 "- new SSID\n"
1065 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1066 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1067 "- new key\n");
1068 return -1;
1069 }
1070
1071 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1072 printf("Too long WPS_ER_CONFIG command.\n");
1073 return -1;
1074 }
1075 return wpa_ctrl_command(ctrl, cmd);
1076}
1077
1078
Dmitry Shmidt04949592012-07-19 12:16:46 -07001079#ifdef CONFIG_WPS_NFC
1080static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1081 char *argv[])
1082{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001083 if (argc != 2) {
1084 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1085 "arguments:\n"
1086 "- WPS/NDEF: token format\n"
1087 "- UUID: specify which AP to use\n");
1088 return -1;
1089 }
1090
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001091 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001092}
1093#endif /* CONFIG_WPS_NFC */
1094
1095
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001096static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1097{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001098 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001099}
1100
1101
1102static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1103{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001104 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001105}
1106
1107
1108static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1109{
1110 char cmd[256], *pos, *end;
1111 int i, ret;
1112
1113 if (argc < 2) {
1114 printf("Invalid IDENTITY command: needs two arguments "
1115 "(network id and identity)\n");
1116 return -1;
1117 }
1118
1119 end = cmd + sizeof(cmd);
1120 pos = cmd;
1121 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1122 argv[0], argv[1]);
1123 if (ret < 0 || ret >= end - pos) {
1124 printf("Too long IDENTITY command.\n");
1125 return -1;
1126 }
1127 pos += ret;
1128 for (i = 2; i < argc; i++) {
1129 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1130 if (ret < 0 || ret >= end - pos) {
1131 printf("Too long IDENTITY command.\n");
1132 return -1;
1133 }
1134 pos += ret;
1135 }
1136
1137 return wpa_ctrl_command(ctrl, cmd);
1138}
1139
1140
1141static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1142{
1143 char cmd[256], *pos, *end;
1144 int i, ret;
1145
1146 if (argc < 2) {
1147 printf("Invalid PASSWORD command: needs two arguments "
1148 "(network id and password)\n");
1149 return -1;
1150 }
1151
1152 end = cmd + sizeof(cmd);
1153 pos = cmd;
1154 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1155 argv[0], argv[1]);
1156 if (ret < 0 || ret >= end - pos) {
1157 printf("Too long PASSWORD command.\n");
1158 return -1;
1159 }
1160 pos += ret;
1161 for (i = 2; i < argc; i++) {
1162 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1163 if (ret < 0 || ret >= end - pos) {
1164 printf("Too long PASSWORD command.\n");
1165 return -1;
1166 }
1167 pos += ret;
1168 }
1169
1170 return wpa_ctrl_command(ctrl, cmd);
1171}
1172
1173
1174static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1175 char *argv[])
1176{
1177 char cmd[256], *pos, *end;
1178 int i, ret;
1179
1180 if (argc < 2) {
1181 printf("Invalid NEW_PASSWORD command: needs two arguments "
1182 "(network id and password)\n");
1183 return -1;
1184 }
1185
1186 end = cmd + sizeof(cmd);
1187 pos = cmd;
1188 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1189 argv[0], argv[1]);
1190 if (ret < 0 || ret >= end - pos) {
1191 printf("Too long NEW_PASSWORD command.\n");
1192 return -1;
1193 }
1194 pos += ret;
1195 for (i = 2; i < argc; i++) {
1196 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1197 if (ret < 0 || ret >= end - pos) {
1198 printf("Too long NEW_PASSWORD command.\n");
1199 return -1;
1200 }
1201 pos += ret;
1202 }
1203
1204 return wpa_ctrl_command(ctrl, cmd);
1205}
1206
1207
1208static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1209{
1210 char cmd[256], *pos, *end;
1211 int i, ret;
1212
1213 if (argc < 2) {
1214 printf("Invalid PIN command: needs two arguments "
1215 "(network id and pin)\n");
1216 return -1;
1217 }
1218
1219 end = cmd + sizeof(cmd);
1220 pos = cmd;
1221 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1222 argv[0], argv[1]);
1223 if (ret < 0 || ret >= end - pos) {
1224 printf("Too long PIN command.\n");
1225 return -1;
1226 }
1227 pos += ret;
1228 for (i = 2; i < argc; i++) {
1229 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1230 if (ret < 0 || ret >= end - pos) {
1231 printf("Too long PIN command.\n");
1232 return -1;
1233 }
1234 pos += ret;
1235 }
1236 return wpa_ctrl_command(ctrl, cmd);
1237}
1238
1239
1240static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1241{
1242 char cmd[256], *pos, *end;
1243 int i, ret;
1244
1245 if (argc < 2) {
1246 printf("Invalid OTP command: needs two arguments (network "
1247 "id and password)\n");
1248 return -1;
1249 }
1250
1251 end = cmd + sizeof(cmd);
1252 pos = cmd;
1253 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1254 argv[0], argv[1]);
1255 if (ret < 0 || ret >= end - pos) {
1256 printf("Too long OTP command.\n");
1257 return -1;
1258 }
1259 pos += ret;
1260 for (i = 2; i < argc; i++) {
1261 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1262 if (ret < 0 || ret >= end - pos) {
1263 printf("Too long OTP command.\n");
1264 return -1;
1265 }
1266 pos += ret;
1267 }
1268
1269 return wpa_ctrl_command(ctrl, cmd);
1270}
1271
1272
1273static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1274 char *argv[])
1275{
1276 char cmd[256], *pos, *end;
1277 int i, ret;
1278
1279 if (argc < 2) {
1280 printf("Invalid PASSPHRASE command: needs two arguments "
1281 "(network id and passphrase)\n");
1282 return -1;
1283 }
1284
1285 end = cmd + sizeof(cmd);
1286 pos = cmd;
1287 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1288 argv[0], argv[1]);
1289 if (ret < 0 || ret >= end - pos) {
1290 printf("Too long PASSPHRASE command.\n");
1291 return -1;
1292 }
1293 pos += ret;
1294 for (i = 2; i < argc; i++) {
1295 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1296 if (ret < 0 || ret >= end - pos) {
1297 printf("Too long PASSPHRASE command.\n");
1298 return -1;
1299 }
1300 pos += ret;
1301 }
1302
1303 return wpa_ctrl_command(ctrl, cmd);
1304}
1305
1306
1307static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1308{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001309 if (argc < 2) {
1310 printf("Invalid BSSID command: needs two arguments (network "
1311 "id and BSSID)\n");
1312 return -1;
1313 }
1314
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001315 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001316}
1317
1318
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001319static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1320{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001321 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001322}
1323
1324
1325static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1326{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001327 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001328}
1329
1330
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001331static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1332 char *argv[])
1333{
1334 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1335}
1336
1337
1338static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1339 char *argv[])
1340{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001341 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001342}
1343
1344
1345static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1346 char *argv[])
1347{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001348 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001349}
1350
1351
1352static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1353 char *argv[])
1354{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001355 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001356}
1357
1358
1359static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1360 char *argv[])
1361{
1362 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1363}
1364
1365
1366static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1367 char *argv[])
1368{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001369 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001370}
1371
1372
1373static void wpa_cli_show_network_variables(void)
1374{
1375 printf("set_network variables:\n"
1376 " ssid (network name, SSID)\n"
1377 " psk (WPA passphrase or pre-shared key)\n"
1378 " key_mgmt (key management protocol)\n"
1379 " identity (EAP identity)\n"
1380 " password (EAP password)\n"
1381 " ...\n"
1382 "\n"
1383 "Note: Values are entered in the same format as the "
1384 "configuration file is using,\n"
1385 "i.e., strings values need to be inside double quotation "
1386 "marks.\n"
1387 "For example: set_network 1 ssid \"network name\"\n"
1388 "\n"
1389 "Please see wpa_supplicant.conf documentation for full list "
1390 "of\navailable variables.\n");
1391}
1392
1393
1394static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1395 char *argv[])
1396{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001397 if (argc == 0) {
1398 wpa_cli_show_network_variables();
1399 return 0;
1400 }
1401
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001402 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001403 printf("Invalid SET_NETWORK command: needs three arguments\n"
1404 "(network id, variable name, and value)\n");
1405 return -1;
1406 }
1407
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001408 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001409}
1410
1411
1412static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1413 char *argv[])
1414{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001415 if (argc == 0) {
1416 wpa_cli_show_network_variables();
1417 return 0;
1418 }
1419
1420 if (argc != 2) {
1421 printf("Invalid GET_NETWORK command: needs two arguments\n"
1422 "(network id and variable name)\n");
1423 return -1;
1424 }
1425
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001426 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001427}
1428
1429
Dmitry Shmidt04949592012-07-19 12:16:46 -07001430static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1431 char *argv[])
1432{
1433 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1434}
1435
1436
1437static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1438{
1439 return wpa_ctrl_command(ctrl, "ADD_CRED");
1440}
1441
1442
1443static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1444 char *argv[])
1445{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001446 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001447}
1448
1449
1450static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1451{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001452 if (argc != 3) {
1453 printf("Invalid SET_CRED command: needs three arguments\n"
1454 "(cred id, variable name, and value)\n");
1455 return -1;
1456 }
1457
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001458 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001459}
1460
1461
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001462static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1463 char *argv[])
1464{
1465 return wpa_ctrl_command(ctrl, "DISCONNECT");
1466}
1467
1468
1469static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1470 char *argv[])
1471{
1472 return wpa_ctrl_command(ctrl, "RECONNECT");
1473}
1474
1475
1476static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1477 char *argv[])
1478{
1479 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1480}
1481
1482
1483static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1484{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001485 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001486}
1487
1488
1489static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1490 char *argv[])
1491{
1492 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1493}
1494
1495
1496static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1497{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001498 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001499}
1500
1501
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001502static char ** wpa_cli_complete_bss(const char *str, int pos)
1503{
1504 int arg = get_cmd_arg_num(str, pos);
1505 char **res = NULL;
1506
1507 switch (arg) {
1508 case 1:
1509 res = cli_txt_list_array(&bsses);
1510 break;
1511 }
1512
1513 return res;
1514}
1515
1516
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001517static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1518 char *argv[])
1519{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001520 if (argc < 1 || argc > 2) {
1521 printf("Invalid GET_CAPABILITY command: need either one or "
1522 "two arguments\n");
1523 return -1;
1524 }
1525
1526 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1527 printf("Invalid GET_CAPABILITY command: second argument, "
1528 "if any, must be 'strict'\n");
1529 return -1;
1530 }
1531
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001532 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001533}
1534
1535
1536static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1537{
1538 printf("Available interfaces:\n");
1539 return wpa_ctrl_command(ctrl, "INTERFACES");
1540}
1541
1542
1543static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1544{
1545 if (argc < 1) {
1546 wpa_cli_list_interfaces(ctrl);
1547 return 0;
1548 }
1549
1550 wpa_cli_close_connection();
1551 os_free(ctrl_ifname);
1552 ctrl_ifname = os_strdup(argv[0]);
1553
1554 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1555 printf("Connected to interface '%s.\n", ctrl_ifname);
1556 } else {
1557 printf("Could not connect to interface '%s' - re-trying\n",
1558 ctrl_ifname);
1559 }
1560 return 0;
1561}
1562
1563
1564static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1565 char *argv[])
1566{
1567 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1568}
1569
1570
1571static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1572 char *argv[])
1573{
1574 return wpa_ctrl_command(ctrl, "TERMINATE");
1575}
1576
1577
1578static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1579 char *argv[])
1580{
1581 char cmd[256];
1582 int res;
1583
1584 if (argc < 1) {
1585 printf("Invalid INTERFACE_ADD command: needs at least one "
1586 "argument (interface name)\n"
1587 "All arguments: ifname confname driver ctrl_interface "
1588 "driver_param bridge_name\n");
1589 return -1;
1590 }
1591
1592 /*
1593 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1594 * <driver_param>TAB<bridge_name>
1595 */
1596 res = os_snprintf(cmd, sizeof(cmd),
1597 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1598 argv[0],
1599 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1600 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1601 argc > 5 ? argv[5] : "");
1602 if (res < 0 || (size_t) res >= sizeof(cmd))
1603 return -1;
1604 cmd[sizeof(cmd) - 1] = '\0';
1605 return wpa_ctrl_command(ctrl, cmd);
1606}
1607
1608
1609static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1610 char *argv[])
1611{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001612 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001613}
1614
1615
1616static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1617 char *argv[])
1618{
1619 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1620}
1621
1622
1623#ifdef CONFIG_AP
1624static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1625{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001626 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001627}
1628
1629
1630static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1631 char *addr, size_t addr_len)
1632{
1633 char buf[4096], *pos;
1634 size_t len;
1635 int ret;
1636
1637 if (ctrl_conn == NULL) {
1638 printf("Not connected to hostapd - command dropped.\n");
1639 return -1;
1640 }
1641 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001642 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001643 wpa_cli_msg_cb);
1644 if (ret == -2) {
1645 printf("'%s' command timed out.\n", cmd);
1646 return -2;
1647 } else if (ret < 0) {
1648 printf("'%s' command failed.\n", cmd);
1649 return -1;
1650 }
1651
1652 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001653 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001654 return -1;
1655 printf("%s", buf);
1656
1657 pos = buf;
1658 while (*pos != '\0' && *pos != '\n')
1659 pos++;
1660 *pos = '\0';
1661 os_strlcpy(addr, buf, addr_len);
1662 return 0;
1663}
1664
1665
1666static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1667{
1668 char addr[32], cmd[64];
1669
1670 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1671 return 0;
1672 do {
1673 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1674 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1675
1676 return -1;
1677}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001678
1679
1680static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1681 char *argv[])
1682{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001683 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001684}
1685
1686
1687static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1688 char *argv[])
1689{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001690 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001691}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001692#endif /* CONFIG_AP */
1693
1694
1695static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1696{
1697 return wpa_ctrl_command(ctrl, "SUSPEND");
1698}
1699
1700
1701static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1702{
1703 return wpa_ctrl_command(ctrl, "RESUME");
1704}
1705
1706
1707static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1708{
1709 return wpa_ctrl_command(ctrl, "DROP_SA");
1710}
1711
1712
1713static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1714{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001715 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001716}
1717
1718
1719#ifdef CONFIG_P2P
1720
1721static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1722{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001723 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1724}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001725
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001726
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001727static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1728{
1729 char **res = NULL;
1730 int arg = get_cmd_arg_num(str, pos);
1731
1732 res = os_calloc(6, sizeof(char *));
1733 if (res == NULL)
1734 return NULL;
1735 res[0] = os_strdup("type=social");
1736 if (res[0] == NULL) {
1737 os_free(res);
1738 return NULL;
1739 }
1740 res[1] = os_strdup("type=progressive");
1741 if (res[1] == NULL)
1742 return res;
1743 res[2] = os_strdup("delay=");
1744 if (res[2] == NULL)
1745 return res;
1746 res[3] = os_strdup("dev_id=");
1747 if (res[3] == NULL)
1748 return res;
1749 if (arg == 1)
1750 res[4] = os_strdup("[timeout]");
1751
1752 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001753}
1754
1755
1756static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1757 char *argv[])
1758{
1759 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1760}
1761
1762
1763static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1764 char *argv[])
1765{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001766 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001767}
1768
1769
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001770static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1771{
1772 int arg = get_cmd_arg_num(str, pos);
1773 char **res = NULL;
1774
1775 switch (arg) {
1776 case 1:
1777 res = cli_txt_list_array(&p2p_peers);
1778 break;
1779 }
1780
1781 return res;
1782}
1783
1784
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001785static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1786 char *argv[])
1787{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001788 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001789}
1790
1791
1792static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1793 char *argv[])
1794{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001795 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001796}
1797
1798
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001799static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1800{
1801 int arg = get_cmd_arg_num(str, pos);
1802 char **res = NULL;
1803
1804 switch (arg) {
1805 case 1:
1806 res = cli_txt_list_array(&p2p_groups);
1807 break;
1808 }
1809
1810 return res;
1811}
1812
1813
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001814static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1815 char *argv[])
1816{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001817 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001818}
1819
1820
1821static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1822 char *argv[])
1823{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001824 if (argc != 2 && argc != 3) {
1825 printf("Invalid P2P_PROV_DISC command: needs at least "
1826 "two arguments, address and config method\n"
1827 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001828 return -1;
1829 }
1830
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001831 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001832}
1833
1834
1835static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1836 char *argv[])
1837{
1838 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1839}
1840
1841
1842static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1843 char *argv[])
1844{
1845 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001846
1847 if (argc != 2 && argc != 4) {
1848 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1849 "arguments (address and TLVs) or four arguments "
1850 "(address, \"upnp\", version, search target "
1851 "(SSDP ST:)\n");
1852 return -1;
1853 }
1854
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001855 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001856 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001857 return wpa_ctrl_command(ctrl, cmd);
1858}
1859
1860
1861static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1862 int argc, char *argv[])
1863{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001864 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001865}
1866
1867
1868static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1869 char *argv[])
1870{
1871 char cmd[4096];
1872 int res;
1873
1874 if (argc != 4) {
1875 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1876 "arguments (freq, address, dialog token, and TLVs)\n");
1877 return -1;
1878 }
1879
1880 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1881 argv[0], argv[1], argv[2], argv[3]);
1882 if (res < 0 || (size_t) res >= sizeof(cmd))
1883 return -1;
1884 cmd[sizeof(cmd) - 1] = '\0';
1885 return wpa_ctrl_command(ctrl, cmd);
1886}
1887
1888
1889static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1890 char *argv[])
1891{
1892 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1893}
1894
1895
1896static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1897 int argc, char *argv[])
1898{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001899 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001900}
1901
1902
1903static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1904 char *argv[])
1905{
1906 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1907}
1908
1909
1910static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1911 char *argv[])
1912{
1913 char cmd[4096];
1914 int res;
1915
1916 if (argc != 3 && argc != 4) {
1917 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1918 "arguments\n");
1919 return -1;
1920 }
1921
1922 if (argc == 4)
1923 res = os_snprintf(cmd, sizeof(cmd),
1924 "P2P_SERVICE_ADD %s %s %s %s",
1925 argv[0], argv[1], argv[2], argv[3]);
1926 else
1927 res = os_snprintf(cmd, sizeof(cmd),
1928 "P2P_SERVICE_ADD %s %s %s",
1929 argv[0], argv[1], argv[2]);
1930 if (res < 0 || (size_t) res >= sizeof(cmd))
1931 return -1;
1932 cmd[sizeof(cmd) - 1] = '\0';
1933 return wpa_ctrl_command(ctrl, cmd);
1934}
1935
1936
1937static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1938 char *argv[])
1939{
1940 char cmd[4096];
1941 int res;
1942
1943 if (argc != 2 && argc != 3) {
1944 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1945 "arguments\n");
1946 return -1;
1947 }
1948
1949 if (argc == 3)
1950 res = os_snprintf(cmd, sizeof(cmd),
1951 "P2P_SERVICE_DEL %s %s %s",
1952 argv[0], argv[1], argv[2]);
1953 else
1954 res = os_snprintf(cmd, sizeof(cmd),
1955 "P2P_SERVICE_DEL %s %s",
1956 argv[0], argv[1]);
1957 if (res < 0 || (size_t) res >= sizeof(cmd))
1958 return -1;
1959 cmd[sizeof(cmd) - 1] = '\0';
1960 return wpa_ctrl_command(ctrl, cmd);
1961}
1962
1963
1964static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1965 int argc, char *argv[])
1966{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001967 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001968}
1969
1970
1971static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1972 int argc, char *argv[])
1973{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001974 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001975}
1976
1977
1978static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1979{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001980 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001981}
1982
1983
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001984static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1985{
1986 int arg = get_cmd_arg_num(str, pos);
1987 char **res = NULL;
1988
1989 switch (arg) {
1990 case 1:
1991 res = cli_txt_list_array(&p2p_peers);
1992 break;
1993 }
1994
1995 return res;
1996}
1997
1998
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001999static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
2000 char *addr, size_t addr_len,
2001 int discovered)
2002{
2003 char buf[4096], *pos;
2004 size_t len;
2005 int ret;
2006
2007 if (ctrl_conn == NULL)
2008 return -1;
2009 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002010 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002011 wpa_cli_msg_cb);
2012 if (ret == -2) {
2013 printf("'%s' command timed out.\n", cmd);
2014 return -2;
2015 } else if (ret < 0) {
2016 printf("'%s' command failed.\n", cmd);
2017 return -1;
2018 }
2019
2020 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002021 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002022 return -1;
2023
2024 pos = buf;
2025 while (*pos != '\0' && *pos != '\n')
2026 pos++;
2027 *pos++ = '\0';
2028 os_strlcpy(addr, buf, addr_len);
2029 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2030 printf("%s\n", addr);
2031 return 0;
2032}
2033
2034
2035static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2036{
2037 char addr[32], cmd[64];
2038 int discovered;
2039
2040 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2041
2042 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2043 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002044 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002045 do {
2046 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2047 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2048 discovered) == 0);
2049
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002050 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002051}
2052
2053
2054static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2055{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002056 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002057}
2058
2059
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002060static char ** wpa_cli_complete_p2p_set(const char *str, int pos)
2061{
2062 int arg = get_cmd_arg_num(str, pos);
2063 const char *fields[] = {
2064 "discoverability",
2065 "managed",
2066 "listen_channel",
2067 "ssid_postfix",
2068 "noa",
2069 "ps",
2070 "oppps",
2071 "ctwindow",
2072 "disabled",
2073 "conc_pref",
2074 "force_long_sd",
2075 "peer_filter",
2076 "cross_connect",
2077 "go_apsd",
2078 "client_apsd",
2079 "disallow_freq",
2080 "disc_int",
2081 "per_sta_psk",
2082 };
2083 int i, num_fields = sizeof(fields) / sizeof(fields[0]);
2084
2085 if (arg == 1) {
2086 char **res = os_calloc(num_fields + 1, sizeof(char *));
2087 if (res == NULL)
2088 return NULL;
2089 for (i = 0; i < num_fields; i++) {
2090 res[i] = os_strdup(fields[i]);
2091 if (res[i] == NULL)
2092 return res;
2093 }
2094 return res;
2095 }
2096
2097 if (arg == 2 && os_strncasecmp(str, "p2p_set peer_filter ", 20) == 0)
2098 return cli_txt_list_array(&p2p_peers);
2099
2100 return NULL;
2101}
2102
2103
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002104static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2105{
2106 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2107}
2108
2109
2110static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2111 char *argv[])
2112{
2113 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2114}
2115
2116
2117static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2118 char *argv[])
2119{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002120 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002121}
2122
2123
2124static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2125 char *argv[])
2126{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002127 if (argc != 0 && argc != 2 && argc != 4) {
2128 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2129 "(preferred duration, interval; in microsecods).\n"
2130 "Optional second pair can be used to provide "
2131 "acceptable values.\n");
2132 return -1;
2133 }
2134
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002135 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002136}
2137
2138
2139static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2140 char *argv[])
2141{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002142 if (argc != 0 && argc != 2) {
2143 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2144 "(availability period, availability interval; in "
2145 "millisecods).\n"
2146 "Extended Listen Timing can be cancelled with this "
2147 "command when used without parameters.\n");
2148 return -1;
2149 }
2150
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002151 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2152}
2153
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002154
2155static int wpa_cli_cmd_p2p_remove_client(struct wpa_ctrl *ctrl, int argc,
2156 char *argv[])
2157{
2158 return wpa_cli_cmd(ctrl, "P2P_REMOVE_CLIENT", 1, argc, argv);
2159}
2160
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002161#endif /* CONFIG_P2P */
2162
2163#ifdef CONFIG_WIFI_DISPLAY
2164
2165static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2166 char *argv[])
2167{
2168 char cmd[100];
2169 int res;
2170
2171 if (argc != 1 && argc != 2) {
2172 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2173 "arguments (subelem, hexdump)\n");
2174 return -1;
2175 }
2176
2177 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2178 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002179 if (res < 0 || (size_t) res >= sizeof(cmd))
2180 return -1;
2181 cmd[sizeof(cmd) - 1] = '\0';
2182 return wpa_ctrl_command(ctrl, cmd);
2183}
2184
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002185
2186static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2187 char *argv[])
2188{
2189 char cmd[100];
2190 int res;
2191
2192 if (argc != 1) {
2193 printf("Invalid WFD_SUBELEM_GET command: needs one "
2194 "argument (subelem)\n");
2195 return -1;
2196 }
2197
2198 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2199 argv[0]);
2200 if (res < 0 || (size_t) res >= sizeof(cmd))
2201 return -1;
2202 cmd[sizeof(cmd) - 1] = '\0';
2203 return wpa_ctrl_command(ctrl, cmd);
2204}
2205#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002206
2207
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002208#ifdef CONFIG_INTERWORKING
2209static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2210 char *argv[])
2211{
2212 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2213}
2214
2215
2216static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2217 char *argv[])
2218{
2219 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2220}
2221
2222
2223static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2224 char *argv[])
2225{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002226 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002227}
2228
2229
2230static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2231 char *argv[])
2232{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002233 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002234}
2235
2236
2237static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2238{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002239 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2240}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002241
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002242
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002243static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2244 char *argv[])
2245{
2246 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2247}
2248
2249
2250static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2251 char *argv[])
2252{
2253 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002254}
2255#endif /* CONFIG_INTERWORKING */
2256
2257
Dmitry Shmidt04949592012-07-19 12:16:46 -07002258#ifdef CONFIG_HS20
2259
2260static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2261 char *argv[])
2262{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002263 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002264}
2265
2266
2267static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2268 char *argv[])
2269{
2270 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002271
2272 if (argc == 0) {
2273 printf("Command needs one or two arguments (dst mac addr and "
2274 "optional home realm)\n");
2275 return -1;
2276 }
2277
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002278 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2279 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002280 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002281
2282 return wpa_ctrl_command(ctrl, cmd);
2283}
2284
2285#endif /* CONFIG_HS20 */
2286
2287
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002288static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2289 char *argv[])
2290{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002291 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002292}
2293
2294
2295static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2296 char *argv[])
2297{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002298 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002299}
2300
2301
2302static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2303 char *argv[])
2304{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002305 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002306}
2307
2308
2309static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2310 char *argv[])
2311{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002312 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002313}
2314
2315
2316static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2317 char *argv[])
2318{
2319 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2320}
2321
2322
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002323static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2324 char *argv[])
2325{
2326 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2327}
2328
2329
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002330static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2331 char *argv[])
2332{
2333 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2334}
2335
Dmitry Shmidt04949592012-07-19 12:16:46 -07002336
2337#ifdef CONFIG_AUTOSCAN
2338
2339static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2340{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002341 if (argc == 0)
2342 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2343
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002344 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002345}
2346
2347#endif /* CONFIG_AUTOSCAN */
2348
2349
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002350#ifdef CONFIG_WNM
2351
2352static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2353{
2354 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2355}
2356
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002357
2358static int wpa_cli_cmd_wnm_bss_query(struct wpa_ctrl *ctrl, int argc, char *argv[])
2359{
2360 return wpa_cli_cmd(ctrl, "WNM_BSS_QUERY", 1, argc, argv);
2361}
2362
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002363#endif /* CONFIG_WNM */
2364
2365
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002366static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2367{
2368 if (argc == 0)
2369 return -1;
2370 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2371}
2372
2373
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002374#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002375static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2376{
2377 char cmd[256];
2378 int i;
2379 int len;
2380
2381 if (argc < 1) {
2382 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2383 return -1;
2384 }
2385
2386 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2387 for (i=1; i < argc; i++)
2388 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2389 cmd[sizeof(cmd) - 1] = '\0';
2390 printf("%s: %s\n", __func__, cmd);
2391 return wpa_ctrl_command(ctrl, cmd);
2392}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002393#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002394
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002395
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002396static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2397{
2398 return wpa_ctrl_command(ctrl, "FLUSH");
2399}
2400
2401
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002402enum wpa_cli_cmd_flags {
2403 cli_cmd_flag_none = 0x00,
2404 cli_cmd_flag_sensitive = 0x01
2405};
2406
2407struct wpa_cli_cmd {
2408 const char *cmd;
2409 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002410 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002411 enum wpa_cli_cmd_flags flags;
2412 const char *usage;
2413};
2414
2415static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002416 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002417 cli_cmd_flag_none,
2418 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002419 { "ifname", wpa_cli_cmd_ifname, NULL,
2420 cli_cmd_flag_none,
2421 "= get current interface name" },
2422 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002423 cli_cmd_flag_none,
2424 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002425 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002426 cli_cmd_flag_none,
2427 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002428 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002429 cli_cmd_flag_none,
2430 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002431 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002432 cli_cmd_flag_none,
2433 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002434 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002435 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002436 "[command] = show usage help" },
2437 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002438 cli_cmd_flag_none,
2439 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002440 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002441 cli_cmd_flag_none,
2442 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002443 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002444 cli_cmd_flag_none,
2445 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002446 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002447 cli_cmd_flag_none,
2448 "= exit wpa_cli" },
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07002449 { "set", wpa_cli_cmd_set, wpa_cli_complete_set,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002450 cli_cmd_flag_none,
2451 "= set variables (shows list of variables when run without "
2452 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002453 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002454 cli_cmd_flag_none,
2455 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002456 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002457 cli_cmd_flag_none,
2458 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002459 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002460 cli_cmd_flag_none,
2461 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002462 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002463 cli_cmd_flag_none,
2464 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002465 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002466 cli_cmd_flag_none,
2467 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002468 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002469 cli_cmd_flag_none,
2470 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002471 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002472 cli_cmd_flag_none,
2473 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002474 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002475 cli_cmd_flag_sensitive,
2476 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002477 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002478 cli_cmd_flag_sensitive,
2479 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002480 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002481 cli_cmd_flag_sensitive,
2482 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002483 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002484 cli_cmd_flag_sensitive,
2485 "<network id> <password> = configure one-time-password for an SSID"
2486 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002487 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002488 cli_cmd_flag_sensitive,
2489 "<network id> <passphrase> = configure private key passphrase\n"
2490 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002491 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002492 cli_cmd_flag_none,
2493 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002494 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002495 cli_cmd_flag_none,
2496 "<BSSID> = add a BSSID to the blacklist\n"
2497 "blacklist clear = clear the blacklist\n"
2498 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002499 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002500 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002501 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002502 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002503 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002504 cli_cmd_flag_none,
2505 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002506 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002507 cli_cmd_flag_none,
2508 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002509 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002510 cli_cmd_flag_none,
2511 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002512 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002513 cli_cmd_flag_none,
2514 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002515 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002516 cli_cmd_flag_none,
2517 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002518 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002519 cli_cmd_flag_none,
2520 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002521 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002522 cli_cmd_flag_sensitive,
2523 "<network id> <variable> <value> = set network variables (shows\n"
2524 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002525 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 cli_cmd_flag_none,
2527 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002528 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002529 cli_cmd_flag_none,
2530 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002531 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002532 cli_cmd_flag_none,
2533 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002534 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002535 cli_cmd_flag_none,
2536 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002537 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002538 cli_cmd_flag_sensitive,
2539 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002540 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002541 cli_cmd_flag_none,
2542 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002543 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002544 cli_cmd_flag_none,
2545 "= disconnect and wait for reassociate/reconnect command before\n"
2546 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002547 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002548 cli_cmd_flag_none,
2549 "= like reassociate, but only takes effect if already disconnected"
2550 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002551 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002552 cli_cmd_flag_none,
2553 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002554 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002555 cli_cmd_flag_none,
2556 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002557 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002558 cli_cmd_flag_none,
2559 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002560 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002561 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002562 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002563 "= get capabilies" },
2564 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002565 cli_cmd_flag_none,
2566 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002567 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002568 cli_cmd_flag_none,
2569 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002570 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002571 cli_cmd_flag_none,
2572 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2573 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2574 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002575 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002576 cli_cmd_flag_none,
2577 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002578 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002579 cli_cmd_flag_none,
2580 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002581 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002582 cli_cmd_flag_none,
2583 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002584 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002585 cli_cmd_flag_none,
2586 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002587 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002588 cli_cmd_flag_none,
2589 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002590 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002591 cli_cmd_flag_none,
2592 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002593 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002594 cli_cmd_flag_none,
2595 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002596 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002597 cli_cmd_flag_none,
2598 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002599 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002600 cli_cmd_flag_none,
2601 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002602 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603 cli_cmd_flag_none,
2604 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002605 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002606 cli_cmd_flag_sensitive,
2607 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2608 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002609 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002610 cli_cmd_flag_sensitive,
2611 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002612 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002613 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002614#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002615 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002616 cli_cmd_flag_none,
2617 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002618 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2619 cli_cmd_flag_none,
2620 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002621 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002622 cli_cmd_flag_none,
2623 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002624 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002625 cli_cmd_flag_sensitive,
2626 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002627 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2628 cli_cmd_flag_none,
2629 "<NDEF> <WPS> = create NFC handover request" },
2630 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2631 cli_cmd_flag_none,
2632 "<NDEF> <WPS> = create NFC handover select" },
2633 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2634 cli_cmd_flag_none,
2635 "<hexdump of payload> = report received NFC handover request" },
2636 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2637 cli_cmd_flag_none,
2638 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002639 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2640 cli_cmd_flag_none,
2641 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2642 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002643#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002644 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002645 cli_cmd_flag_sensitive,
2646 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002647 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648 cli_cmd_flag_sensitive,
2649 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002650 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002651 cli_cmd_flag_none,
2652 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002653 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002654 cli_cmd_flag_none,
2655 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002656 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002657 cli_cmd_flag_sensitive,
2658 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002659 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002660 cli_cmd_flag_none,
2661 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002662 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002663 cli_cmd_flag_sensitive,
2664 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002665 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002666 cli_cmd_flag_none,
2667 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002668 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002669 cli_cmd_flag_sensitive,
2670 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002671#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002672 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002673 cli_cmd_flag_none,
2674 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2675#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002676 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002677 cli_cmd_flag_none,
2678 "<addr> = request RSN authentication with <addr> in IBSS" },
2679#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002680 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002681 cli_cmd_flag_none,
2682 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002683 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002684 cli_cmd_flag_none,
2685 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002686 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002687 cli_cmd_flag_none,
2688 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002689 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002690 cli_cmd_flag_none,
2691 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002692#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002693 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002694 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002695 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002696 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002697 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002698 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002699 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002700 cli_cmd_flag_none,
2701 "<addr> = roam to the specified BSS" },
2702#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002703 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2704 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002705 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002706 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002707 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002708 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2709 cli_cmd_flag_none,
2710 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2711 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002712 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002713 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2714 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002715 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002716 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2717 "[ht40] = add a new P2P group (local end as GO)" },
2718 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2719 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002720 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002721 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002722 cli_cmd_flag_none,
2723 "= get the passphrase for a group (GO only)" },
2724 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002725 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002726 "<addr> <TLVs> = schedule service discovery request" },
2727 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002728 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002729 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002730 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002731 cli_cmd_flag_none,
2732 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002733 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002734 cli_cmd_flag_none,
2735 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002736 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002737 cli_cmd_flag_none,
2738 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002739 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002740 cli_cmd_flag_none,
2741 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002742 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002743 cli_cmd_flag_none,
2744 "<bonjour|upnp> <query|version> <response|service> = add a local "
2745 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002746 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002747 cli_cmd_flag_none,
2748 "<bonjour|upnp> <query|version> [|service] = remove a local "
2749 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002750 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002751 cli_cmd_flag_none,
2752 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002753 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002754 cli_cmd_flag_none,
2755 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002756 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002757 "[discovered] = list known (optionally, only fully discovered) P2P "
2758 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002759 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2760 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002761 "<address> = show information about known P2P peer" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002762 { "p2p_set", wpa_cli_cmd_p2p_set, wpa_cli_complete_p2p_set,
2763 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002764 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002765 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002766 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002767 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002768 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002769 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2770 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002771 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002772 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2773 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002774 "[<duration> <interval>] [<duration> <interval>] = request GO "
2775 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002776 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2777 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002778 "[<period> <interval>] = set extended listen timing" },
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07002779 { "p2p_remove_client", wpa_cli_cmd_p2p_remove_client,
2780 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2781 "<address|iface=address> = remove a peer from all groups" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002782#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002783#ifdef CONFIG_WIFI_DISPLAY
2784 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2785 cli_cmd_flag_none,
2786 "<subelem> [contents] = set Wi-Fi Display subelement" },
2787 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2788 cli_cmd_flag_none,
2789 "<subelem> = get Wi-Fi Display subelement" },
2790#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002791#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002792 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002793 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002794 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2795 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002796 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002797 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002798 cli_cmd_flag_none,
2799 "[auto] = perform Interworking network selection" },
2800 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002801 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002802 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002803 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2804 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002805 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002806 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2807 cli_cmd_flag_none,
2808 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2809 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2810 wpa_cli_complete_bss, cli_cmd_flag_none,
2811 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002812#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002813#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002814 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2815 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002816 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2817 },
2818 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002819 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002820 "<addr> <home realm> = get HS20 nai home realm list" },
2821#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002822 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2823 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002824 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002825 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002826 cli_cmd_flag_none,
2827 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002828 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002829 cli_cmd_flag_none,
2830 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002831 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002832 cli_cmd_flag_none,
2833 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002834 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002835 cli_cmd_flag_none,
2836 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002837 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002838 cli_cmd_flag_none,
2839 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002840 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2841 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002842 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002843#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002844 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002845 "[params] = Set or unset (if none) autoscan parameters" },
2846#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002847#ifdef CONFIG_WNM
2848 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2849 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
Dmitry Shmidt44c95782013-05-17 09:51:35 -07002850 { "wnm_bss_query", wpa_cli_cmd_wnm_bss_query, NULL, cli_cmd_flag_none,
2851 "<query reason> = Send BSS Transition Management Query" },
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002852#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002853 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2854 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002855 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2856 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002857#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002858 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002859 cli_cmd_flag_none,
2860 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002861#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002862 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002863};
2864
2865
2866/*
2867 * Prints command usage, lines are padded with the specified string.
2868 */
2869static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2870{
2871 char c;
2872 size_t n;
2873
2874 printf("%s%s ", pad, cmd->cmd);
2875 for (n = 0; (c = cmd->usage[n]); n++) {
2876 printf("%c", c);
2877 if (c == '\n')
2878 printf("%s", pad);
2879 }
2880 printf("\n");
2881}
2882
2883
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002884static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002885{
2886 int n;
2887 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002888 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2889 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2890 print_cmd_help(&wpa_cli_commands[n], " ");
2891 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002892}
2893
2894
2895static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2896{
2897 const char *c, *delim;
2898 int n;
2899 size_t len;
2900
2901 delim = os_strchr(cmd, ' ');
2902 if (delim)
2903 len = delim - cmd;
2904 else
2905 len = os_strlen(cmd);
2906
2907 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2908 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2909 return (wpa_cli_commands[n].flags &
2910 cli_cmd_flag_sensitive);
2911 }
2912 return 0;
2913}
2914
2915
2916static char ** wpa_list_cmd_list(void)
2917{
2918 char **res;
2919 int i, count;
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002920 struct cli_txt_entry *e;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002921
2922 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002923 count += dl_list_len(&p2p_groups);
2924 count += dl_list_len(&ifnames);
2925 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002926 if (res == NULL)
2927 return NULL;
2928
2929 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2930 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2931 if (res[i] == NULL)
2932 break;
2933 }
2934
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002935 dl_list_for_each(e, &p2p_groups, struct cli_txt_entry, list) {
2936 size_t len = 8 + os_strlen(e->txt);
2937 res[i] = os_malloc(len);
2938 if (res[i] == NULL)
2939 break;
2940 os_snprintf(res[i], len, "ifname=%s", e->txt);
2941 i++;
2942 }
2943
2944 dl_list_for_each(e, &ifnames, struct cli_txt_entry, list) {
2945 res[i] = os_strdup(e->txt);
2946 if (res[i] == NULL)
2947 break;
2948 i++;
2949 }
2950
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002951 return res;
2952}
2953
2954
2955static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2956 int pos)
2957{
2958 int i;
2959
2960 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2961 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002962 if (wpa_cli_commands[i].completion)
2963 return wpa_cli_commands[i].completion(str,
2964 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002965 edit_clear_line();
2966 printf("\r%s\n", wpa_cli_commands[i].usage);
2967 edit_redraw();
2968 break;
2969 }
2970 }
2971
2972 return NULL;
2973}
2974
2975
2976static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2977{
2978 char **res;
2979 const char *end;
2980 char *cmd;
2981
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07002982 if (pos > 7 && os_strncasecmp(str, "IFNAME=", 7) == 0) {
2983 end = os_strchr(str, ' ');
2984 if (end && pos > end - str) {
2985 pos -= end - str + 1;
2986 str = end + 1;
2987 }
2988 }
2989
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002990 end = os_strchr(str, ' ');
2991 if (end == NULL || str + pos < end)
2992 return wpa_list_cmd_list();
2993
2994 cmd = os_malloc(pos + 1);
2995 if (cmd == NULL)
2996 return NULL;
2997 os_memcpy(cmd, str, pos);
2998 cmd[end - str] = '\0';
2999 res = wpa_cli_cmd_completion(cmd, str, pos);
3000 os_free(cmd);
3001 return res;
3002}
3003
3004
3005static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
3006{
3007 struct wpa_cli_cmd *cmd, *match = NULL;
3008 int count;
3009 int ret = 0;
3010
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003011 if (argc > 1 && os_strncasecmp(argv[0], "IFNAME=", 7) == 0) {
3012 ifname_prefix = argv[0] + 7;
3013 argv = &argv[1];
3014 argc--;
3015 } else
3016 ifname_prefix = NULL;
3017
3018 if (argc == 0)
3019 return -1;
3020
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003021 count = 0;
3022 cmd = wpa_cli_commands;
3023 while (cmd->cmd) {
3024 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
3025 {
3026 match = cmd;
3027 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
3028 /* we have an exact match */
3029 count = 1;
3030 break;
3031 }
3032 count++;
3033 }
3034 cmd++;
3035 }
3036
3037 if (count > 1) {
3038 printf("Ambiguous command '%s'; possible commands:", argv[0]);
3039 cmd = wpa_cli_commands;
3040 while (cmd->cmd) {
3041 if (os_strncasecmp(cmd->cmd, argv[0],
3042 os_strlen(argv[0])) == 0) {
3043 printf(" %s", cmd->cmd);
3044 }
3045 cmd++;
3046 }
3047 printf("\n");
3048 ret = 1;
3049 } else if (count == 0) {
3050 printf("Unknown command '%s'\n", argv[0]);
3051 ret = 1;
3052 } else {
3053 ret = match->handler(ctrl, argc - 1, &argv[1]);
3054 }
3055
3056 return ret;
3057}
3058
3059
3060static int str_match(const char *a, const char *b)
3061{
3062 return os_strncmp(a, b, os_strlen(b)) == 0;
3063}
3064
3065
3066static int wpa_cli_exec(const char *program, const char *arg1,
3067 const char *arg2)
3068{
3069 char *cmd;
3070 size_t len;
3071 int res;
3072 int ret = 0;
3073
3074 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
3075 cmd = os_malloc(len);
3076 if (cmd == NULL)
3077 return -1;
3078 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
3079 if (res < 0 || (size_t) res >= len) {
3080 os_free(cmd);
3081 return -1;
3082 }
3083 cmd[len - 1] = '\0';
3084#ifndef _WIN32_WCE
3085 if (system(cmd) < 0)
3086 ret = -1;
3087#endif /* _WIN32_WCE */
3088 os_free(cmd);
3089
3090 return ret;
3091}
3092
3093
3094static void wpa_cli_action_process(const char *msg)
3095{
3096 const char *pos;
3097 char *copy = NULL, *id, *pos2;
3098
3099 pos = msg;
3100 if (*pos == '<') {
3101 /* skip priority */
3102 pos = os_strchr(pos, '>');
3103 if (pos)
3104 pos++;
3105 else
3106 pos = msg;
3107 }
3108
3109 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3110 int new_id = -1;
3111 os_unsetenv("WPA_ID");
3112 os_unsetenv("WPA_ID_STR");
3113 os_unsetenv("WPA_CTRL_DIR");
3114
3115 pos = os_strstr(pos, "[id=");
3116 if (pos)
3117 copy = os_strdup(pos + 4);
3118
3119 if (copy) {
3120 pos2 = id = copy;
3121 while (*pos2 && *pos2 != ' ')
3122 pos2++;
3123 *pos2++ = '\0';
3124 new_id = atoi(id);
3125 os_setenv("WPA_ID", id, 1);
3126 while (*pos2 && *pos2 != '=')
3127 pos2++;
3128 if (*pos2 == '=')
3129 pos2++;
3130 id = pos2;
3131 while (*pos2 && *pos2 != ']')
3132 pos2++;
3133 *pos2 = '\0';
3134 os_setenv("WPA_ID_STR", id, 1);
3135 os_free(copy);
3136 }
3137
3138 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3139
Dmitry Shmidt391c59f2013-09-03 12:16:28 -07003140 if (wpa_cli_connected <= 0 || new_id != wpa_cli_last_id) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003141 wpa_cli_connected = 1;
3142 wpa_cli_last_id = new_id;
3143 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3144 }
3145 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3146 if (wpa_cli_connected) {
3147 wpa_cli_connected = 0;
3148 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3149 }
3150 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3151 wpa_cli_exec(action_file, ctrl_ifname, pos);
3152 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3153 wpa_cli_exec(action_file, ctrl_ifname, pos);
3154 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3155 wpa_cli_exec(action_file, ctrl_ifname, pos);
3156 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3157 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003158 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3159 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003160 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3161 wpa_cli_exec(action_file, ctrl_ifname, pos);
3162 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3163 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003164 } else if (str_match(pos, AP_STA_CONNECTED)) {
3165 wpa_cli_exec(action_file, ctrl_ifname, pos);
3166 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3167 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003168 } else if (str_match(pos, ESS_DISASSOC_IMMINENT)) {
3169 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003170 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3171 printf("wpa_supplicant is terminating - stop monitoring\n");
3172 wpa_cli_quit = 1;
3173 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003174}
3175
3176
3177#ifndef CONFIG_ANSI_C_EXTRA
3178static void wpa_cli_action_cb(char *msg, size_t len)
3179{
3180 wpa_cli_action_process(msg);
3181}
3182#endif /* CONFIG_ANSI_C_EXTRA */
3183
3184
3185static void wpa_cli_reconnect(void)
3186{
3187 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003188 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3189 return;
3190
3191 if (interactive) {
3192 edit_clear_line();
3193 printf("\rConnection to wpa_supplicant re-established\n");
3194 edit_redraw();
3195 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003196}
3197
3198
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003199static void cli_event(const char *str)
3200{
3201 const char *start, *s;
3202
3203 start = os_strchr(str, '>');
3204 if (start == NULL)
3205 return;
3206
3207 start++;
3208
3209 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3210 s = os_strchr(start, ' ');
3211 if (s == NULL)
3212 return;
3213 s = os_strchr(s + 1, ' ');
3214 if (s == NULL)
3215 return;
3216 cli_txt_list_add(&bsses, s + 1);
3217 return;
3218 }
3219
3220 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3221 s = os_strchr(start, ' ');
3222 if (s == NULL)
3223 return;
3224 s = os_strchr(s + 1, ' ');
3225 if (s == NULL)
3226 return;
3227 cli_txt_list_del_addr(&bsses, s + 1);
3228 return;
3229 }
3230
3231#ifdef CONFIG_P2P
3232 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3233 s = os_strstr(start, " p2p_dev_addr=");
3234 if (s == NULL)
3235 return;
3236 cli_txt_list_add_addr(&p2p_peers, s + 14);
3237 return;
3238 }
3239
3240 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3241 s = os_strstr(start, " p2p_dev_addr=");
3242 if (s == NULL)
3243 return;
3244 cli_txt_list_del_addr(&p2p_peers, s + 14);
3245 return;
3246 }
3247
3248 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3249 s = os_strchr(start, ' ');
3250 if (s == NULL)
3251 return;
3252 cli_txt_list_add_word(&p2p_groups, s + 1);
3253 return;
3254 }
3255
3256 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3257 s = os_strchr(start, ' ');
3258 if (s == NULL)
3259 return;
3260 cli_txt_list_del_word(&p2p_groups, s + 1);
3261 return;
3262 }
3263#endif /* CONFIG_P2P */
3264}
3265
3266
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003267static int check_terminating(const char *msg)
3268{
3269 const char *pos = msg;
3270
3271 if (*pos == '<') {
3272 /* skip priority */
3273 pos = os_strchr(pos, '>');
3274 if (pos)
3275 pos++;
3276 else
3277 pos = msg;
3278 }
3279
3280 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3281 edit_clear_line();
3282 printf("\rConnection to wpa_supplicant lost - trying to "
3283 "reconnect\n");
3284 edit_redraw();
3285 wpa_cli_attached = 0;
3286 wpa_cli_close_connection();
3287 return 1;
3288 }
3289
3290 return 0;
3291}
3292
3293
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003294static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3295{
3296 if (ctrl_conn == NULL) {
3297 wpa_cli_reconnect();
3298 return;
3299 }
3300 while (wpa_ctrl_pending(ctrl) > 0) {
3301 char buf[256];
3302 size_t len = sizeof(buf) - 1;
3303 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3304 buf[len] = '\0';
3305 if (action_monitor)
3306 wpa_cli_action_process(buf);
3307 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003308 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003309 if (wpa_cli_show_event(buf)) {
3310 edit_clear_line();
3311 printf("\r%s\n", buf);
3312 edit_redraw();
3313 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003314
3315 if (interactive && check_terminating(buf) > 0)
3316 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003317 }
3318 } else {
3319 printf("Could not read pending message.\n");
3320 break;
3321 }
3322 }
3323
3324 if (wpa_ctrl_pending(ctrl) < 0) {
3325 printf("Connection to wpa_supplicant lost - trying to "
3326 "reconnect\n");
3327 wpa_cli_reconnect();
3328 }
3329}
3330
3331#define max_args 10
3332
3333static int tokenize_cmd(char *cmd, char *argv[])
3334{
3335 char *pos;
3336 int argc = 0;
3337
3338 pos = cmd;
3339 for (;;) {
3340 while (*pos == ' ')
3341 pos++;
3342 if (*pos == '\0')
3343 break;
3344 argv[argc] = pos;
3345 argc++;
3346 if (argc == max_args)
3347 break;
3348 if (*pos == '"') {
3349 char *pos2 = os_strrchr(pos, '"');
3350 if (pos2)
3351 pos = pos2 + 1;
3352 }
3353 while (*pos != '\0' && *pos != ' ')
3354 pos++;
3355 if (*pos == ' ')
3356 *pos++ = '\0';
3357 }
3358
3359 return argc;
3360}
3361
3362
3363static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3364{
3365 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3366 printf("Connection to wpa_supplicant lost - trying to "
3367 "reconnect\n");
3368 wpa_cli_close_connection();
3369 }
3370 if (!ctrl_conn)
3371 wpa_cli_reconnect();
3372 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3373}
3374
3375
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003376static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3377{
3378 wpa_cli_recv_pending(mon_conn, 0);
3379}
3380
3381
3382static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3383{
3384 char *argv[max_args];
3385 int argc;
3386 argc = tokenize_cmd(cmd, argv);
3387 if (argc)
3388 wpa_request(ctrl_conn, argc, argv);
3389}
3390
3391
3392static void wpa_cli_edit_eof_cb(void *ctx)
3393{
3394 eloop_terminate();
3395}
3396
3397
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003398static int warning_displayed = 0;
3399static char *hfile = NULL;
3400static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003401
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003402static void start_edit(void)
3403{
3404 char *home;
3405 char *ps = NULL;
3406
3407#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3408 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3409#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003410
3411 home = getenv("HOME");
3412 if (home) {
3413 const char *fname = ".wpa_cli_history";
3414 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3415 hfile = os_malloc(hfile_len);
3416 if (hfile)
3417 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3418 }
3419
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003420 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3421 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3422 eloop_terminate();
3423 return;
3424 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003425
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003426 edit_started = 1;
3427 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3428}
3429
3430
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003431static void update_bssid_list(struct wpa_ctrl *ctrl)
3432{
3433 char buf[4096];
3434 size_t len = sizeof(buf);
3435 int ret;
3436 char *cmd = "BSS RANGE=ALL MASK=0x2";
3437 char *pos, *end;
3438
3439 if (ctrl == NULL)
3440 return;
3441 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3442 if (ret < 0)
3443 return;
3444 buf[len] = '\0';
3445
3446 pos = buf;
3447 while (pos) {
3448 pos = os_strstr(pos, "bssid=");
3449 if (pos == NULL)
3450 break;
3451 pos += 6;
3452 end = os_strchr(pos, '\n');
3453 if (end == NULL)
3454 break;
3455 *end = '\0';
3456 cli_txt_list_add(&bsses, pos);
3457 pos = end + 1;
3458 }
3459}
3460
3461
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003462static void update_ifnames(struct wpa_ctrl *ctrl)
3463{
3464 char buf[4096];
3465 size_t len = sizeof(buf);
3466 int ret;
3467 char *cmd = "INTERFACES";
3468 char *pos, *end;
3469 char txt[200];
3470
3471 cli_txt_list_flush(&ifnames);
3472
3473 if (ctrl == NULL)
3474 return;
3475 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, NULL);
3476 if (ret < 0)
3477 return;
3478 buf[len] = '\0';
3479
3480 pos = buf;
3481 while (pos) {
3482 end = os_strchr(pos, '\n');
3483 if (end == NULL)
3484 break;
3485 *end = '\0';
3486 ret = os_snprintf(txt, sizeof(txt), "ifname=%s", pos);
3487 if (ret > 0 && ret < (int) sizeof(txt))
3488 cli_txt_list_add(&ifnames, txt);
3489 pos = end + 1;
3490 }
3491}
3492
3493
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003494static void try_connection(void *eloop_ctx, void *timeout_ctx)
3495{
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003496 if (ctrl_conn)
3497 goto done;
3498
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003499 if (ctrl_ifname == NULL)
3500 ctrl_ifname = wpa_cli_get_default_ifname();
3501
3502 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3503 if (!warning_displayed) {
3504 printf("Could not connect to wpa_supplicant: "
3505 "%s - re-trying\n", ctrl_ifname);
3506 warning_displayed = 1;
3507 }
3508 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3509 return;
3510 }
3511
Dmitry Shmidt51b6ea82013-05-08 10:42:09 -07003512 update_bssid_list(ctrl_conn);
3513
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003514 if (warning_displayed)
3515 printf("Connection established.\n");
3516
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003517done:
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003518 start_edit();
3519}
3520
3521
3522static void wpa_cli_interactive(void)
3523{
3524 printf("\nInteractive mode\n\n");
3525
3526 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003527 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003528 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003529
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003530 cli_txt_list_flush(&p2p_peers);
3531 cli_txt_list_flush(&p2p_groups);
3532 cli_txt_list_flush(&bsses);
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003533 cli_txt_list_flush(&ifnames);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003534 if (edit_started)
3535 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003536 os_free(hfile);
3537 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3538 wpa_cli_close_connection();
3539}
3540
3541
3542static void wpa_cli_action(struct wpa_ctrl *ctrl)
3543{
3544#ifdef CONFIG_ANSI_C_EXTRA
3545 /* TODO: ANSI C version(?) */
3546 printf("Action processing not supported in ANSI C build.\n");
3547#else /* CONFIG_ANSI_C_EXTRA */
3548 fd_set rfds;
3549 int fd, res;
3550 struct timeval tv;
3551 char buf[256]; /* note: large enough to fit in unsolicited messages */
3552 size_t len;
3553
3554 fd = wpa_ctrl_get_fd(ctrl);
3555
3556 while (!wpa_cli_quit) {
3557 FD_ZERO(&rfds);
3558 FD_SET(fd, &rfds);
3559 tv.tv_sec = ping_interval;
3560 tv.tv_usec = 0;
3561 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3562 if (res < 0 && errno != EINTR) {
3563 perror("select");
3564 break;
3565 }
3566
3567 if (FD_ISSET(fd, &rfds))
3568 wpa_cli_recv_pending(ctrl, 1);
3569 else {
3570 /* verify that connection is still working */
3571 len = sizeof(buf) - 1;
3572 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3573 wpa_cli_action_cb) < 0 ||
3574 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3575 printf("wpa_supplicant did not reply to PING "
3576 "command - exiting\n");
3577 break;
3578 }
3579 }
3580 }
3581#endif /* CONFIG_ANSI_C_EXTRA */
3582}
3583
3584
3585static void wpa_cli_cleanup(void)
3586{
3587 wpa_cli_close_connection();
3588 if (pid_file)
3589 os_daemonize_terminate(pid_file);
3590
3591 os_program_deinit();
3592}
3593
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003594
3595static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003596{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003597 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003598}
3599
3600
3601static char * wpa_cli_get_default_ifname(void)
3602{
3603 char *ifname = NULL;
3604
3605#ifdef CONFIG_CTRL_IFACE_UNIX
3606 struct dirent *dent;
3607 DIR *dir = opendir(ctrl_iface_dir);
3608 if (!dir) {
3609#ifdef ANDROID
3610 char ifprop[PROPERTY_VALUE_MAX];
3611 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3612 ifname = os_strdup(ifprop);
3613 printf("Using interface '%s'\n", ifname);
3614 return ifname;
3615 }
3616#endif /* ANDROID */
3617 return NULL;
3618 }
3619 while ((dent = readdir(dir))) {
3620#ifdef _DIRENT_HAVE_D_TYPE
3621 /*
3622 * Skip the file if it is not a socket. Also accept
3623 * DT_UNKNOWN (0) in case the C library or underlying
3624 * file system does not support d_type.
3625 */
3626 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3627 continue;
3628#endif /* _DIRENT_HAVE_D_TYPE */
3629 if (os_strcmp(dent->d_name, ".") == 0 ||
3630 os_strcmp(dent->d_name, "..") == 0)
3631 continue;
3632 printf("Selected interface '%s'\n", dent->d_name);
3633 ifname = os_strdup(dent->d_name);
3634 break;
3635 }
3636 closedir(dir);
3637#endif /* CONFIG_CTRL_IFACE_UNIX */
3638
3639#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003640 char buf[4096], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003641 size_t len;
3642 struct wpa_ctrl *ctrl;
3643 int ret;
3644
3645 ctrl = wpa_ctrl_open(NULL);
3646 if (ctrl == NULL)
3647 return NULL;
3648
3649 len = sizeof(buf) - 1;
3650 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3651 if (ret >= 0) {
3652 buf[len] = '\0';
3653 pos = os_strchr(buf, '\n');
3654 if (pos)
3655 *pos = '\0';
3656 ifname = os_strdup(buf);
3657 }
3658 wpa_ctrl_close(ctrl);
3659#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3660
3661 return ifname;
3662}
3663
3664
3665int main(int argc, char *argv[])
3666{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003667 int c;
3668 int daemonize = 0;
3669 int ret = 0;
3670 const char *global = NULL;
3671
3672 if (os_program_init())
3673 return -1;
3674
3675 for (;;) {
3676 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3677 if (c < 0)
3678 break;
3679 switch (c) {
3680 case 'a':
3681 action_file = optarg;
3682 break;
3683 case 'B':
3684 daemonize = 1;
3685 break;
3686 case 'g':
3687 global = optarg;
3688 break;
3689 case 'G':
3690 ping_interval = atoi(optarg);
3691 break;
3692 case 'h':
3693 usage();
3694 return 0;
3695 case 'v':
3696 printf("%s\n", wpa_cli_version);
3697 return 0;
3698 case 'i':
3699 os_free(ctrl_ifname);
3700 ctrl_ifname = os_strdup(optarg);
3701 break;
3702 case 'p':
3703 ctrl_iface_dir = optarg;
3704 break;
3705 case 'P':
3706 pid_file = optarg;
3707 break;
3708 default:
3709 usage();
3710 return -1;
3711 }
3712 }
3713
3714 interactive = (argc == optind) && (action_file == NULL);
3715
3716 if (interactive)
3717 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3718
3719 if (eloop_init())
3720 return -1;
3721
3722 if (global) {
3723#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3724 ctrl_conn = wpa_ctrl_open(NULL);
3725#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3726 ctrl_conn = wpa_ctrl_open(global);
3727#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3728 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003729 fprintf(stderr, "Failed to connect to wpa_supplicant "
3730 "global interface: %s error: %s\n",
3731 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003732 return -1;
3733 }
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003734
3735 if (interactive) {
Dmitry Shmidtf7e0a992013-05-23 11:03:10 -07003736 update_ifnames(ctrl_conn);
Dmitry Shmidtb6e9aaf2013-05-20 14:49:44 -07003737 mon_conn = wpa_ctrl_open(global);
3738 if (mon_conn) {
3739 if (wpa_ctrl_attach(mon_conn) == 0) {
3740 wpa_cli_attached = 1;
3741 eloop_register_read_sock(
3742 wpa_ctrl_get_fd(mon_conn),
3743 wpa_cli_mon_receive,
3744 NULL, NULL);
3745 } else {
3746 printf("Failed to open monitor "
3747 "connection through global "
3748 "control interface\n");
3749 }
3750 }
3751 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003752 }
3753
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003754 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003755
3756 if (ctrl_ifname == NULL)
3757 ctrl_ifname = wpa_cli_get_default_ifname();
3758
3759 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003760 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003761 } else {
3762 if (!global &&
3763 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003764 fprintf(stderr, "Failed to connect to non-global "
3765 "ctrl_ifname: %s error: %s\n",
3766 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003767 return -1;
3768 }
3769
3770 if (action_file) {
3771 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3772 wpa_cli_attached = 1;
3773 } else {
3774 printf("Warning: Failed to attach to "
3775 "wpa_supplicant.\n");
3776 return -1;
3777 }
3778 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003779
3780 if (daemonize && os_daemonize(pid_file))
3781 return -1;
3782
3783 if (action_file)
3784 wpa_cli_action(ctrl_conn);
3785 else
3786 ret = wpa_request(ctrl_conn, argc - optind,
3787 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003788 }
3789
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003790 os_free(ctrl_ifname);
3791 eloop_destroy();
3792 wpa_cli_cleanup();
3793
3794 return ret;
3795}
3796
3797#else /* CONFIG_CTRL_IFACE */
3798int main(int argc, char *argv[])
3799{
3800 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3801 return -1;
3802}
3803#endif /* CONFIG_CTRL_IFACE */