blob: 204d13e1f4df8804f2dbfdb6ef4813ec2ecfe6b3 [file] [log] [blame]
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
Dmitry Shmidt04949592012-07-19 12:16:46 -07003 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07004 *
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08005 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07007 */
8
9#include "includes.h"
10
11#ifdef CONFIG_CTRL_IFACE
12
13#ifdef CONFIG_CTRL_IFACE_UNIX
14#include <dirent.h>
15#endif /* CONFIG_CTRL_IFACE_UNIX */
16
17#include "common/wpa_ctrl.h"
18#include "utils/common.h"
19#include "utils/eloop.h"
20#include "utils/edit.h"
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080021#include "utils/list.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070022#include "common/version.h"
Dmitry Shmidt04949592012-07-19 12:16:46 -070023#include "common/ieee802_11_defs.h"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070024#ifdef ANDROID
25#include <cutils/properties.h>
26#endif /* ANDROID */
27
28
29static const char *wpa_cli_version =
30"wpa_cli v" VERSION_STR "\n"
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -080031"Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> and contributors";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070032
33
34static const char *wpa_cli_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080035"This software may be distributed under the terms of the BSD license.\n"
36"See README for more details.\n";
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070037
38static const char *wpa_cli_full_license =
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -080039"This software may be distributed under the terms of the BSD license.\n"
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070040"\n"
41"Redistribution and use in source and binary forms, with or without\n"
42"modification, are permitted provided that the following conditions are\n"
43"met:\n"
44"\n"
45"1. Redistributions of source code must retain the above copyright\n"
46" notice, this list of conditions and the following disclaimer.\n"
47"\n"
48"2. Redistributions in binary form must reproduce the above copyright\n"
49" notice, this list of conditions and the following disclaimer in the\n"
50" documentation and/or other materials provided with the distribution.\n"
51"\n"
52"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
53" names of its contributors may be used to endorse or promote products\n"
54" derived from this software without specific prior written permission.\n"
55"\n"
56"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
57"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
58"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
59"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
60"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
61"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
62"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
63"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
64"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
65"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
66"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
67"\n";
68
69static struct wpa_ctrl *ctrl_conn;
70static struct wpa_ctrl *mon_conn;
71static int wpa_cli_quit = 0;
72static int wpa_cli_attached = 0;
73static int wpa_cli_connected = 0;
74static int wpa_cli_last_id = 0;
75#ifndef CONFIG_CTRL_IFACE_DIR
76#define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant"
77#endif /* CONFIG_CTRL_IFACE_DIR */
78static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79static char *ctrl_ifname = NULL;
80static const char *pid_file = NULL;
81static const char *action_file = NULL;
82static int ping_interval = 5;
83static int interactive = 0;
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -070084#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
85static char* redirect_interface = NULL;
86#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070087
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -080088struct cli_txt_entry {
89 struct dl_list list;
90 char *txt;
91};
92
93static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
94static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
95static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
96
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070097
Dmitry Shmidt61d9df32012-08-29 16:22:06 -070098static void print_help(const char *cmd);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -070099static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700100static void wpa_cli_close_connection(void);
101static char * wpa_cli_get_default_ifname(void);
102static char ** wpa_list_cmd_list(void);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700103
104
105static void usage(void)
106{
107 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
108 "[-a<action file>] \\\n"
109 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
110 "[command..]\n"
111 " -h = help (show this usage text)\n"
112 " -v = shown version information\n"
113 " -a = run in daemon mode executing the action file based on "
114 "events from\n"
115 " wpa_supplicant\n"
116 " -B = run a daemon in the background\n"
117 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
118 " default interface: first interface found in socket path\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700119 print_help(NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700120}
121
122
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800123static void cli_txt_list_free(struct cli_txt_entry *e)
124{
125 dl_list_del(&e->list);
126 os_free(e->txt);
127 os_free(e);
128}
129
130
131static void cli_txt_list_flush(struct dl_list *list)
132{
133 struct cli_txt_entry *e;
134 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
135 cli_txt_list_free(e);
136}
137
138
139static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
140 const char *txt)
141{
142 struct cli_txt_entry *e;
143 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
144 if (os_strcmp(e->txt, txt) == 0)
145 return e;
146 }
147 return NULL;
148}
149
150
151static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
152{
153 struct cli_txt_entry *e;
154 e = cli_txt_list_get(txt_list, txt);
155 if (e)
156 cli_txt_list_free(e);
157}
158
159
160static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
161{
162 u8 addr[ETH_ALEN];
163 char buf[18];
164 if (hwaddr_aton(txt, addr) < 0)
165 return;
166 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
167 cli_txt_list_del(txt_list, buf);
168}
169
170
171#ifdef CONFIG_P2P
172static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
173{
174 const char *end;
175 char *buf;
176 end = os_strchr(txt, ' ');
177 if (end == NULL)
178 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700179 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800180 if (buf == NULL)
181 return;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800182 cli_txt_list_del(txt_list, buf);
183 os_free(buf);
184}
185#endif /* CONFIG_P2P */
186
187
188static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
189{
190 struct cli_txt_entry *e;
191 e = cli_txt_list_get(txt_list, txt);
192 if (e)
193 return 0;
194 e = os_zalloc(sizeof(*e));
195 if (e == NULL)
196 return -1;
197 e->txt = os_strdup(txt);
198 if (e->txt == NULL) {
199 os_free(e);
200 return -1;
201 }
202 dl_list_add(txt_list, &e->list);
203 return 0;
204}
205
206
207#ifdef CONFIG_P2P
208static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
209{
210 u8 addr[ETH_ALEN];
211 char buf[18];
212 if (hwaddr_aton(txt, addr) < 0)
213 return -1;
214 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
215 return cli_txt_list_add(txt_list, buf);
216}
217
218
219static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
220{
221 const char *end;
222 char *buf;
223 int ret;
224 end = os_strchr(txt, ' ');
225 if (end == NULL)
226 end = txt + os_strlen(txt);
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700227 buf = dup_binstr(txt, end - txt);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800228 if (buf == NULL)
229 return -1;
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800230 ret = cli_txt_list_add(txt_list, buf);
231 os_free(buf);
232 return ret;
233}
234#endif /* CONFIG_P2P */
235
236
237static char ** cli_txt_list_array(struct dl_list *txt_list)
238{
239 unsigned int i, count = dl_list_len(txt_list);
240 char **res;
241 struct cli_txt_entry *e;
242
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700243 res = os_calloc(count + 1, sizeof(char *));
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800244 if (res == NULL)
245 return NULL;
246
247 i = 0;
248 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
249 res[i] = os_strdup(e->txt);
250 if (res[i] == NULL)
251 break;
252 i++;
253 }
254
255 return res;
256}
257
258
259static int get_cmd_arg_num(const char *str, int pos)
260{
261 int arg = 0, i;
262
263 for (i = 0; i <= pos; i++) {
264 if (str[i] != ' ') {
265 arg++;
266 while (i <= pos && str[i] != ' ')
267 i++;
268 }
269 }
270
271 if (arg > 0)
272 arg--;
273 return arg;
274}
275
276
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700277static int str_starts(const char *src, const char *match)
278{
279 return os_strncmp(src, match, os_strlen(match)) == 0;
280}
281
282
283static int wpa_cli_show_event(const char *event)
284{
285 const char *start;
286
287 start = os_strchr(event, '>');
288 if (start == NULL)
289 return 1;
290
291 start++;
292 /*
293 * Skip BSS added/removed events since they can be relatively frequent
294 * and are likely of not much use for an interactive user.
295 */
296 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
297 str_starts(start, WPA_EVENT_BSS_REMOVED))
298 return 0;
299
300 return 1;
301}
302
303
304static int wpa_cli_open_connection(const char *ifname, int attach)
305{
306#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
307 ctrl_conn = wpa_ctrl_open(ifname);
308 if (ctrl_conn == NULL)
309 return -1;
310
311 if (attach && interactive)
312 mon_conn = wpa_ctrl_open(ifname);
313 else
314 mon_conn = NULL;
315#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
316 char *cfile = NULL;
317 int flen, res;
318
319 if (ifname == NULL)
320 return -1;
321
322#ifdef ANDROID
323 if (access(ctrl_iface_dir, F_OK) < 0) {
324 cfile = os_strdup(ifname);
325 if (cfile == NULL)
326 return -1;
327 }
328#endif /* ANDROID */
329
330 if (cfile == NULL) {
331 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
332 cfile = os_malloc(flen);
333 if (cfile == NULL)
334 return -1;
335 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
336 ifname);
337 if (res < 0 || res >= flen) {
338 os_free(cfile);
339 return -1;
340 }
341 }
342
343 ctrl_conn = wpa_ctrl_open(cfile);
344 if (ctrl_conn == NULL) {
345 os_free(cfile);
346 return -1;
347 }
348
349 if (attach && interactive)
350 mon_conn = wpa_ctrl_open(cfile);
351 else
352 mon_conn = NULL;
353 os_free(cfile);
354#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
355
356 if (mon_conn) {
357 if (wpa_ctrl_attach(mon_conn) == 0) {
358 wpa_cli_attached = 1;
359 if (interactive)
360 eloop_register_read_sock(
361 wpa_ctrl_get_fd(mon_conn),
362 wpa_cli_mon_receive, NULL, NULL);
363 } else {
364 printf("Warning: Failed to attach to "
365 "wpa_supplicant.\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700366 wpa_cli_close_connection();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700367 return -1;
368 }
369 }
370
371 return 0;
372}
373
374
375static void wpa_cli_close_connection(void)
376{
377 if (ctrl_conn == NULL)
378 return;
379
380 if (wpa_cli_attached) {
381 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
382 wpa_cli_attached = 0;
383 }
384 wpa_ctrl_close(ctrl_conn);
385 ctrl_conn = NULL;
386 if (mon_conn) {
387 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
388 wpa_ctrl_close(mon_conn);
389 mon_conn = NULL;
390 }
391}
392
393
394static void wpa_cli_msg_cb(char *msg, size_t len)
395{
396 printf("%s\n", msg);
397}
398
399
400static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
401{
Dmitry Shmidtc97d8bf2011-08-30 11:10:13 -0700402 char buf[4096];
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -0700403#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
404 char _cmd[256];
405#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700406 size_t len;
407 int ret;
408
409 if (ctrl_conn == NULL) {
410 printf("Not connected to wpa_supplicant - command dropped.\n");
411 return -1;
412 }
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -0700413#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
414 if (redirect_interface) {
415 char *arg;
416 arg = os_strchr(cmd, ' ');
417 if (arg) {
418 *arg++ = '\0';
419 ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s %s", cmd, redirect_interface, arg);
420 }
421 else {
422 ret = os_snprintf(_cmd, sizeof(_cmd), "%s %s", cmd, redirect_interface);
423 }
424 cmd = _cmd;
425 os_free(redirect_interface);
426 redirect_interface = NULL;
427 }
428#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700429 len = sizeof(buf) - 1;
430 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
431 wpa_cli_msg_cb);
432 if (ret == -2) {
433 printf("'%s' command timed out.\n", cmd);
434 return -2;
435 } else if (ret < 0) {
436 printf("'%s' command failed.\n", cmd);
437 return -1;
438 }
439 if (print) {
440 buf[len] = '\0';
441 printf("%s", buf);
442 if (interactive && len > 0 && buf[len - 1] != '\n')
443 printf("\n");
444 }
445 return 0;
446}
447
448
449static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
450{
451 return _wpa_ctrl_command(ctrl, cmd, 1);
452}
453
454
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700455static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
456 char *argv[])
457{
458 int i, res;
459 char *pos, *end;
460
461 pos = buf;
462 end = buf + buflen;
463
464 res = os_snprintf(pos, end - pos, "%s", cmd);
465 if (res < 0 || res >= end - pos)
466 goto fail;
467 pos += res;
468
469 for (i = 0; i < argc; i++) {
470 res = os_snprintf(pos, end - pos, " %s", argv[i]);
471 if (res < 0 || res >= end - pos)
472 goto fail;
473 pos += res;
474 }
475
476 buf[buflen - 1] = '\0';
477 return 0;
478
479fail:
480 printf("Too long command\n");
481 return -1;
482}
483
484
485static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
486 int argc, char *argv[])
487{
Dmitry Shmidt4b060592013-04-29 16:42:49 -0700488 char buf[4096];
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700489 if (argc < min_args) {
490 printf("Invalid %s command - at least %d argument%s "
491 "required.\n", cmd, min_args,
492 min_args > 1 ? "s are" : " is");
493 return -1;
494 }
495 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
496 return -1;
497 return wpa_ctrl_command(ctrl, buf);
498}
499
500
501static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
502{
503 return wpa_ctrl_command(ctrl, "IFNAME");
504}
505
506
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700507static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
508{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800509 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
510 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
511 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
512 return wpa_ctrl_command(ctrl, "STATUS-WPS");
513 return wpa_ctrl_command(ctrl, "STATUS");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700514}
515
516
517static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
518{
519 return wpa_ctrl_command(ctrl, "PING");
520}
521
522
523static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
524{
525 return wpa_ctrl_command(ctrl, "RELOG");
526}
527
528
529static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
530{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700531 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700532}
533
534
535static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
536{
537 return wpa_ctrl_command(ctrl, "MIB");
538}
539
540
541static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
542{
543 return wpa_ctrl_command(ctrl, "PMKSA");
544}
545
546
547static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
548{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700549 print_help(argc > 0 ? argv[0] : NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700550 return 0;
551}
552
553
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700554static char ** wpa_cli_complete_help(const char *str, int pos)
555{
556 int arg = get_cmd_arg_num(str, pos);
557 char **res = NULL;
558
559 switch (arg) {
560 case 1:
561 res = wpa_list_cmd_list();
562 break;
563 }
564
565 return res;
566}
567
568
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700569static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
570{
571 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
572 return 0;
573}
574
575
576static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
577{
578 wpa_cli_quit = 1;
579 if (interactive)
580 eloop_terminate();
581 return 0;
582}
583
584
585static void wpa_cli_show_variables(void)
586{
587 printf("set variables:\n"
588 " EAPOL::heldPeriod (EAPOL state machine held period, "
589 "in seconds)\n"
590 " EAPOL::authPeriod (EAPOL state machine authentication "
591 "period, in seconds)\n"
592 " EAPOL::startPeriod (EAPOL state machine start period, in "
593 "seconds)\n"
594 " EAPOL::maxStart (EAPOL state machine maximum start "
595 "attempts)\n");
596 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
597 "seconds)\n"
598 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
599 " threshold\n\tpercentage)\n"
600 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
601 "security\n\tassociation in seconds)\n");
602}
603
604
605static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
606{
607 char cmd[256];
608 int res;
609
610 if (argc == 0) {
611 wpa_cli_show_variables();
612 return 0;
613 }
614
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800615 if (argc != 1 && argc != 2) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700616 printf("Invalid SET command: needs two arguments (variable "
617 "name and value)\n");
618 return -1;
619 }
620
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -0800621 if (argc == 1)
622 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
623 else
624 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
625 argv[0], argv[1]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700626 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
627 printf("Too long SET command.\n");
628 return -1;
629 }
630 return wpa_ctrl_command(ctrl, cmd);
631}
632
633
634static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
635{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700636 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700637}
638
639
640static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
641{
642 return wpa_ctrl_command(ctrl, "LOGOFF");
643}
644
645
646static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
647{
648 return wpa_ctrl_command(ctrl, "LOGON");
649}
650
651
652static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
653 char *argv[])
654{
655 return wpa_ctrl_command(ctrl, "REASSOCIATE");
656}
657
658
659static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
660 char *argv[])
661{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700662 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700663}
664
665
666static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
667{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700668 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700669}
670
671
672static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
673 char *argv[])
674{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700675 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700676}
677
678
679static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
680 char *argv[])
681{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700682 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700683}
684
685
686static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
687 char *argv[])
688{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700689 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700690}
691
692
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -0700693static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
694{
695 char cmd[256];
696 int res;
697
698 if (argc < 1)
699 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
700 else
701 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
702 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
703 printf("Too long BSS_FLUSH command.\n");
704 return -1;
705 }
706 return wpa_ctrl_command(ctrl, cmd);
707}
708
709
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700710static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
711 char *argv[])
712{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700713 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700714}
715
716
717static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
718{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700719 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700720}
721
722
723static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
724{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700725 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700726}
727
728
729static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
730{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700731 if (argc == 0) {
732 printf("Invalid WPS_PIN command: need one or two arguments:\n"
733 "- BSSID: use 'any' to select any\n"
734 "- PIN: optional, used only with devices that have no "
735 "display\n");
736 return -1;
737 }
738
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700739 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700740}
741
742
743static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
744 char *argv[])
745{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700746 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700747}
748
749
750static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
751 char *argv[])
752{
753 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
754}
755
756
Dmitry Shmidt04949592012-07-19 12:16:46 -0700757#ifdef CONFIG_WPS_NFC
758
759static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
760{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700761 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700762}
763
764
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800765static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
766 char *argv[])
767{
768 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
769}
770
771
Dmitry Shmidt04949592012-07-19 12:16:46 -0700772static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
773 char *argv[])
774{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700775 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -0700776}
777
778
779static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
780 char *argv[])
781{
782 int ret;
783 char *buf;
784 size_t buflen;
785
786 if (argc != 1) {
787 printf("Invalid 'wps_nfc_tag_read' command - one argument "
788 "is required.\n");
789 return -1;
790 }
791
792 buflen = 18 + os_strlen(argv[0]);
793 buf = os_malloc(buflen);
794 if (buf == NULL)
795 return -1;
796 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
797
798 ret = wpa_ctrl_command(ctrl, buf);
799 os_free(buf);
800
801 return ret;
802}
803
Dmitry Shmidtd5e49232012-12-03 15:08:10 -0800804
805static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
806 char *argv[])
807{
808 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
809}
810
811
812static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
813 char *argv[])
814{
815 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
816}
817
818
819static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
820 char *argv[])
821{
822 int ret;
823 char *buf;
824 size_t buflen;
825
826 if (argc != 1) {
827 printf("Invalid 'nfc_rx_handover_req' command - one argument "
828 "is required.\n");
829 return -1;
830 }
831
832 buflen = 21 + os_strlen(argv[0]);
833 buf = os_malloc(buflen);
834 if (buf == NULL)
835 return -1;
836 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
837
838 ret = wpa_ctrl_command(ctrl, buf);
839 os_free(buf);
840
841 return ret;
842}
843
844
845static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
846 char *argv[])
847{
848 int ret;
849 char *buf;
850 size_t buflen;
851
852 if (argc != 1) {
853 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
854 "is required.\n");
855 return -1;
856 }
857
858 buflen = 21 + os_strlen(argv[0]);
859 buf = os_malloc(buflen);
860 if (buf == NULL)
861 return -1;
862 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
863
864 ret = wpa_ctrl_command(ctrl, buf);
865 os_free(buf);
866
867 return ret;
868}
869
Dmitry Shmidtf8623282013-02-20 14:34:59 -0800870
871static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
872 char *argv[])
873{
874 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
875}
876
Dmitry Shmidt04949592012-07-19 12:16:46 -0700877#endif /* CONFIG_WPS_NFC */
878
879
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700880static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
881{
882 char cmd[256];
883 int res;
884
885 if (argc == 2)
886 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
887 argv[0], argv[1]);
888 else if (argc == 5 || argc == 6) {
889 char ssid_hex[2 * 32 + 1];
890 char key_hex[2 * 64 + 1];
891 int i;
892
893 ssid_hex[0] = '\0';
894 for (i = 0; i < 32; i++) {
895 if (argv[2][i] == '\0')
896 break;
897 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
898 }
899
900 key_hex[0] = '\0';
901 if (argc == 6) {
902 for (i = 0; i < 64; i++) {
903 if (argv[5][i] == '\0')
904 break;
905 os_snprintf(&key_hex[i * 2], 3, "%02x",
906 argv[5][i]);
907 }
908 }
909
910 res = os_snprintf(cmd, sizeof(cmd),
911 "WPS_REG %s %s %s %s %s %s",
912 argv[0], argv[1], ssid_hex, argv[3], argv[4],
913 key_hex);
914 } else {
915 printf("Invalid WPS_REG command: need two arguments:\n"
916 "- BSSID of the target AP\n"
917 "- AP PIN\n");
918 printf("Alternatively, six arguments can be used to "
919 "reconfigure the AP:\n"
920 "- BSSID of the target AP\n"
921 "- AP PIN\n"
922 "- new SSID\n"
923 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
924 "- new encr (NONE, WEP, TKIP, CCMP)\n"
925 "- new key\n");
926 return -1;
927 }
928
929 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
930 printf("Too long WPS_REG command.\n");
931 return -1;
932 }
933 return wpa_ctrl_command(ctrl, cmd);
934}
935
936
937static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
938 char *argv[])
939{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700940 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700941}
942
943
944static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
945 char *argv[])
946{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700947 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700948}
949
950
951static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
952 char *argv[])
953{
954 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
955
956}
957
958
959static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
960 char *argv[])
961{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700962 if (argc < 2) {
963 printf("Invalid WPS_ER_PIN command: need at least two "
964 "arguments:\n"
965 "- UUID: use 'any' to select any\n"
966 "- PIN: Enrollee PIN\n"
967 "optional: - Enrollee MAC address\n");
968 return -1;
969 }
970
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700971 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700972}
973
974
975static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
976 char *argv[])
977{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700978 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700979}
980
981
982static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
983 char *argv[])
984{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700985 if (argc != 2) {
986 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
987 "- UUID: specify which AP to use\n"
988 "- PIN: AP PIN\n");
989 return -1;
990 }
991
Dmitry Shmidt61d9df32012-08-29 16:22:06 -0700992 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700993}
994
995
996static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
997 char *argv[])
998{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -0700999 if (argc != 2) {
1000 printf("Invalid WPS_ER_SET_CONFIG command: need two "
1001 "arguments:\n"
1002 "- UUID: specify which AP to use\n"
1003 "- Network configuration id\n");
1004 return -1;
1005 }
1006
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001007 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001008}
1009
1010
1011static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
1012 char *argv[])
1013{
1014 char cmd[256];
1015 int res;
1016
1017 if (argc == 5 || argc == 6) {
1018 char ssid_hex[2 * 32 + 1];
1019 char key_hex[2 * 64 + 1];
1020 int i;
1021
1022 ssid_hex[0] = '\0';
1023 for (i = 0; i < 32; i++) {
1024 if (argv[2][i] == '\0')
1025 break;
1026 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1027 }
1028
1029 key_hex[0] = '\0';
1030 if (argc == 6) {
1031 for (i = 0; i < 64; i++) {
1032 if (argv[5][i] == '\0')
1033 break;
1034 os_snprintf(&key_hex[i * 2], 3, "%02x",
1035 argv[5][i]);
1036 }
1037 }
1038
1039 res = os_snprintf(cmd, sizeof(cmd),
1040 "WPS_ER_CONFIG %s %s %s %s %s %s",
1041 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1042 key_hex);
1043 } else {
1044 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1045 "- AP UUID\n"
1046 "- AP PIN\n"
1047 "- new SSID\n"
1048 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1049 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1050 "- new key\n");
1051 return -1;
1052 }
1053
1054 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1055 printf("Too long WPS_ER_CONFIG command.\n");
1056 return -1;
1057 }
1058 return wpa_ctrl_command(ctrl, cmd);
1059}
1060
1061
Dmitry Shmidt04949592012-07-19 12:16:46 -07001062#ifdef CONFIG_WPS_NFC
1063static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1064 char *argv[])
1065{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001066 if (argc != 2) {
1067 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1068 "arguments:\n"
1069 "- WPS/NDEF: token format\n"
1070 "- UUID: specify which AP to use\n");
1071 return -1;
1072 }
1073
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001074 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001075}
1076#endif /* CONFIG_WPS_NFC */
1077
1078
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001079static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1080{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001081 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001082}
1083
1084
1085static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1086{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001087 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001088}
1089
1090
1091static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1092{
1093 char cmd[256], *pos, *end;
1094 int i, ret;
1095
1096 if (argc < 2) {
1097 printf("Invalid IDENTITY command: needs two arguments "
1098 "(network id and identity)\n");
1099 return -1;
1100 }
1101
1102 end = cmd + sizeof(cmd);
1103 pos = cmd;
1104 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1105 argv[0], argv[1]);
1106 if (ret < 0 || ret >= end - pos) {
1107 printf("Too long IDENTITY command.\n");
1108 return -1;
1109 }
1110 pos += ret;
1111 for (i = 2; i < argc; i++) {
1112 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1113 if (ret < 0 || ret >= end - pos) {
1114 printf("Too long IDENTITY command.\n");
1115 return -1;
1116 }
1117 pos += ret;
1118 }
1119
1120 return wpa_ctrl_command(ctrl, cmd);
1121}
1122
1123
1124static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1125{
1126 char cmd[256], *pos, *end;
1127 int i, ret;
1128
1129 if (argc < 2) {
1130 printf("Invalid PASSWORD command: needs two arguments "
1131 "(network id and password)\n");
1132 return -1;
1133 }
1134
1135 end = cmd + sizeof(cmd);
1136 pos = cmd;
1137 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1138 argv[0], argv[1]);
1139 if (ret < 0 || ret >= end - pos) {
1140 printf("Too long PASSWORD command.\n");
1141 return -1;
1142 }
1143 pos += ret;
1144 for (i = 2; i < argc; i++) {
1145 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1146 if (ret < 0 || ret >= end - pos) {
1147 printf("Too long PASSWORD command.\n");
1148 return -1;
1149 }
1150 pos += ret;
1151 }
1152
1153 return wpa_ctrl_command(ctrl, cmd);
1154}
1155
1156
1157static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1158 char *argv[])
1159{
1160 char cmd[256], *pos, *end;
1161 int i, ret;
1162
1163 if (argc < 2) {
1164 printf("Invalid NEW_PASSWORD command: needs two arguments "
1165 "(network id and password)\n");
1166 return -1;
1167 }
1168
1169 end = cmd + sizeof(cmd);
1170 pos = cmd;
1171 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1172 argv[0], argv[1]);
1173 if (ret < 0 || ret >= end - pos) {
1174 printf("Too long NEW_PASSWORD command.\n");
1175 return -1;
1176 }
1177 pos += ret;
1178 for (i = 2; i < argc; i++) {
1179 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1180 if (ret < 0 || ret >= end - pos) {
1181 printf("Too long NEW_PASSWORD command.\n");
1182 return -1;
1183 }
1184 pos += ret;
1185 }
1186
1187 return wpa_ctrl_command(ctrl, cmd);
1188}
1189
1190
1191static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1192{
1193 char cmd[256], *pos, *end;
1194 int i, ret;
1195
1196 if (argc < 2) {
1197 printf("Invalid PIN command: needs two arguments "
1198 "(network id and pin)\n");
1199 return -1;
1200 }
1201
1202 end = cmd + sizeof(cmd);
1203 pos = cmd;
1204 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1205 argv[0], argv[1]);
1206 if (ret < 0 || ret >= end - pos) {
1207 printf("Too long PIN command.\n");
1208 return -1;
1209 }
1210 pos += ret;
1211 for (i = 2; i < argc; i++) {
1212 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1213 if (ret < 0 || ret >= end - pos) {
1214 printf("Too long PIN command.\n");
1215 return -1;
1216 }
1217 pos += ret;
1218 }
1219 return wpa_ctrl_command(ctrl, cmd);
1220}
1221
1222
1223static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1224{
1225 char cmd[256], *pos, *end;
1226 int i, ret;
1227
1228 if (argc < 2) {
1229 printf("Invalid OTP command: needs two arguments (network "
1230 "id and password)\n");
1231 return -1;
1232 }
1233
1234 end = cmd + sizeof(cmd);
1235 pos = cmd;
1236 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1237 argv[0], argv[1]);
1238 if (ret < 0 || ret >= end - pos) {
1239 printf("Too long OTP command.\n");
1240 return -1;
1241 }
1242 pos += ret;
1243 for (i = 2; i < argc; i++) {
1244 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1245 if (ret < 0 || ret >= end - pos) {
1246 printf("Too long OTP command.\n");
1247 return -1;
1248 }
1249 pos += ret;
1250 }
1251
1252 return wpa_ctrl_command(ctrl, cmd);
1253}
1254
1255
1256static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1257 char *argv[])
1258{
1259 char cmd[256], *pos, *end;
1260 int i, ret;
1261
1262 if (argc < 2) {
1263 printf("Invalid PASSPHRASE command: needs two arguments "
1264 "(network id and passphrase)\n");
1265 return -1;
1266 }
1267
1268 end = cmd + sizeof(cmd);
1269 pos = cmd;
1270 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1271 argv[0], argv[1]);
1272 if (ret < 0 || ret >= end - pos) {
1273 printf("Too long PASSPHRASE command.\n");
1274 return -1;
1275 }
1276 pos += ret;
1277 for (i = 2; i < argc; i++) {
1278 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1279 if (ret < 0 || ret >= end - pos) {
1280 printf("Too long PASSPHRASE command.\n");
1281 return -1;
1282 }
1283 pos += ret;
1284 }
1285
1286 return wpa_ctrl_command(ctrl, cmd);
1287}
1288
1289
1290static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1291{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001292 if (argc < 2) {
1293 printf("Invalid BSSID command: needs two arguments (network "
1294 "id and BSSID)\n");
1295 return -1;
1296 }
1297
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001298 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001299}
1300
1301
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001302static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1303{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001304 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001305}
1306
1307
1308static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1309{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001310 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
Dmitry Shmidt696359e2011-03-16 15:04:31 -07001311}
1312
1313
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001314static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1315 char *argv[])
1316{
1317 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1318}
1319
1320
1321static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1322 char *argv[])
1323{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001324 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001325}
1326
1327
1328static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1329 char *argv[])
1330{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001331 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001332}
1333
1334
1335static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1336 char *argv[])
1337{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001338 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001339}
1340
1341
1342static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1343 char *argv[])
1344{
1345 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1346}
1347
1348
1349static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1350 char *argv[])
1351{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001352 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001353}
1354
1355
1356static void wpa_cli_show_network_variables(void)
1357{
1358 printf("set_network variables:\n"
1359 " ssid (network name, SSID)\n"
1360 " psk (WPA passphrase or pre-shared key)\n"
1361 " key_mgmt (key management protocol)\n"
1362 " identity (EAP identity)\n"
1363 " password (EAP password)\n"
1364 " ...\n"
1365 "\n"
1366 "Note: Values are entered in the same format as the "
1367 "configuration file is using,\n"
1368 "i.e., strings values need to be inside double quotation "
1369 "marks.\n"
1370 "For example: set_network 1 ssid \"network name\"\n"
1371 "\n"
1372 "Please see wpa_supplicant.conf documentation for full list "
1373 "of\navailable variables.\n");
1374}
1375
1376
1377static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1378 char *argv[])
1379{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001380 if (argc == 0) {
1381 wpa_cli_show_network_variables();
1382 return 0;
1383 }
1384
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08001385 if (argc < 3) {
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001386 printf("Invalid SET_NETWORK command: needs three arguments\n"
1387 "(network id, variable name, and value)\n");
1388 return -1;
1389 }
1390
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001391 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001392}
1393
1394
1395static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1396 char *argv[])
1397{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001398 if (argc == 0) {
1399 wpa_cli_show_network_variables();
1400 return 0;
1401 }
1402
1403 if (argc != 2) {
1404 printf("Invalid GET_NETWORK command: needs two arguments\n"
1405 "(network id and variable name)\n");
1406 return -1;
1407 }
1408
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001409 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001410}
1411
1412
Dmitry Shmidt04949592012-07-19 12:16:46 -07001413static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1414 char *argv[])
1415{
1416 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1417}
1418
1419
1420static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1421{
1422 return wpa_ctrl_command(ctrl, "ADD_CRED");
1423}
1424
1425
1426static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1427 char *argv[])
1428{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001429 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001430}
1431
1432
1433static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1434{
Dmitry Shmidt04949592012-07-19 12:16:46 -07001435 if (argc != 3) {
1436 printf("Invalid SET_CRED command: needs three arguments\n"
1437 "(cred id, variable name, and value)\n");
1438 return -1;
1439 }
1440
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001441 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001442}
1443
1444
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001445static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1446 char *argv[])
1447{
1448 return wpa_ctrl_command(ctrl, "DISCONNECT");
1449}
1450
1451
1452static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1453 char *argv[])
1454{
1455 return wpa_ctrl_command(ctrl, "RECONNECT");
1456}
1457
1458
1459static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1460 char *argv[])
1461{
1462 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1463}
1464
1465
1466static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1467{
Dmitry Shmidt4b9d52f2013-02-05 17:44:43 -08001468 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001469}
1470
1471
1472static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1473 char *argv[])
1474{
1475 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1476}
1477
1478
1479static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1480{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001481 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001482}
1483
1484
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001485static char ** wpa_cli_complete_bss(const char *str, int pos)
1486{
1487 int arg = get_cmd_arg_num(str, pos);
1488 char **res = NULL;
1489
1490 switch (arg) {
1491 case 1:
1492 res = cli_txt_list_array(&bsses);
1493 break;
1494 }
1495
1496 return res;
1497}
1498
1499
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001500static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1501 char *argv[])
1502{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001503 if (argc < 1 || argc > 2) {
1504 printf("Invalid GET_CAPABILITY command: need either one or "
1505 "two arguments\n");
1506 return -1;
1507 }
1508
1509 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1510 printf("Invalid GET_CAPABILITY command: second argument, "
1511 "if any, must be 'strict'\n");
1512 return -1;
1513 }
1514
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001515 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001516}
1517
1518
1519static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1520{
1521 printf("Available interfaces:\n");
1522 return wpa_ctrl_command(ctrl, "INTERFACES");
1523}
1524
1525
1526static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1527{
1528 if (argc < 1) {
1529 wpa_cli_list_interfaces(ctrl);
1530 return 0;
1531 }
1532
1533 wpa_cli_close_connection();
1534 os_free(ctrl_ifname);
1535 ctrl_ifname = os_strdup(argv[0]);
1536
1537 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1538 printf("Connected to interface '%s.\n", ctrl_ifname);
1539 } else {
1540 printf("Could not connect to interface '%s' - re-trying\n",
1541 ctrl_ifname);
1542 }
1543 return 0;
1544}
1545
1546
1547static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1548 char *argv[])
1549{
1550 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1551}
1552
1553
1554static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1555 char *argv[])
1556{
1557 return wpa_ctrl_command(ctrl, "TERMINATE");
1558}
1559
1560
1561static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1562 char *argv[])
1563{
1564 char cmd[256];
1565 int res;
1566
1567 if (argc < 1) {
1568 printf("Invalid INTERFACE_ADD command: needs at least one "
1569 "argument (interface name)\n"
1570 "All arguments: ifname confname driver ctrl_interface "
1571 "driver_param bridge_name\n");
1572 return -1;
1573 }
1574
1575 /*
1576 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1577 * <driver_param>TAB<bridge_name>
1578 */
1579 res = os_snprintf(cmd, sizeof(cmd),
1580 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1581 argv[0],
1582 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1583 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1584 argc > 5 ? argv[5] : "");
1585 if (res < 0 || (size_t) res >= sizeof(cmd))
1586 return -1;
1587 cmd[sizeof(cmd) - 1] = '\0';
1588 return wpa_ctrl_command(ctrl, cmd);
1589}
1590
1591
1592static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1593 char *argv[])
1594{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001595 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001596}
1597
1598
1599static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1600 char *argv[])
1601{
1602 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1603}
1604
1605
1606#ifdef CONFIG_AP
1607static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1608{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001609 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001610}
1611
1612
1613static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1614 char *addr, size_t addr_len)
1615{
1616 char buf[4096], *pos;
1617 size_t len;
1618 int ret;
1619
1620 if (ctrl_conn == NULL) {
1621 printf("Not connected to hostapd - command dropped.\n");
1622 return -1;
1623 }
1624 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001625 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001626 wpa_cli_msg_cb);
1627 if (ret == -2) {
1628 printf("'%s' command timed out.\n", cmd);
1629 return -2;
1630 } else if (ret < 0) {
1631 printf("'%s' command failed.\n", cmd);
1632 return -1;
1633 }
1634
1635 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07001636 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001637 return -1;
1638 printf("%s", buf);
1639
1640 pos = buf;
1641 while (*pos != '\0' && *pos != '\n')
1642 pos++;
1643 *pos = '\0';
1644 os_strlcpy(addr, buf, addr_len);
1645 return 0;
1646}
1647
1648
1649static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1650{
1651 char addr[32], cmd[64];
1652
1653 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1654 return 0;
1655 do {
1656 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1657 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1658
1659 return -1;
1660}
Dmitry Shmidt04949592012-07-19 12:16:46 -07001661
1662
1663static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1664 char *argv[])
1665{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001666 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001667}
1668
1669
1670static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1671 char *argv[])
1672{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001673 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07001674}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001675#endif /* CONFIG_AP */
1676
1677
1678static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1679{
1680 return wpa_ctrl_command(ctrl, "SUSPEND");
1681}
1682
1683
1684static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1685{
1686 return wpa_ctrl_command(ctrl, "RESUME");
1687}
1688
1689
1690static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1691{
1692 return wpa_ctrl_command(ctrl, "DROP_SA");
1693}
1694
1695
1696static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1697{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001698 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001699}
1700
1701
1702#ifdef CONFIG_P2P
1703
1704static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1705{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001706 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1707}
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001708
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001709
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001710static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1711{
1712 char **res = NULL;
1713 int arg = get_cmd_arg_num(str, pos);
1714
1715 res = os_calloc(6, sizeof(char *));
1716 if (res == NULL)
1717 return NULL;
1718 res[0] = os_strdup("type=social");
1719 if (res[0] == NULL) {
1720 os_free(res);
1721 return NULL;
1722 }
1723 res[1] = os_strdup("type=progressive");
1724 if (res[1] == NULL)
1725 return res;
1726 res[2] = os_strdup("delay=");
1727 if (res[2] == NULL)
1728 return res;
1729 res[3] = os_strdup("dev_id=");
1730 if (res[3] == NULL)
1731 return res;
1732 if (arg == 1)
1733 res[4] = os_strdup("[timeout]");
1734
1735 return res;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001736}
1737
1738
1739static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1740 char *argv[])
1741{
1742 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1743}
1744
1745
1746static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1747 char *argv[])
1748{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001749 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001750}
1751
1752
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001753static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1754{
1755 int arg = get_cmd_arg_num(str, pos);
1756 char **res = NULL;
1757
1758 switch (arg) {
1759 case 1:
1760 res = cli_txt_list_array(&p2p_peers);
1761 break;
1762 }
1763
1764 return res;
1765}
1766
1767
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001768static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1769 char *argv[])
1770{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001771 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001772}
1773
1774
1775static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1776 char *argv[])
1777{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001778 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001779}
1780
1781
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001782static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1783{
1784 int arg = get_cmd_arg_num(str, pos);
1785 char **res = NULL;
1786
1787 switch (arg) {
1788 case 1:
1789 res = cli_txt_list_array(&p2p_groups);
1790 break;
1791 }
1792
1793 return res;
1794}
1795
1796
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001797static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1798 char *argv[])
1799{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001800 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001801}
1802
1803
1804static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1805 char *argv[])
1806{
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001807 if (argc != 2 && argc != 3) {
1808 printf("Invalid P2P_PROV_DISC command: needs at least "
1809 "two arguments, address and config method\n"
1810 "(display, keypad, or pbc) and an optional join\n");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001811 return -1;
1812 }
1813
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001814 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001815}
1816
1817
1818static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1819 char *argv[])
1820{
1821 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1822}
1823
1824
1825static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1826 char *argv[])
1827{
1828 char cmd[4096];
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001829
1830 if (argc != 2 && argc != 4) {
1831 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1832 "arguments (address and TLVs) or four arguments "
1833 "(address, \"upnp\", version, search target "
1834 "(SSDP ST:)\n");
1835 return -1;
1836 }
1837
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001838 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001839 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001840 return wpa_ctrl_command(ctrl, cmd);
1841}
1842
1843
1844static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1845 int argc, char *argv[])
1846{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001847 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001848}
1849
1850
1851static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1852 char *argv[])
1853{
1854 char cmd[4096];
1855 int res;
1856
1857 if (argc != 4) {
1858 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1859 "arguments (freq, address, dialog token, and TLVs)\n");
1860 return -1;
1861 }
1862
1863 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1864 argv[0], argv[1], argv[2], argv[3]);
1865 if (res < 0 || (size_t) res >= sizeof(cmd))
1866 return -1;
1867 cmd[sizeof(cmd) - 1] = '\0';
1868 return wpa_ctrl_command(ctrl, cmd);
1869}
1870
1871
1872static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1873 char *argv[])
1874{
1875 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1876}
1877
1878
1879static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1880 int argc, char *argv[])
1881{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001882 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001883}
1884
1885
1886static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1887 char *argv[])
1888{
1889 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1890}
1891
1892
1893static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1894 char *argv[])
1895{
1896 char cmd[4096];
1897 int res;
1898
1899 if (argc != 3 && argc != 4) {
1900 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1901 "arguments\n");
1902 return -1;
1903 }
1904
1905 if (argc == 4)
1906 res = os_snprintf(cmd, sizeof(cmd),
1907 "P2P_SERVICE_ADD %s %s %s %s",
1908 argv[0], argv[1], argv[2], argv[3]);
1909 else
1910 res = os_snprintf(cmd, sizeof(cmd),
1911 "P2P_SERVICE_ADD %s %s %s",
1912 argv[0], argv[1], argv[2]);
1913 if (res < 0 || (size_t) res >= sizeof(cmd))
1914 return -1;
1915 cmd[sizeof(cmd) - 1] = '\0';
1916 return wpa_ctrl_command(ctrl, cmd);
1917}
1918
1919
1920static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1921 char *argv[])
1922{
1923 char cmd[4096];
1924 int res;
1925
1926 if (argc != 2 && argc != 3) {
1927 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1928 "arguments\n");
1929 return -1;
1930 }
1931
1932 if (argc == 3)
1933 res = os_snprintf(cmd, sizeof(cmd),
1934 "P2P_SERVICE_DEL %s %s %s",
1935 argv[0], argv[1], argv[2]);
1936 else
1937 res = os_snprintf(cmd, sizeof(cmd),
1938 "P2P_SERVICE_DEL %s %s",
1939 argv[0], argv[1]);
1940 if (res < 0 || (size_t) res >= sizeof(cmd))
1941 return -1;
1942 cmd[sizeof(cmd) - 1] = '\0';
1943 return wpa_ctrl_command(ctrl, cmd);
1944}
1945
1946
1947static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1948 int argc, char *argv[])
1949{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001950 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001951}
1952
1953
1954static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1955 int argc, char *argv[])
1956{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001957 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001958}
1959
1960
1961static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1962{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07001963 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001964}
1965
1966
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08001967static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1968{
1969 int arg = get_cmd_arg_num(str, pos);
1970 char **res = NULL;
1971
1972 switch (arg) {
1973 case 1:
1974 res = cli_txt_list_array(&p2p_peers);
1975 break;
1976 }
1977
1978 return res;
1979}
1980
1981
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001982static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1983 char *addr, size_t addr_len,
1984 int discovered)
1985{
1986 char buf[4096], *pos;
1987 size_t len;
1988 int ret;
1989
1990 if (ctrl_conn == NULL)
1991 return -1;
1992 len = sizeof(buf) - 1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07001993 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07001994 wpa_cli_msg_cb);
1995 if (ret == -2) {
1996 printf("'%s' command timed out.\n", cmd);
1997 return -2;
1998 } else if (ret < 0) {
1999 printf("'%s' command failed.\n", cmd);
2000 return -1;
2001 }
2002
2003 buf[len] = '\0';
Dmitry Shmidt04949592012-07-19 12:16:46 -07002004 if (os_memcmp(buf, "FAIL", 4) == 0)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002005 return -1;
2006
2007 pos = buf;
2008 while (*pos != '\0' && *pos != '\n')
2009 pos++;
2010 *pos++ = '\0';
2011 os_strlcpy(addr, buf, addr_len);
2012 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
2013 printf("%s\n", addr);
2014 return 0;
2015}
2016
2017
2018static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
2019{
2020 char addr[32], cmd[64];
2021 int discovered;
2022
2023 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2024
2025 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2026 addr, sizeof(addr), discovered))
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002027 return -1;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002028 do {
2029 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2030 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2031 discovered) == 0);
2032
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002033 return 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002034}
2035
2036
2037static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2038{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002039 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002040}
2041
2042
2043static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2044{
2045 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2046}
2047
2048
2049static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2050 char *argv[])
2051{
2052 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2053}
2054
2055
2056static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2057 char *argv[])
2058{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002059 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002060}
2061
2062
2063static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2064 char *argv[])
2065{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002066 if (argc != 0 && argc != 2 && argc != 4) {
2067 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2068 "(preferred duration, interval; in microsecods).\n"
2069 "Optional second pair can be used to provide "
2070 "acceptable values.\n");
2071 return -1;
2072 }
2073
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002074 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002075}
2076
2077
2078static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2079 char *argv[])
2080{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002081 if (argc != 0 && argc != 2) {
2082 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2083 "(availability period, availability interval; in "
2084 "millisecods).\n"
2085 "Extended Listen Timing can be cancelled with this "
2086 "command when used without parameters.\n");
2087 return -1;
2088 }
2089
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002090 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2091}
2092
2093#endif /* CONFIG_P2P */
2094
2095#ifdef CONFIG_WIFI_DISPLAY
2096
2097static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2098 char *argv[])
2099{
2100 char cmd[100];
2101 int res;
2102
2103 if (argc != 1 && argc != 2) {
2104 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2105 "arguments (subelem, hexdump)\n");
2106 return -1;
2107 }
2108
2109 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2110 argv[0], argc > 1 ? argv[1] : "");
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002111 if (res < 0 || (size_t) res >= sizeof(cmd))
2112 return -1;
2113 cmd[sizeof(cmd) - 1] = '\0';
2114 return wpa_ctrl_command(ctrl, cmd);
2115}
2116
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002117
2118static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2119 char *argv[])
2120{
2121 char cmd[100];
2122 int res;
2123
2124 if (argc != 1) {
2125 printf("Invalid WFD_SUBELEM_GET command: needs one "
2126 "argument (subelem)\n");
2127 return -1;
2128 }
2129
2130 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2131 argv[0]);
2132 if (res < 0 || (size_t) res >= sizeof(cmd))
2133 return -1;
2134 cmd[sizeof(cmd) - 1] = '\0';
2135 return wpa_ctrl_command(ctrl, cmd);
2136}
2137#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002138
2139
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002140#ifdef CONFIG_INTERWORKING
2141static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2142 char *argv[])
2143{
2144 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2145}
2146
2147
2148static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2149 char *argv[])
2150{
2151 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2152}
2153
2154
2155static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2156 char *argv[])
2157{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002158 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002159}
2160
2161
2162static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2163 char *argv[])
2164{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002165 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002166}
2167
2168
2169static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2170{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002171 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2172}
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002173
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002174
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002175static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2176 char *argv[])
2177{
2178 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2179}
2180
2181
2182static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2183 char *argv[])
2184{
2185 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002186}
2187#endif /* CONFIG_INTERWORKING */
2188
2189
Dmitry Shmidt04949592012-07-19 12:16:46 -07002190#ifdef CONFIG_HS20
2191
2192static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2193 char *argv[])
2194{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002195 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002196}
2197
2198
2199static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2200 char *argv[])
2201{
2202 char cmd[512];
Dmitry Shmidt04949592012-07-19 12:16:46 -07002203
2204 if (argc == 0) {
2205 printf("Command needs one or two arguments (dst mac addr and "
2206 "optional home realm)\n");
2207 return -1;
2208 }
2209
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002210 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2211 argc, argv) < 0)
Dmitry Shmidt04949592012-07-19 12:16:46 -07002212 return -1;
Dmitry Shmidt04949592012-07-19 12:16:46 -07002213
2214 return wpa_ctrl_command(ctrl, cmd);
2215}
2216
2217#endif /* CONFIG_HS20 */
2218
2219
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002220static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2221 char *argv[])
2222{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002223 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002224}
2225
2226
2227static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2228 char *argv[])
2229{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002230 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002231}
2232
2233
2234static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2235 char *argv[])
2236{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002237 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002238}
2239
2240
2241static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2242 char *argv[])
2243{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002244 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002245}
2246
2247
2248static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2249 char *argv[])
2250{
2251 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2252}
2253
2254
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002255static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2256 char *argv[])
2257{
2258 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2259}
2260
2261
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002262static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2263 char *argv[])
2264{
2265 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2266}
2267
Dmitry Shmidt04949592012-07-19 12:16:46 -07002268
2269#ifdef CONFIG_AUTOSCAN
2270
2271static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2272{
Dmitry Shmidt04949592012-07-19 12:16:46 -07002273 if (argc == 0)
2274 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2275
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002276 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
Dmitry Shmidt04949592012-07-19 12:16:46 -07002277}
2278
2279#endif /* CONFIG_AUTOSCAN */
2280
2281
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002282#ifdef CONFIG_WNM
2283
2284static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2285{
2286 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2287}
2288
2289#endif /* CONFIG_WNM */
2290
2291
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002292static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2293{
2294 if (argc == 0)
2295 return -1;
2296 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2297}
2298
2299
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002300#ifdef ANDROID
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002301static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
2302{
2303 char cmd[256];
2304 int i;
2305 int len;
2306
2307 if (argc < 1) {
2308 printf("Invalid DRIVER command: needs one argument (cmd)\n");
2309 return -1;
2310 }
2311
2312 len = os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
2313 for (i=1; i < argc; i++)
2314 len += os_snprintf(cmd + len, sizeof(cmd) - len, " %s", argv[i]);
2315 cmd[sizeof(cmd) - 1] = '\0';
2316 printf("%s: %s\n", __func__, cmd);
2317 return wpa_ctrl_command(ctrl, cmd);
2318}
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002319#endif
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002320
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002321
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002322static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2323{
2324 return wpa_ctrl_command(ctrl, "FLUSH");
2325}
2326
2327
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002328enum wpa_cli_cmd_flags {
2329 cli_cmd_flag_none = 0x00,
2330 cli_cmd_flag_sensitive = 0x01
2331};
2332
2333struct wpa_cli_cmd {
2334 const char *cmd;
2335 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002336 char ** (*completion)(const char *str, int pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002337 enum wpa_cli_cmd_flags flags;
2338 const char *usage;
2339};
2340
2341static struct wpa_cli_cmd wpa_cli_commands[] = {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002342 { "status", wpa_cli_cmd_status, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002343 cli_cmd_flag_none,
2344 "[verbose] = get current WPA/EAPOL/EAP status" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002345 { "ifname", wpa_cli_cmd_ifname, NULL,
2346 cli_cmd_flag_none,
2347 "= get current interface name" },
2348 { "ping", wpa_cli_cmd_ping, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002349 cli_cmd_flag_none,
2350 "= pings wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002351 { "relog", wpa_cli_cmd_relog, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002352 cli_cmd_flag_none,
2353 "= re-open log-file (allow rolling logs)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002354 { "note", wpa_cli_cmd_note, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002355 cli_cmd_flag_none,
2356 "<text> = add a note to wpa_supplicant debug log" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002357 { "mib", wpa_cli_cmd_mib, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002358 cli_cmd_flag_none,
2359 "= get MIB variables (dot1x, dot11)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002360 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002361 cli_cmd_flag_none,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002362 "[command] = show usage help" },
2363 { "interface", wpa_cli_cmd_interface, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002364 cli_cmd_flag_none,
2365 "[ifname] = show interfaces/select interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002366 { "level", wpa_cli_cmd_level, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002367 cli_cmd_flag_none,
2368 "<debug level> = change debug level" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002369 { "license", wpa_cli_cmd_license, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002370 cli_cmd_flag_none,
2371 "= show full wpa_cli license" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002372 { "quit", wpa_cli_cmd_quit, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002373 cli_cmd_flag_none,
2374 "= exit wpa_cli" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002375 { "set", wpa_cli_cmd_set, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002376 cli_cmd_flag_none,
2377 "= set variables (shows list of variables when run without "
2378 "arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002379 { "get", wpa_cli_cmd_get, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002380 cli_cmd_flag_none,
2381 "<name> = get information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002382 { "logon", wpa_cli_cmd_logon, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002383 cli_cmd_flag_none,
2384 "= IEEE 802.1X EAPOL state machine logon" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002385 { "logoff", wpa_cli_cmd_logoff, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002386 cli_cmd_flag_none,
2387 "= IEEE 802.1X EAPOL state machine logoff" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002388 { "pmksa", wpa_cli_cmd_pmksa, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002389 cli_cmd_flag_none,
2390 "= show PMKSA cache" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002391 { "reassociate", wpa_cli_cmd_reassociate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002392 cli_cmd_flag_none,
2393 "= force reassociation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002394 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002395 cli_cmd_flag_none,
2396 "<BSSID> = force preauthentication" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002397 { "identity", wpa_cli_cmd_identity, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002398 cli_cmd_flag_none,
2399 "<network id> <identity> = configure identity for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002400 { "password", wpa_cli_cmd_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002401 cli_cmd_flag_sensitive,
2402 "<network id> <password> = configure password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002403 { "new_password", wpa_cli_cmd_new_password, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002404 cli_cmd_flag_sensitive,
2405 "<network id> <password> = change password for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002406 { "pin", wpa_cli_cmd_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002407 cli_cmd_flag_sensitive,
2408 "<network id> <pin> = configure pin for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002409 { "otp", wpa_cli_cmd_otp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002410 cli_cmd_flag_sensitive,
2411 "<network id> <password> = configure one-time-password for an SSID"
2412 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002413 { "passphrase", wpa_cli_cmd_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002414 cli_cmd_flag_sensitive,
2415 "<network id> <passphrase> = configure private key passphrase\n"
2416 " for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002417 { "bssid", wpa_cli_cmd_bssid, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002418 cli_cmd_flag_none,
2419 "<network id> <BSSID> = set preferred BSSID for an SSID" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002420 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002421 cli_cmd_flag_none,
2422 "<BSSID> = add a BSSID to the blacklist\n"
2423 "blacklist clear = clear the blacklist\n"
2424 "blacklist = display the blacklist" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002425 { "log_level", wpa_cli_cmd_log_level, NULL,
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002426 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002427 "<level> [<timestamp>] = update the log level/timestamp\n"
Dmitry Shmidt696359e2011-03-16 15:04:31 -07002428 "log_level = display the current log level and log options" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002429 { "list_networks", wpa_cli_cmd_list_networks, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002430 cli_cmd_flag_none,
2431 "= list configured networks" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002432 { "select_network", wpa_cli_cmd_select_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002433 cli_cmd_flag_none,
2434 "<network id> = select a network (disable others)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002435 { "enable_network", wpa_cli_cmd_enable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002436 cli_cmd_flag_none,
2437 "<network id> = enable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002438 { "disable_network", wpa_cli_cmd_disable_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002439 cli_cmd_flag_none,
2440 "<network id> = disable a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002441 { "add_network", wpa_cli_cmd_add_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002442 cli_cmd_flag_none,
2443 "= add a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002444 { "remove_network", wpa_cli_cmd_remove_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002445 cli_cmd_flag_none,
2446 "<network id> = remove a network" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002447 { "set_network", wpa_cli_cmd_set_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002448 cli_cmd_flag_sensitive,
2449 "<network id> <variable> <value> = set network variables (shows\n"
2450 " list of variables when run without arguments)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002451 { "get_network", wpa_cli_cmd_get_network, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002452 cli_cmd_flag_none,
2453 "<network id> <variable> = get network variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002454 { "list_creds", wpa_cli_cmd_list_creds, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002455 cli_cmd_flag_none,
2456 "= list configured credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002457 { "add_cred", wpa_cli_cmd_add_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002458 cli_cmd_flag_none,
2459 "= add a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002460 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002461 cli_cmd_flag_none,
2462 "<cred id> = remove a credential" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002463 { "set_cred", wpa_cli_cmd_set_cred, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002464 cli_cmd_flag_sensitive,
2465 "<cred id> <variable> <value> = set credential variables" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002466 { "save_config", wpa_cli_cmd_save_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002467 cli_cmd_flag_none,
2468 "= save the current configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002469 { "disconnect", wpa_cli_cmd_disconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002470 cli_cmd_flag_none,
2471 "= disconnect and wait for reassociate/reconnect command before\n"
2472 " connecting" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002473 { "reconnect", wpa_cli_cmd_reconnect, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002474 cli_cmd_flag_none,
2475 "= like reassociate, but only takes effect if already disconnected"
2476 },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002477 { "scan", wpa_cli_cmd_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002478 cli_cmd_flag_none,
2479 "= request new BSS scan" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002480 { "scan_results", wpa_cli_cmd_scan_results, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002481 cli_cmd_flag_none,
2482 "= get latest scan results" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002483 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002484 cli_cmd_flag_none,
2485 "<<idx> | <bssid>> = get detailed scan result info" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002486 { "get_capability", wpa_cli_cmd_get_capability, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002487 cli_cmd_flag_none,
Dmitry Shmidt8da800a2013-04-24 12:57:01 -07002488 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002489 "= get capabilies" },
2490 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002491 cli_cmd_flag_none,
2492 "= force wpa_supplicant to re-read its configuration file" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002493 { "terminate", wpa_cli_cmd_terminate, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002494 cli_cmd_flag_none,
2495 "= terminate wpa_supplicant" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002496 { "interface_add", wpa_cli_cmd_interface_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002497 cli_cmd_flag_none,
2498 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2499 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2500 " are optional" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002501 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002502 cli_cmd_flag_none,
2503 "<ifname> = removes the interface" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002504 { "interface_list", wpa_cli_cmd_interface_list, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002505 cli_cmd_flag_none,
2506 "= list available interfaces" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002507 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002508 cli_cmd_flag_none,
2509 "<value> = set ap_scan parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002510 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002511 cli_cmd_flag_none,
2512 "<value> = set scan_interval parameter (in seconds)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002513 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002514 cli_cmd_flag_none,
2515 "<value> = set BSS expiration age parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002516 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002517 cli_cmd_flag_none,
2518 "<value> = set BSS expiration scan count parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002519 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
Dmitry Shmidtf48e4f92012-08-24 11:14:44 -07002520 cli_cmd_flag_none,
2521 "<value> = set BSS flush age (0 by default)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002522 { "stkstart", wpa_cli_cmd_stkstart, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002523 cli_cmd_flag_none,
2524 "<addr> = request STK negotiation with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002525 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002526 cli_cmd_flag_none,
2527 "<addr> = request over-the-DS FT with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002528 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002529 cli_cmd_flag_none,
2530 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002531 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002532 cli_cmd_flag_sensitive,
2533 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2534 "hardcoded)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002535 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002536 cli_cmd_flag_sensitive,
2537 "<PIN> = verify PIN checksum" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002538 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002539 "Cancels the pending WPS operation" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002540#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002541 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002542 cli_cmd_flag_none,
2543 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002544 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2545 cli_cmd_flag_none,
2546 "<WPS|NDEF> = build configuration token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002547 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002548 cli_cmd_flag_none,
2549 "<WPS|NDEF> = create password token" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002550 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002551 cli_cmd_flag_sensitive,
2552 "<hexdump of payload> = report read NFC tag with WPS data" },
Dmitry Shmidtd5e49232012-12-03 15:08:10 -08002553 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2554 cli_cmd_flag_none,
2555 "<NDEF> <WPS> = create NFC handover request" },
2556 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2557 cli_cmd_flag_none,
2558 "<NDEF> <WPS> = create NFC handover select" },
2559 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2560 cli_cmd_flag_none,
2561 "<hexdump of payload> = report received NFC handover request" },
2562 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2563 cli_cmd_flag_none,
2564 "<hexdump of payload> = report received NFC handover select" },
Dmitry Shmidtf8623282013-02-20 14:34:59 -08002565 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2566 cli_cmd_flag_none,
2567 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2568 "NFC handover" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002569#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002570 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002571 cli_cmd_flag_sensitive,
2572 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002573 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002574 cli_cmd_flag_sensitive,
2575 "[params..] = enable/disable AP PIN" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002576 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002577 cli_cmd_flag_none,
2578 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002579 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002580 cli_cmd_flag_none,
2581 "= stop Wi-Fi Protected Setup External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002582 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002583 cli_cmd_flag_sensitive,
2584 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002585 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002586 cli_cmd_flag_none,
2587 "<UUID> = accept an Enrollee PBC using External Registrar" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002588 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002589 cli_cmd_flag_sensitive,
2590 "<UUID> <PIN> = learn AP configuration" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002591 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002592 cli_cmd_flag_none,
2593 "<UUID> <network id> = set AP configuration for enrolling" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002594 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002595 cli_cmd_flag_sensitive,
2596 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002597#ifdef CONFIG_WPS_NFC
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002598 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002599 cli_cmd_flag_none,
2600 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2601#endif /* CONFIG_WPS_NFC */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002602 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002603 cli_cmd_flag_none,
2604 "<addr> = request RSN authentication with <addr> in IBSS" },
2605#ifdef CONFIG_AP
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002606 { "sta", wpa_cli_cmd_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002607 cli_cmd_flag_none,
2608 "<addr> = get information about an associated station (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002609 { "all_sta", wpa_cli_cmd_all_sta, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002610 cli_cmd_flag_none,
2611 "= get information about all associated stations (AP)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002612 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002613 cli_cmd_flag_none,
2614 "<addr> = deauthenticate a station" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002615 { "disassociate", wpa_cli_cmd_disassociate, NULL,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002616 cli_cmd_flag_none,
2617 "<addr> = disassociate a station" },
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002618#endif /* CONFIG_AP */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002619 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002620 "= notification of suspend/hibernate" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002621 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002622 "= notification of resume/thaw" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002623 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002624 "= drop SA without deauth/disassoc (test command)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002625 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002626 cli_cmd_flag_none,
2627 "<addr> = roam to the specified BSS" },
2628#ifdef CONFIG_P2P
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002629 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2630 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002631 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002632 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002633 "= stop P2P Devices search" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002634 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2635 cli_cmd_flag_none,
2636 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2637 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002638 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002639 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2640 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002641 "<ifname> = remove P2P group interface (terminate group if GO)" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002642 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2643 "[ht40] = add a new P2P group (local end as GO)" },
2644 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2645 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002646 "<addr> <method> = request provisioning discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002647 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002648 cli_cmd_flag_none,
2649 "= get the passphrase for a group (GO only)" },
2650 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002651 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002652 "<addr> <TLVs> = schedule service discovery request" },
2653 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002654 NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002655 "<id> = cancel pending service discovery request" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002656 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002657 cli_cmd_flag_none,
2658 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002659 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002660 cli_cmd_flag_none,
2661 "= indicate change in local services" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002662 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002663 cli_cmd_flag_none,
2664 "<external> = set external processing of service discovery" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002665 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002666 cli_cmd_flag_none,
2667 "= remove all stored service entries" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002668 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002669 cli_cmd_flag_none,
2670 "<bonjour|upnp> <query|version> <response|service> = add a local "
2671 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002672 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002673 cli_cmd_flag_none,
2674 "<bonjour|upnp> <query|version> [|service] = remove a local "
2675 "service" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002676 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002677 cli_cmd_flag_none,
2678 "<addr> = reject connection attempts from a specific peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002679 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002680 cli_cmd_flag_none,
2681 "<cmd> [peer=addr] = invite peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002682 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002683 "[discovered] = list known (optionally, only fully discovered) P2P "
2684 "peers" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002685 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2686 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002687 "<address> = show information about known P2P peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002688 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002689 "<field> <value> = set a P2P parameter" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002690 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002691 "= flush P2P state" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002692 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002693 "= cancel P2P group formation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002694 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2695 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002696 "<address> = unauthorize a peer" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002697 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2698 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002699 "[<duration> <interval>] [<duration> <interval>] = request GO "
2700 "presence" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002701 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2702 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002703 "[<period> <interval>] = set extended listen timing" },
2704#endif /* CONFIG_P2P */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002705#ifdef CONFIG_WIFI_DISPLAY
2706 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2707 cli_cmd_flag_none,
2708 "<subelem> [contents] = set Wi-Fi Display subelement" },
2709 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2710 cli_cmd_flag_none,
2711 "<subelem> = get Wi-Fi Display subelement" },
2712#endif /* CONFIG_WIFI_DISPLAY */
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002713#ifdef CONFIG_INTERWORKING
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002714 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002715 "= fetch ANQP information for all APs" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002716 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2717 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002718 "= stop fetch_anqp operation" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002719 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002720 cli_cmd_flag_none,
2721 "[auto] = perform Interworking network selection" },
2722 { "interworking_connect", wpa_cli_cmd_interworking_connect,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002723 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002724 "<BSSID> = connect using Interworking credentials" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002725 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2726 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002727 "<addr> <info id>[,<info id>]... = request ANQP information" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002728 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2729 cli_cmd_flag_none,
2730 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2731 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2732 wpa_cli_complete_bss, cli_cmd_flag_none,
2733 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002734#endif /* CONFIG_INTERWORKING */
Dmitry Shmidt04949592012-07-19 12:16:46 -07002735#ifdef CONFIG_HS20
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002736 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2737 cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002738 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2739 },
2740 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002741 wpa_cli_complete_bss, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002742 "<addr> <home realm> = get HS20 nai home realm list" },
2743#endif /* CONFIG_HS20 */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002744 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2745 cli_cmd_flag_none,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002746 "<0/1> = disable/enable automatic reconnection" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002747 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002748 cli_cmd_flag_none,
2749 "<addr> = request TDLS discovery with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002750 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002751 cli_cmd_flag_none,
2752 "<addr> = request TDLS setup with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002753 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002754 cli_cmd_flag_none,
2755 "<addr> = tear down TDLS with <addr>" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002756 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002757 cli_cmd_flag_none,
2758 "= get signal parameters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002759 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
Yuhao Zhengfcd6f212012-07-27 10:37:52 -07002760 cli_cmd_flag_none,
2761 "= get TX/RX packet counters" },
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002762 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2763 cli_cmd_flag_none,
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08002764 "= trigger IEEE 802.1X/EAPOL reauthentication" },
Dmitry Shmidt04949592012-07-19 12:16:46 -07002765#ifdef CONFIG_AUTOSCAN
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002766 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
Dmitry Shmidt04949592012-07-19 12:16:46 -07002767 "[params] = Set or unset (if none) autoscan parameters" },
2768#endif /* CONFIG_AUTOSCAN */
Dmitry Shmidta54fa5f2013-01-15 13:53:35 -08002769#ifdef CONFIG_WNM
2770 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2771 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
2772#endif /* CONFIG_WNM */
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002773 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2774 "<params..> = Sent unprocessed command" },
Dmitry Shmidt444d5672013-04-01 13:08:44 -07002775 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2776 "= flush wpa_supplicant state" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002777#ifdef ANDROID
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002778 { "driver", wpa_cli_cmd_driver, NULL,
Dmitry Shmidt0716c122011-04-08 15:03:17 -07002779 cli_cmd_flag_none,
2780 "<command> = driver private commands" },
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08002781#endif
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002782 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002783};
2784
2785
2786/*
2787 * Prints command usage, lines are padded with the specified string.
2788 */
2789static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2790{
2791 char c;
2792 size_t n;
2793
2794 printf("%s%s ", pad, cmd->cmd);
2795 for (n = 0; (c = cmd->usage[n]); n++) {
2796 printf("%c", c);
2797 if (c == '\n')
2798 printf("%s", pad);
2799 }
2800 printf("\n");
2801}
2802
2803
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002804static void print_help(const char *cmd)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002805{
2806 int n;
2807 printf("commands:\n");
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002808 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2809 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2810 print_cmd_help(&wpa_cli_commands[n], " ");
2811 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002812}
2813
2814
2815static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2816{
2817 const char *c, *delim;
2818 int n;
2819 size_t len;
2820
2821 delim = os_strchr(cmd, ' ');
2822 if (delim)
2823 len = delim - cmd;
2824 else
2825 len = os_strlen(cmd);
2826
2827 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2828 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2829 return (wpa_cli_commands[n].flags &
2830 cli_cmd_flag_sensitive);
2831 }
2832 return 0;
2833}
2834
2835
2836static char ** wpa_list_cmd_list(void)
2837{
2838 char **res;
2839 int i, count;
2840
2841 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002842 res = os_calloc(count, sizeof(char *));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002843 if (res == NULL)
2844 return NULL;
2845
2846 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2847 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2848 if (res[i] == NULL)
2849 break;
2850 }
2851
2852 return res;
2853}
2854
2855
2856static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2857 int pos)
2858{
2859 int i;
2860
2861 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2862 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07002863 if (wpa_cli_commands[i].completion)
2864 return wpa_cli_commands[i].completion(str,
2865 pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002866 edit_clear_line();
2867 printf("\r%s\n", wpa_cli_commands[i].usage);
2868 edit_redraw();
2869 break;
2870 }
2871 }
2872
2873 return NULL;
2874}
2875
2876
2877static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2878{
2879 char **res;
2880 const char *end;
2881 char *cmd;
2882
2883 end = os_strchr(str, ' ');
2884 if (end == NULL || str + pos < end)
2885 return wpa_list_cmd_list();
2886
2887 cmd = os_malloc(pos + 1);
2888 if (cmd == NULL)
2889 return NULL;
2890 os_memcpy(cmd, str, pos);
2891 cmd[end - str] = '\0';
2892 res = wpa_cli_cmd_completion(cmd, str, pos);
2893 os_free(cmd);
2894 return res;
2895}
2896
2897
2898static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2899{
2900 struct wpa_cli_cmd *cmd, *match = NULL;
2901 int count;
2902 int ret = 0;
2903
2904 count = 0;
2905 cmd = wpa_cli_commands;
2906 while (cmd->cmd) {
2907 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2908 {
2909 match = cmd;
2910 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2911 /* we have an exact match */
2912 count = 1;
2913 break;
2914 }
2915 count++;
2916 }
2917 cmd++;
2918 }
2919
2920 if (count > 1) {
2921 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2922 cmd = wpa_cli_commands;
2923 while (cmd->cmd) {
2924 if (os_strncasecmp(cmd->cmd, argv[0],
2925 os_strlen(argv[0])) == 0) {
2926 printf(" %s", cmd->cmd);
2927 }
2928 cmd++;
2929 }
2930 printf("\n");
2931 ret = 1;
2932 } else if (count == 0) {
2933 printf("Unknown command '%s'\n", argv[0]);
2934 ret = 1;
2935 } else {
Dmitry Shmidt2fb777c2012-05-02 12:29:53 -07002936#if defined(CONFIG_P2P) && defined(ANDROID_P2P)
2937 if ( (argc >= 2) && (os_strncmp(argv[1], "interface=", 10) == 0)) {
2938 redirect_interface = os_strdup(argv[1]);
2939 ret = match->handler(ctrl, argc - 2, &argv[2]);
2940 }
2941 else
2942#endif
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07002943 ret = match->handler(ctrl, argc - 1, &argv[1]);
2944 }
2945
2946 return ret;
2947}
2948
2949
2950static int str_match(const char *a, const char *b)
2951{
2952 return os_strncmp(a, b, os_strlen(b)) == 0;
2953}
2954
2955
2956static int wpa_cli_exec(const char *program, const char *arg1,
2957 const char *arg2)
2958{
2959 char *cmd;
2960 size_t len;
2961 int res;
2962 int ret = 0;
2963
2964 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2965 cmd = os_malloc(len);
2966 if (cmd == NULL)
2967 return -1;
2968 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2969 if (res < 0 || (size_t) res >= len) {
2970 os_free(cmd);
2971 return -1;
2972 }
2973 cmd[len - 1] = '\0';
2974#ifndef _WIN32_WCE
2975 if (system(cmd) < 0)
2976 ret = -1;
2977#endif /* _WIN32_WCE */
2978 os_free(cmd);
2979
2980 return ret;
2981}
2982
2983
2984static void wpa_cli_action_process(const char *msg)
2985{
2986 const char *pos;
2987 char *copy = NULL, *id, *pos2;
2988
2989 pos = msg;
2990 if (*pos == '<') {
2991 /* skip priority */
2992 pos = os_strchr(pos, '>');
2993 if (pos)
2994 pos++;
2995 else
2996 pos = msg;
2997 }
2998
2999 if (str_match(pos, WPA_EVENT_CONNECTED)) {
3000 int new_id = -1;
3001 os_unsetenv("WPA_ID");
3002 os_unsetenv("WPA_ID_STR");
3003 os_unsetenv("WPA_CTRL_DIR");
3004
3005 pos = os_strstr(pos, "[id=");
3006 if (pos)
3007 copy = os_strdup(pos + 4);
3008
3009 if (copy) {
3010 pos2 = id = copy;
3011 while (*pos2 && *pos2 != ' ')
3012 pos2++;
3013 *pos2++ = '\0';
3014 new_id = atoi(id);
3015 os_setenv("WPA_ID", id, 1);
3016 while (*pos2 && *pos2 != '=')
3017 pos2++;
3018 if (*pos2 == '=')
3019 pos2++;
3020 id = pos2;
3021 while (*pos2 && *pos2 != ']')
3022 pos2++;
3023 *pos2 = '\0';
3024 os_setenv("WPA_ID_STR", id, 1);
3025 os_free(copy);
3026 }
3027
3028 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
3029
3030 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
3031 wpa_cli_connected = 1;
3032 wpa_cli_last_id = new_id;
3033 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
3034 }
3035 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
3036 if (wpa_cli_connected) {
3037 wpa_cli_connected = 0;
3038 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
3039 }
3040 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
3041 wpa_cli_exec(action_file, ctrl_ifname, pos);
3042 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
3043 wpa_cli_exec(action_file, ctrl_ifname, pos);
3044 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
3045 wpa_cli_exec(action_file, ctrl_ifname, pos);
3046 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
3047 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003048 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
3049 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003050 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
3051 wpa_cli_exec(action_file, ctrl_ifname, pos);
3052 } else if (str_match(pos, WPS_EVENT_FAIL)) {
3053 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003054 } else if (str_match(pos, AP_STA_CONNECTED)) {
3055 wpa_cli_exec(action_file, ctrl_ifname, pos);
3056 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3057 wpa_cli_exec(action_file, ctrl_ifname, pos);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003058 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3059 printf("wpa_supplicant is terminating - stop monitoring\n");
3060 wpa_cli_quit = 1;
3061 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003062}
3063
3064
3065#ifndef CONFIG_ANSI_C_EXTRA
3066static void wpa_cli_action_cb(char *msg, size_t len)
3067{
3068 wpa_cli_action_process(msg);
3069}
3070#endif /* CONFIG_ANSI_C_EXTRA */
3071
3072
3073static void wpa_cli_reconnect(void)
3074{
3075 wpa_cli_close_connection();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003076 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3077 return;
3078
3079 if (interactive) {
3080 edit_clear_line();
3081 printf("\rConnection to wpa_supplicant re-established\n");
3082 edit_redraw();
3083 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003084}
3085
3086
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003087static void cli_event(const char *str)
3088{
3089 const char *start, *s;
3090
3091 start = os_strchr(str, '>');
3092 if (start == NULL)
3093 return;
3094
3095 start++;
3096
3097 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3098 s = os_strchr(start, ' ');
3099 if (s == NULL)
3100 return;
3101 s = os_strchr(s + 1, ' ');
3102 if (s == NULL)
3103 return;
3104 cli_txt_list_add(&bsses, s + 1);
3105 return;
3106 }
3107
3108 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3109 s = os_strchr(start, ' ');
3110 if (s == NULL)
3111 return;
3112 s = os_strchr(s + 1, ' ');
3113 if (s == NULL)
3114 return;
3115 cli_txt_list_del_addr(&bsses, s + 1);
3116 return;
3117 }
3118
3119#ifdef CONFIG_P2P
3120 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3121 s = os_strstr(start, " p2p_dev_addr=");
3122 if (s == NULL)
3123 return;
3124 cli_txt_list_add_addr(&p2p_peers, s + 14);
3125 return;
3126 }
3127
3128 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3129 s = os_strstr(start, " p2p_dev_addr=");
3130 if (s == NULL)
3131 return;
3132 cli_txt_list_del_addr(&p2p_peers, s + 14);
3133 return;
3134 }
3135
3136 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3137 s = os_strchr(start, ' ');
3138 if (s == NULL)
3139 return;
3140 cli_txt_list_add_word(&p2p_groups, s + 1);
3141 return;
3142 }
3143
3144 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3145 s = os_strchr(start, ' ');
3146 if (s == NULL)
3147 return;
3148 cli_txt_list_del_word(&p2p_groups, s + 1);
3149 return;
3150 }
3151#endif /* CONFIG_P2P */
3152}
3153
3154
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003155static int check_terminating(const char *msg)
3156{
3157 const char *pos = msg;
3158
3159 if (*pos == '<') {
3160 /* skip priority */
3161 pos = os_strchr(pos, '>');
3162 if (pos)
3163 pos++;
3164 else
3165 pos = msg;
3166 }
3167
3168 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3169 edit_clear_line();
3170 printf("\rConnection to wpa_supplicant lost - trying to "
3171 "reconnect\n");
3172 edit_redraw();
3173 wpa_cli_attached = 0;
3174 wpa_cli_close_connection();
3175 return 1;
3176 }
3177
3178 return 0;
3179}
3180
3181
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003182static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3183{
3184 if (ctrl_conn == NULL) {
3185 wpa_cli_reconnect();
3186 return;
3187 }
3188 while (wpa_ctrl_pending(ctrl) > 0) {
3189 char buf[256];
3190 size_t len = sizeof(buf) - 1;
3191 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3192 buf[len] = '\0';
3193 if (action_monitor)
3194 wpa_cli_action_process(buf);
3195 else {
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003196 cli_event(buf);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003197 if (wpa_cli_show_event(buf)) {
3198 edit_clear_line();
3199 printf("\r%s\n", buf);
3200 edit_redraw();
3201 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003202
3203 if (interactive && check_terminating(buf) > 0)
3204 return;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003205 }
3206 } else {
3207 printf("Could not read pending message.\n");
3208 break;
3209 }
3210 }
3211
3212 if (wpa_ctrl_pending(ctrl) < 0) {
3213 printf("Connection to wpa_supplicant lost - trying to "
3214 "reconnect\n");
3215 wpa_cli_reconnect();
3216 }
3217}
3218
3219#define max_args 10
3220
3221static int tokenize_cmd(char *cmd, char *argv[])
3222{
3223 char *pos;
3224 int argc = 0;
3225
3226 pos = cmd;
3227 for (;;) {
3228 while (*pos == ' ')
3229 pos++;
3230 if (*pos == '\0')
3231 break;
3232 argv[argc] = pos;
3233 argc++;
3234 if (argc == max_args)
3235 break;
3236 if (*pos == '"') {
3237 char *pos2 = os_strrchr(pos, '"');
3238 if (pos2)
3239 pos = pos2 + 1;
3240 }
3241 while (*pos != '\0' && *pos != ' ')
3242 pos++;
3243 if (*pos == ' ')
3244 *pos++ = '\0';
3245 }
3246
3247 return argc;
3248}
3249
3250
3251static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3252{
3253 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3254 printf("Connection to wpa_supplicant lost - trying to "
3255 "reconnect\n");
3256 wpa_cli_close_connection();
3257 }
3258 if (!ctrl_conn)
3259 wpa_cli_reconnect();
3260 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3261}
3262
3263
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003264static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3265{
3266 wpa_cli_recv_pending(mon_conn, 0);
3267}
3268
3269
3270static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3271{
3272 char *argv[max_args];
3273 int argc;
3274 argc = tokenize_cmd(cmd, argv);
3275 if (argc)
3276 wpa_request(ctrl_conn, argc, argv);
3277}
3278
3279
3280static void wpa_cli_edit_eof_cb(void *ctx)
3281{
3282 eloop_terminate();
3283}
3284
3285
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003286static int warning_displayed = 0;
3287static char *hfile = NULL;
3288static int edit_started = 0;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003289
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003290static void start_edit(void)
3291{
3292 char *home;
3293 char *ps = NULL;
3294
3295#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3296 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3297#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003298
3299 home = getenv("HOME");
3300 if (home) {
3301 const char *fname = ".wpa_cli_history";
3302 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3303 hfile = os_malloc(hfile_len);
3304 if (hfile)
3305 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3306 }
3307
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003308 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3309 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3310 eloop_terminate();
3311 return;
3312 }
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003313
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003314 edit_started = 1;
3315 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3316}
3317
3318
3319static void try_connection(void *eloop_ctx, void *timeout_ctx)
3320{
3321 if (ctrl_ifname == NULL)
3322 ctrl_ifname = wpa_cli_get_default_ifname();
3323
3324 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3325 if (!warning_displayed) {
3326 printf("Could not connect to wpa_supplicant: "
3327 "%s - re-trying\n", ctrl_ifname);
3328 warning_displayed = 1;
3329 }
3330 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3331 return;
3332 }
3333
3334 if (warning_displayed)
3335 printf("Connection established.\n");
3336
3337 start_edit();
3338}
3339
3340
3341static void wpa_cli_interactive(void)
3342{
3343 printf("\nInteractive mode\n\n");
3344
3345 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003346 eloop_run();
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003347 eloop_cancel_timeout(try_connection, NULL, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003348
Dmitry Shmidt1f69aa52012-01-24 16:10:04 -08003349 cli_txt_list_flush(&p2p_peers);
3350 cli_txt_list_flush(&p2p_groups);
3351 cli_txt_list_flush(&bsses);
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003352 if (edit_started)
3353 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003354 os_free(hfile);
3355 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3356 wpa_cli_close_connection();
3357}
3358
3359
3360static void wpa_cli_action(struct wpa_ctrl *ctrl)
3361{
3362#ifdef CONFIG_ANSI_C_EXTRA
3363 /* TODO: ANSI C version(?) */
3364 printf("Action processing not supported in ANSI C build.\n");
3365#else /* CONFIG_ANSI_C_EXTRA */
3366 fd_set rfds;
3367 int fd, res;
3368 struct timeval tv;
3369 char buf[256]; /* note: large enough to fit in unsolicited messages */
3370 size_t len;
3371
3372 fd = wpa_ctrl_get_fd(ctrl);
3373
3374 while (!wpa_cli_quit) {
3375 FD_ZERO(&rfds);
3376 FD_SET(fd, &rfds);
3377 tv.tv_sec = ping_interval;
3378 tv.tv_usec = 0;
3379 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3380 if (res < 0 && errno != EINTR) {
3381 perror("select");
3382 break;
3383 }
3384
3385 if (FD_ISSET(fd, &rfds))
3386 wpa_cli_recv_pending(ctrl, 1);
3387 else {
3388 /* verify that connection is still working */
3389 len = sizeof(buf) - 1;
3390 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3391 wpa_cli_action_cb) < 0 ||
3392 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3393 printf("wpa_supplicant did not reply to PING "
3394 "command - exiting\n");
3395 break;
3396 }
3397 }
3398 }
3399#endif /* CONFIG_ANSI_C_EXTRA */
3400}
3401
3402
3403static void wpa_cli_cleanup(void)
3404{
3405 wpa_cli_close_connection();
3406 if (pid_file)
3407 os_daemonize_terminate(pid_file);
3408
3409 os_program_deinit();
3410}
3411
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003412
3413static void wpa_cli_terminate(int sig, void *ctx)
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003414{
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003415 eloop_terminate();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003416}
3417
3418
3419static char * wpa_cli_get_default_ifname(void)
3420{
3421 char *ifname = NULL;
3422
3423#ifdef CONFIG_CTRL_IFACE_UNIX
3424 struct dirent *dent;
3425 DIR *dir = opendir(ctrl_iface_dir);
3426 if (!dir) {
3427#ifdef ANDROID
3428 char ifprop[PROPERTY_VALUE_MAX];
3429 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3430 ifname = os_strdup(ifprop);
3431 printf("Using interface '%s'\n", ifname);
3432 return ifname;
3433 }
3434#endif /* ANDROID */
3435 return NULL;
3436 }
3437 while ((dent = readdir(dir))) {
3438#ifdef _DIRENT_HAVE_D_TYPE
3439 /*
3440 * Skip the file if it is not a socket. Also accept
3441 * DT_UNKNOWN (0) in case the C library or underlying
3442 * file system does not support d_type.
3443 */
3444 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3445 continue;
3446#endif /* _DIRENT_HAVE_D_TYPE */
3447 if (os_strcmp(dent->d_name, ".") == 0 ||
3448 os_strcmp(dent->d_name, "..") == 0)
3449 continue;
3450 printf("Selected interface '%s'\n", dent->d_name);
3451 ifname = os_strdup(dent->d_name);
3452 break;
3453 }
3454 closedir(dir);
3455#endif /* CONFIG_CTRL_IFACE_UNIX */
3456
3457#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
Dmitry Shmidtc5ec7f52012-03-06 16:33:24 -08003458 char buf[2048], *pos;
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003459 size_t len;
3460 struct wpa_ctrl *ctrl;
3461 int ret;
3462
3463 ctrl = wpa_ctrl_open(NULL);
3464 if (ctrl == NULL)
3465 return NULL;
3466
3467 len = sizeof(buf) - 1;
3468 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3469 if (ret >= 0) {
3470 buf[len] = '\0';
3471 pos = os_strchr(buf, '\n');
3472 if (pos)
3473 *pos = '\0';
3474 ifname = os_strdup(buf);
3475 }
3476 wpa_ctrl_close(ctrl);
3477#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3478
3479 return ifname;
3480}
3481
3482
3483int main(int argc, char *argv[])
3484{
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003485 int c;
3486 int daemonize = 0;
3487 int ret = 0;
3488 const char *global = NULL;
3489
3490 if (os_program_init())
3491 return -1;
3492
3493 for (;;) {
3494 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3495 if (c < 0)
3496 break;
3497 switch (c) {
3498 case 'a':
3499 action_file = optarg;
3500 break;
3501 case 'B':
3502 daemonize = 1;
3503 break;
3504 case 'g':
3505 global = optarg;
3506 break;
3507 case 'G':
3508 ping_interval = atoi(optarg);
3509 break;
3510 case 'h':
3511 usage();
3512 return 0;
3513 case 'v':
3514 printf("%s\n", wpa_cli_version);
3515 return 0;
3516 case 'i':
3517 os_free(ctrl_ifname);
3518 ctrl_ifname = os_strdup(optarg);
3519 break;
3520 case 'p':
3521 ctrl_iface_dir = optarg;
3522 break;
3523 case 'P':
3524 pid_file = optarg;
3525 break;
3526 default:
3527 usage();
3528 return -1;
3529 }
3530 }
3531
3532 interactive = (argc == optind) && (action_file == NULL);
3533
3534 if (interactive)
3535 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3536
3537 if (eloop_init())
3538 return -1;
3539
3540 if (global) {
3541#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3542 ctrl_conn = wpa_ctrl_open(NULL);
3543#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3544 ctrl_conn = wpa_ctrl_open(global);
3545#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3546 if (ctrl_conn == NULL) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003547 fprintf(stderr, "Failed to connect to wpa_supplicant "
3548 "global interface: %s error: %s\n",
3549 global, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003550 return -1;
3551 }
3552 }
3553
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003554 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003555
3556 if (ctrl_ifname == NULL)
3557 ctrl_ifname = wpa_cli_get_default_ifname();
3558
3559 if (interactive) {
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003560 wpa_cli_interactive();
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003561 } else {
3562 if (!global &&
3563 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
Dmitry Shmidt04949592012-07-19 12:16:46 -07003564 fprintf(stderr, "Failed to connect to non-global "
3565 "ctrl_ifname: %s error: %s\n",
3566 ctrl_ifname, strerror(errno));
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003567 return -1;
3568 }
3569
3570 if (action_file) {
3571 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3572 wpa_cli_attached = 1;
3573 } else {
3574 printf("Warning: Failed to attach to "
3575 "wpa_supplicant.\n");
3576 return -1;
3577 }
3578 }
Dmitry Shmidt61d9df32012-08-29 16:22:06 -07003579
3580 if (daemonize && os_daemonize(pid_file))
3581 return -1;
3582
3583 if (action_file)
3584 wpa_cli_action(ctrl_conn);
3585 else
3586 ret = wpa_request(ctrl_conn, argc - optind,
3587 &argv[optind]);
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003588 }
3589
Dmitry Shmidt8d520ff2011-05-09 14:06:53 -07003590 os_free(ctrl_ifname);
3591 eloop_destroy();
3592 wpa_cli_cleanup();
3593
3594 return ret;
3595}
3596
3597#else /* CONFIG_CTRL_IFACE */
3598int main(int argc, char *argv[])
3599{
3600 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3601 return -1;
3602}
3603#endif /* CONFIG_CTRL_IFACE */