]> git.ipfire.org Git - thirdparty/hostap.git/blob - wpa_supplicant/wpa_cli.c
Add dup_binstr() to help common binary string tasks
[thirdparty/hostap.git] / wpa_supplicant / wpa_cli.c
1 /*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
4 *
5 * This software may be distributed under the terms of the BSD license.
6 * See README for more details.
7 */
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"
21 #include "utils/list.h"
22 #include "common/version.h"
23 #include "common/ieee802_11_defs.h"
24 #ifdef ANDROID
25 #include <cutils/properties.h>
26 #endif /* ANDROID */
27
28
29 static const char *wpa_cli_version =
30 "wpa_cli v" VERSION_STR "\n"
31 "Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> and contributors";
32
33
34 static const char *wpa_cli_license =
35 "This software may be distributed under the terms of the BSD license.\n"
36 "See README for more details.\n";
37
38 static const char *wpa_cli_full_license =
39 "This software may be distributed under the terms of the BSD license.\n"
40 "\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
69 static struct wpa_ctrl *ctrl_conn;
70 static struct wpa_ctrl *mon_conn;
71 static int wpa_cli_quit = 0;
72 static int wpa_cli_attached = 0;
73 static int wpa_cli_connected = 0;
74 static 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 */
78 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
79 static char *ctrl_ifname = NULL;
80 static const char *pid_file = NULL;
81 static const char *action_file = NULL;
82 static int ping_interval = 5;
83 static int interactive = 0;
84
85 struct cli_txt_entry {
86 struct dl_list list;
87 char *txt;
88 };
89
90 static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */
91 static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */
92 static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */
93
94
95 static void print_help(const char *cmd);
96 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx);
97 static void wpa_cli_close_connection(void);
98 static char * wpa_cli_get_default_ifname(void);
99 static char ** wpa_list_cmd_list(void);
100
101
102 static void usage(void)
103 {
104 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
105 "[-a<action file>] \\\n"
106 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] "
107 "[command..]\n"
108 " -h = help (show this usage text)\n"
109 " -v = shown version information\n"
110 " -a = run in daemon mode executing the action file based on "
111 "events from\n"
112 " wpa_supplicant\n"
113 " -B = run a daemon in the background\n"
114 " default path: " CONFIG_CTRL_IFACE_DIR "\n"
115 " default interface: first interface found in socket path\n");
116 print_help(NULL);
117 }
118
119
120 static void cli_txt_list_free(struct cli_txt_entry *e)
121 {
122 dl_list_del(&e->list);
123 os_free(e->txt);
124 os_free(e);
125 }
126
127
128 static void cli_txt_list_flush(struct dl_list *list)
129 {
130 struct cli_txt_entry *e;
131 while ((e = dl_list_first(list, struct cli_txt_entry, list)))
132 cli_txt_list_free(e);
133 }
134
135
136 static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list,
137 const char *txt)
138 {
139 struct cli_txt_entry *e;
140 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
141 if (os_strcmp(e->txt, txt) == 0)
142 return e;
143 }
144 return NULL;
145 }
146
147
148 static void cli_txt_list_del(struct dl_list *txt_list, const char *txt)
149 {
150 struct cli_txt_entry *e;
151 e = cli_txt_list_get(txt_list, txt);
152 if (e)
153 cli_txt_list_free(e);
154 }
155
156
157 static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt)
158 {
159 u8 addr[ETH_ALEN];
160 char buf[18];
161 if (hwaddr_aton(txt, addr) < 0)
162 return;
163 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
164 cli_txt_list_del(txt_list, buf);
165 }
166
167
168 #ifdef CONFIG_P2P
169 static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt)
170 {
171 const char *end;
172 char *buf;
173 end = os_strchr(txt, ' ');
174 if (end == NULL)
175 end = txt + os_strlen(txt);
176 buf = dup_binstr(txt, end - txt);
177 if (buf == NULL)
178 return;
179 cli_txt_list_del(txt_list, buf);
180 os_free(buf);
181 }
182 #endif /* CONFIG_P2P */
183
184
185 static int cli_txt_list_add(struct dl_list *txt_list, const char *txt)
186 {
187 struct cli_txt_entry *e;
188 e = cli_txt_list_get(txt_list, txt);
189 if (e)
190 return 0;
191 e = os_zalloc(sizeof(*e));
192 if (e == NULL)
193 return -1;
194 e->txt = os_strdup(txt);
195 if (e->txt == NULL) {
196 os_free(e);
197 return -1;
198 }
199 dl_list_add(txt_list, &e->list);
200 return 0;
201 }
202
203
204 #ifdef CONFIG_P2P
205 static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt)
206 {
207 u8 addr[ETH_ALEN];
208 char buf[18];
209 if (hwaddr_aton(txt, addr) < 0)
210 return -1;
211 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr));
212 return cli_txt_list_add(txt_list, buf);
213 }
214
215
216 static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt)
217 {
218 const char *end;
219 char *buf;
220 int ret;
221 end = os_strchr(txt, ' ');
222 if (end == NULL)
223 end = txt + os_strlen(txt);
224 buf = dup_binstr(txt, end - txt);
225 if (buf == NULL)
226 return -1;
227 ret = cli_txt_list_add(txt_list, buf);
228 os_free(buf);
229 return ret;
230 }
231 #endif /* CONFIG_P2P */
232
233
234 static char ** cli_txt_list_array(struct dl_list *txt_list)
235 {
236 unsigned int i, count = dl_list_len(txt_list);
237 char **res;
238 struct cli_txt_entry *e;
239
240 res = os_calloc(count + 1, sizeof(char *));
241 if (res == NULL)
242 return NULL;
243
244 i = 0;
245 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) {
246 res[i] = os_strdup(e->txt);
247 if (res[i] == NULL)
248 break;
249 i++;
250 }
251
252 return res;
253 }
254
255
256 static int get_cmd_arg_num(const char *str, int pos)
257 {
258 int arg = 0, i;
259
260 for (i = 0; i <= pos; i++) {
261 if (str[i] != ' ') {
262 arg++;
263 while (i <= pos && str[i] != ' ')
264 i++;
265 }
266 }
267
268 if (arg > 0)
269 arg--;
270 return arg;
271 }
272
273
274 static int str_starts(const char *src, const char *match)
275 {
276 return os_strncmp(src, match, os_strlen(match)) == 0;
277 }
278
279
280 static int wpa_cli_show_event(const char *event)
281 {
282 const char *start;
283
284 start = os_strchr(event, '>');
285 if (start == NULL)
286 return 1;
287
288 start++;
289 /*
290 * Skip BSS added/removed events since they can be relatively frequent
291 * and are likely of not much use for an interactive user.
292 */
293 if (str_starts(start, WPA_EVENT_BSS_ADDED) ||
294 str_starts(start, WPA_EVENT_BSS_REMOVED))
295 return 0;
296
297 return 1;
298 }
299
300
301 static int wpa_cli_open_connection(const char *ifname, int attach)
302 {
303 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
304 ctrl_conn = wpa_ctrl_open(ifname);
305 if (ctrl_conn == NULL)
306 return -1;
307
308 if (attach && interactive)
309 mon_conn = wpa_ctrl_open(ifname);
310 else
311 mon_conn = NULL;
312 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
313 char *cfile = NULL;
314 int flen, res;
315
316 if (ifname == NULL)
317 return -1;
318
319 #ifdef ANDROID
320 if (access(ctrl_iface_dir, F_OK) < 0) {
321 cfile = os_strdup(ifname);
322 if (cfile == NULL)
323 return -1;
324 }
325 #endif /* ANDROID */
326
327 if (cfile == NULL) {
328 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
329 cfile = os_malloc(flen);
330 if (cfile == NULL)
331 return -1;
332 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir,
333 ifname);
334 if (res < 0 || res >= flen) {
335 os_free(cfile);
336 return -1;
337 }
338 }
339
340 ctrl_conn = wpa_ctrl_open(cfile);
341 if (ctrl_conn == NULL) {
342 os_free(cfile);
343 return -1;
344 }
345
346 if (attach && interactive)
347 mon_conn = wpa_ctrl_open(cfile);
348 else
349 mon_conn = NULL;
350 os_free(cfile);
351 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
352
353 if (mon_conn) {
354 if (wpa_ctrl_attach(mon_conn) == 0) {
355 wpa_cli_attached = 1;
356 if (interactive)
357 eloop_register_read_sock(
358 wpa_ctrl_get_fd(mon_conn),
359 wpa_cli_mon_receive, NULL, NULL);
360 } else {
361 printf("Warning: Failed to attach to "
362 "wpa_supplicant.\n");
363 wpa_cli_close_connection();
364 return -1;
365 }
366 }
367
368 return 0;
369 }
370
371
372 static void wpa_cli_close_connection(void)
373 {
374 if (ctrl_conn == NULL)
375 return;
376
377 if (wpa_cli_attached) {
378 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn);
379 wpa_cli_attached = 0;
380 }
381 wpa_ctrl_close(ctrl_conn);
382 ctrl_conn = NULL;
383 if (mon_conn) {
384 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn));
385 wpa_ctrl_close(mon_conn);
386 mon_conn = NULL;
387 }
388 }
389
390
391 static void wpa_cli_msg_cb(char *msg, size_t len)
392 {
393 printf("%s\n", msg);
394 }
395
396
397 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
398 {
399 char buf[4096];
400 size_t len;
401 int ret;
402
403 if (ctrl_conn == NULL) {
404 printf("Not connected to wpa_supplicant - command dropped.\n");
405 return -1;
406 }
407 len = sizeof(buf) - 1;
408 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
409 wpa_cli_msg_cb);
410 if (ret == -2) {
411 printf("'%s' command timed out.\n", cmd);
412 return -2;
413 } else if (ret < 0) {
414 printf("'%s' command failed.\n", cmd);
415 return -1;
416 }
417 if (print) {
418 buf[len] = '\0';
419 printf("%s", buf);
420 if (interactive && len > 0 && buf[len - 1] != '\n')
421 printf("\n");
422 }
423 return 0;
424 }
425
426
427 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
428 {
429 return _wpa_ctrl_command(ctrl, cmd, 1);
430 }
431
432
433 static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc,
434 char *argv[])
435 {
436 int i, res;
437 char *pos, *end;
438
439 pos = buf;
440 end = buf + buflen;
441
442 res = os_snprintf(pos, end - pos, "%s", cmd);
443 if (res < 0 || res >= end - pos)
444 goto fail;
445 pos += res;
446
447 for (i = 0; i < argc; i++) {
448 res = os_snprintf(pos, end - pos, " %s", argv[i]);
449 if (res < 0 || res >= end - pos)
450 goto fail;
451 pos += res;
452 }
453
454 buf[buflen - 1] = '\0';
455 return 0;
456
457 fail:
458 printf("Too long command\n");
459 return -1;
460 }
461
462
463 static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args,
464 int argc, char *argv[])
465 {
466 char buf[4096];
467 if (argc < min_args) {
468 printf("Invalid %s command - at least %d argument%s "
469 "required.\n", cmd, min_args,
470 min_args > 1 ? "s are" : " is");
471 return -1;
472 }
473 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
474 return -1;
475 return wpa_ctrl_command(ctrl, buf);
476 }
477
478
479 static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[])
480 {
481 return wpa_ctrl_command(ctrl, "IFNAME");
482 }
483
484
485 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
486 {
487 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0)
488 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE");
489 if (argc > 0 && os_strcmp(argv[0], "wps") == 0)
490 return wpa_ctrl_command(ctrl, "STATUS-WPS");
491 return wpa_ctrl_command(ctrl, "STATUS");
492 }
493
494
495 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
496 {
497 return wpa_ctrl_command(ctrl, "PING");
498 }
499
500
501 static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
502 {
503 return wpa_ctrl_command(ctrl, "RELOG");
504 }
505
506
507 static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[])
508 {
509 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv);
510 }
511
512
513 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
514 {
515 return wpa_ctrl_command(ctrl, "MIB");
516 }
517
518
519 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
520 {
521 return wpa_ctrl_command(ctrl, "PMKSA");
522 }
523
524
525 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
526 {
527 print_help(argc > 0 ? argv[0] : NULL);
528 return 0;
529 }
530
531
532 static char ** wpa_cli_complete_help(const char *str, int pos)
533 {
534 int arg = get_cmd_arg_num(str, pos);
535 char **res = NULL;
536
537 switch (arg) {
538 case 1:
539 res = wpa_list_cmd_list();
540 break;
541 }
542
543 return res;
544 }
545
546
547 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
548 {
549 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
550 return 0;
551 }
552
553
554 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
555 {
556 wpa_cli_quit = 1;
557 if (interactive)
558 eloop_terminate();
559 return 0;
560 }
561
562
563 static void wpa_cli_show_variables(void)
564 {
565 printf("set variables:\n"
566 " EAPOL::heldPeriod (EAPOL state machine held period, "
567 "in seconds)\n"
568 " EAPOL::authPeriod (EAPOL state machine authentication "
569 "period, in seconds)\n"
570 " EAPOL::startPeriod (EAPOL state machine start period, in "
571 "seconds)\n"
572 " EAPOL::maxStart (EAPOL state machine maximum start "
573 "attempts)\n");
574 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
575 "seconds)\n"
576 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
577 " threshold\n\tpercentage)\n"
578 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
579 "security\n\tassociation in seconds)\n");
580 }
581
582
583 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
584 {
585 char cmd[256];
586 int res;
587
588 if (argc == 0) {
589 wpa_cli_show_variables();
590 return 0;
591 }
592
593 if (argc != 1 && argc != 2) {
594 printf("Invalid SET command: needs two arguments (variable "
595 "name and value)\n");
596 return -1;
597 }
598
599 if (argc == 1)
600 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]);
601 else
602 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s",
603 argv[0], argv[1]);
604 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
605 printf("Too long SET command.\n");
606 return -1;
607 }
608 return wpa_ctrl_command(ctrl, cmd);
609 }
610
611
612 static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
613 {
614 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv);
615 }
616
617
618 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
619 {
620 return wpa_ctrl_command(ctrl, "LOGOFF");
621 }
622
623
624 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
625 {
626 return wpa_ctrl_command(ctrl, "LOGON");
627 }
628
629
630 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
631 char *argv[])
632 {
633 return wpa_ctrl_command(ctrl, "REASSOCIATE");
634 }
635
636
637 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
638 char *argv[])
639 {
640 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv);
641 }
642
643
644 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
645 {
646 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv);
647 }
648
649
650 static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc,
651 char *argv[])
652 {
653 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv);
654 }
655
656
657 static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc,
658 char *argv[])
659 {
660 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv);
661 }
662
663
664 static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc,
665 char *argv[])
666 {
667 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv);
668 }
669
670
671 static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
672 {
673 char cmd[256];
674 int res;
675
676 if (argc < 1)
677 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0");
678 else
679 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]);
680 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
681 printf("Too long BSS_FLUSH command.\n");
682 return -1;
683 }
684 return wpa_ctrl_command(ctrl, cmd);
685 }
686
687
688 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
689 char *argv[])
690 {
691 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv);
692 }
693
694
695 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
696 {
697 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv);
698 }
699
700
701 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
702 {
703 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv);
704 }
705
706
707 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
708 {
709 if (argc == 0) {
710 printf("Invalid WPS_PIN command: need one or two arguments:\n"
711 "- BSSID: use 'any' to select any\n"
712 "- PIN: optional, used only with devices that have no "
713 "display\n");
714 return -1;
715 }
716
717 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv);
718 }
719
720
721 static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
722 char *argv[])
723 {
724 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv);
725 }
726
727
728 static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
729 char *argv[])
730 {
731 return wpa_ctrl_command(ctrl, "WPS_CANCEL");
732 }
733
734
735 #ifdef CONFIG_WPS_NFC
736
737 static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[])
738 {
739 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv);
740 }
741
742
743 static int wpa_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
744 char *argv[])
745 {
746 return wpa_cli_cmd(ctrl, "WPS_NFC_CONFIG_TOKEN", 1, argc, argv);
747 }
748
749
750 static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc,
751 char *argv[])
752 {
753 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv);
754 }
755
756
757 static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
758 char *argv[])
759 {
760 int ret;
761 char *buf;
762 size_t buflen;
763
764 if (argc != 1) {
765 printf("Invalid 'wps_nfc_tag_read' command - one argument "
766 "is required.\n");
767 return -1;
768 }
769
770 buflen = 18 + os_strlen(argv[0]);
771 buf = os_malloc(buflen);
772 if (buf == NULL)
773 return -1;
774 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
775
776 ret = wpa_ctrl_command(ctrl, buf);
777 os_free(buf);
778
779 return ret;
780 }
781
782
783 static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc,
784 char *argv[])
785 {
786 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv);
787 }
788
789
790 static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc,
791 char *argv[])
792 {
793 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv);
794 }
795
796
797 static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc,
798 char *argv[])
799 {
800 int ret;
801 char *buf;
802 size_t buflen;
803
804 if (argc != 1) {
805 printf("Invalid 'nfc_rx_handover_req' command - one argument "
806 "is required.\n");
807 return -1;
808 }
809
810 buflen = 21 + os_strlen(argv[0]);
811 buf = os_malloc(buflen);
812 if (buf == NULL)
813 return -1;
814 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]);
815
816 ret = wpa_ctrl_command(ctrl, buf);
817 os_free(buf);
818
819 return ret;
820 }
821
822
823 static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc,
824 char *argv[])
825 {
826 int ret;
827 char *buf;
828 size_t buflen;
829
830 if (argc != 1) {
831 printf("Invalid 'nfc_rx_handover_sel' command - one argument "
832 "is required.\n");
833 return -1;
834 }
835
836 buflen = 21 + os_strlen(argv[0]);
837 buf = os_malloc(buflen);
838 if (buf == NULL)
839 return -1;
840 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]);
841
842 ret = wpa_ctrl_command(ctrl, buf);
843 os_free(buf);
844
845 return ret;
846 }
847
848
849 static int wpa_cli_cmd_nfc_report_handover(struct wpa_ctrl *ctrl, int argc,
850 char *argv[])
851 {
852 return wpa_cli_cmd(ctrl, "NFC_REPORT_HANDOVER", 4, argc, argv);
853 }
854
855 #endif /* CONFIG_WPS_NFC */
856
857
858 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
859 {
860 char cmd[256];
861 int res;
862
863 if (argc == 2)
864 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
865 argv[0], argv[1]);
866 else if (argc == 5 || argc == 6) {
867 char ssid_hex[2 * 32 + 1];
868 char key_hex[2 * 64 + 1];
869 int i;
870
871 ssid_hex[0] = '\0';
872 for (i = 0; i < 32; i++) {
873 if (argv[2][i] == '\0')
874 break;
875 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
876 }
877
878 key_hex[0] = '\0';
879 if (argc == 6) {
880 for (i = 0; i < 64; i++) {
881 if (argv[5][i] == '\0')
882 break;
883 os_snprintf(&key_hex[i * 2], 3, "%02x",
884 argv[5][i]);
885 }
886 }
887
888 res = os_snprintf(cmd, sizeof(cmd),
889 "WPS_REG %s %s %s %s %s %s",
890 argv[0], argv[1], ssid_hex, argv[3], argv[4],
891 key_hex);
892 } else {
893 printf("Invalid WPS_REG command: need two arguments:\n"
894 "- BSSID of the target AP\n"
895 "- AP PIN\n");
896 printf("Alternatively, six arguments can be used to "
897 "reconfigure the AP:\n"
898 "- BSSID of the target AP\n"
899 "- AP PIN\n"
900 "- new SSID\n"
901 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
902 "- new encr (NONE, WEP, TKIP, CCMP)\n"
903 "- new key\n");
904 return -1;
905 }
906
907 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
908 printf("Too long WPS_REG command.\n");
909 return -1;
910 }
911 return wpa_ctrl_command(ctrl, cmd);
912 }
913
914
915 static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
916 char *argv[])
917 {
918 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv);
919 }
920
921
922 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
923 char *argv[])
924 {
925 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv);
926 }
927
928
929 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
930 char *argv[])
931 {
932 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
933
934 }
935
936
937 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
938 char *argv[])
939 {
940 if (argc < 2) {
941 printf("Invalid WPS_ER_PIN command: need at least two "
942 "arguments:\n"
943 "- UUID: use 'any' to select any\n"
944 "- PIN: Enrollee PIN\n"
945 "optional: - Enrollee MAC address\n");
946 return -1;
947 }
948
949 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv);
950 }
951
952
953 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
954 char *argv[])
955 {
956 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv);
957 }
958
959
960 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
961 char *argv[])
962 {
963 if (argc != 2) {
964 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
965 "- UUID: specify which AP to use\n"
966 "- PIN: AP PIN\n");
967 return -1;
968 }
969
970 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv);
971 }
972
973
974 static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc,
975 char *argv[])
976 {
977 if (argc != 2) {
978 printf("Invalid WPS_ER_SET_CONFIG command: need two "
979 "arguments:\n"
980 "- UUID: specify which AP to use\n"
981 "- Network configuration id\n");
982 return -1;
983 }
984
985 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv);
986 }
987
988
989 static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc,
990 char *argv[])
991 {
992 char cmd[256];
993 int res;
994
995 if (argc == 5 || argc == 6) {
996 char ssid_hex[2 * 32 + 1];
997 char key_hex[2 * 64 + 1];
998 int i;
999
1000 ssid_hex[0] = '\0';
1001 for (i = 0; i < 32; i++) {
1002 if (argv[2][i] == '\0')
1003 break;
1004 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
1005 }
1006
1007 key_hex[0] = '\0';
1008 if (argc == 6) {
1009 for (i = 0; i < 64; i++) {
1010 if (argv[5][i] == '\0')
1011 break;
1012 os_snprintf(&key_hex[i * 2], 3, "%02x",
1013 argv[5][i]);
1014 }
1015 }
1016
1017 res = os_snprintf(cmd, sizeof(cmd),
1018 "WPS_ER_CONFIG %s %s %s %s %s %s",
1019 argv[0], argv[1], ssid_hex, argv[3], argv[4],
1020 key_hex);
1021 } else {
1022 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n"
1023 "- AP UUID\n"
1024 "- AP PIN\n"
1025 "- new SSID\n"
1026 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
1027 "- new encr (NONE, WEP, TKIP, CCMP)\n"
1028 "- new key\n");
1029 return -1;
1030 }
1031
1032 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1033 printf("Too long WPS_ER_CONFIG command.\n");
1034 return -1;
1035 }
1036 return wpa_ctrl_command(ctrl, cmd);
1037 }
1038
1039
1040 #ifdef CONFIG_WPS_NFC
1041 static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc,
1042 char *argv[])
1043 {
1044 if (argc != 2) {
1045 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two "
1046 "arguments:\n"
1047 "- WPS/NDEF: token format\n"
1048 "- UUID: specify which AP to use\n");
1049 return -1;
1050 }
1051
1052 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv);
1053 }
1054 #endif /* CONFIG_WPS_NFC */
1055
1056
1057 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
1058 {
1059 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv);
1060 }
1061
1062
1063 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1064 {
1065 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv);
1066 }
1067
1068
1069 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
1070 {
1071 char cmd[256], *pos, *end;
1072 int i, ret;
1073
1074 if (argc < 2) {
1075 printf("Invalid IDENTITY command: needs two arguments "
1076 "(network id and identity)\n");
1077 return -1;
1078 }
1079
1080 end = cmd + sizeof(cmd);
1081 pos = cmd;
1082 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
1083 argv[0], argv[1]);
1084 if (ret < 0 || ret >= end - pos) {
1085 printf("Too long IDENTITY command.\n");
1086 return -1;
1087 }
1088 pos += ret;
1089 for (i = 2; i < argc; i++) {
1090 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1091 if (ret < 0 || ret >= end - pos) {
1092 printf("Too long IDENTITY command.\n");
1093 return -1;
1094 }
1095 pos += ret;
1096 }
1097
1098 return wpa_ctrl_command(ctrl, cmd);
1099 }
1100
1101
1102 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
1103 {
1104 char cmd[256], *pos, *end;
1105 int i, ret;
1106
1107 if (argc < 2) {
1108 printf("Invalid PASSWORD command: needs two arguments "
1109 "(network id and password)\n");
1110 return -1;
1111 }
1112
1113 end = cmd + sizeof(cmd);
1114 pos = cmd;
1115 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
1116 argv[0], argv[1]);
1117 if (ret < 0 || ret >= end - pos) {
1118 printf("Too long PASSWORD command.\n");
1119 return -1;
1120 }
1121 pos += ret;
1122 for (i = 2; i < argc; i++) {
1123 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1124 if (ret < 0 || ret >= end - pos) {
1125 printf("Too long PASSWORD command.\n");
1126 return -1;
1127 }
1128 pos += ret;
1129 }
1130
1131 return wpa_ctrl_command(ctrl, cmd);
1132 }
1133
1134
1135 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
1136 char *argv[])
1137 {
1138 char cmd[256], *pos, *end;
1139 int i, ret;
1140
1141 if (argc < 2) {
1142 printf("Invalid NEW_PASSWORD command: needs two arguments "
1143 "(network id and password)\n");
1144 return -1;
1145 }
1146
1147 end = cmd + sizeof(cmd);
1148 pos = cmd;
1149 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
1150 argv[0], argv[1]);
1151 if (ret < 0 || ret >= end - pos) {
1152 printf("Too long NEW_PASSWORD command.\n");
1153 return -1;
1154 }
1155 pos += ret;
1156 for (i = 2; i < argc; i++) {
1157 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1158 if (ret < 0 || ret >= end - pos) {
1159 printf("Too long NEW_PASSWORD command.\n");
1160 return -1;
1161 }
1162 pos += ret;
1163 }
1164
1165 return wpa_ctrl_command(ctrl, cmd);
1166 }
1167
1168
1169 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
1170 {
1171 char cmd[256], *pos, *end;
1172 int i, ret;
1173
1174 if (argc < 2) {
1175 printf("Invalid PIN command: needs two arguments "
1176 "(network id and pin)\n");
1177 return -1;
1178 }
1179
1180 end = cmd + sizeof(cmd);
1181 pos = cmd;
1182 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
1183 argv[0], argv[1]);
1184 if (ret < 0 || ret >= end - pos) {
1185 printf("Too long PIN command.\n");
1186 return -1;
1187 }
1188 pos += ret;
1189 for (i = 2; i < argc; i++) {
1190 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1191 if (ret < 0 || ret >= end - pos) {
1192 printf("Too long PIN command.\n");
1193 return -1;
1194 }
1195 pos += ret;
1196 }
1197 return wpa_ctrl_command(ctrl, cmd);
1198 }
1199
1200
1201 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
1202 {
1203 char cmd[256], *pos, *end;
1204 int i, ret;
1205
1206 if (argc < 2) {
1207 printf("Invalid OTP command: needs two arguments (network "
1208 "id and password)\n");
1209 return -1;
1210 }
1211
1212 end = cmd + sizeof(cmd);
1213 pos = cmd;
1214 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
1215 argv[0], argv[1]);
1216 if (ret < 0 || ret >= end - pos) {
1217 printf("Too long OTP command.\n");
1218 return -1;
1219 }
1220 pos += ret;
1221 for (i = 2; i < argc; i++) {
1222 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1223 if (ret < 0 || ret >= end - pos) {
1224 printf("Too long OTP command.\n");
1225 return -1;
1226 }
1227 pos += ret;
1228 }
1229
1230 return wpa_ctrl_command(ctrl, cmd);
1231 }
1232
1233
1234 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
1235 char *argv[])
1236 {
1237 char cmd[256], *pos, *end;
1238 int i, ret;
1239
1240 if (argc < 2) {
1241 printf("Invalid PASSPHRASE command: needs two arguments "
1242 "(network id and passphrase)\n");
1243 return -1;
1244 }
1245
1246 end = cmd + sizeof(cmd);
1247 pos = cmd;
1248 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
1249 argv[0], argv[1]);
1250 if (ret < 0 || ret >= end - pos) {
1251 printf("Too long PASSPHRASE command.\n");
1252 return -1;
1253 }
1254 pos += ret;
1255 for (i = 2; i < argc; i++) {
1256 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
1257 if (ret < 0 || ret >= end - pos) {
1258 printf("Too long PASSPHRASE command.\n");
1259 return -1;
1260 }
1261 pos += ret;
1262 }
1263
1264 return wpa_ctrl_command(ctrl, cmd);
1265 }
1266
1267
1268 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
1269 {
1270 if (argc < 2) {
1271 printf("Invalid BSSID command: needs two arguments (network "
1272 "id and BSSID)\n");
1273 return -1;
1274 }
1275
1276 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv);
1277 }
1278
1279
1280 static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
1281 {
1282 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv);
1283 }
1284
1285
1286 static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
1287 {
1288 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv);
1289 }
1290
1291
1292 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
1293 char *argv[])
1294 {
1295 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
1296 }
1297
1298
1299 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
1300 char *argv[])
1301 {
1302 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv);
1303 }
1304
1305
1306 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
1307 char *argv[])
1308 {
1309 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv);
1310 }
1311
1312
1313 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
1314 char *argv[])
1315 {
1316 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv);
1317 }
1318
1319
1320 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
1321 char *argv[])
1322 {
1323 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
1324 }
1325
1326
1327 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
1328 char *argv[])
1329 {
1330 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv);
1331 }
1332
1333
1334 static void wpa_cli_show_network_variables(void)
1335 {
1336 printf("set_network variables:\n"
1337 " ssid (network name, SSID)\n"
1338 " psk (WPA passphrase or pre-shared key)\n"
1339 " key_mgmt (key management protocol)\n"
1340 " identity (EAP identity)\n"
1341 " password (EAP password)\n"
1342 " ...\n"
1343 "\n"
1344 "Note: Values are entered in the same format as the "
1345 "configuration file is using,\n"
1346 "i.e., strings values need to be inside double quotation "
1347 "marks.\n"
1348 "For example: set_network 1 ssid \"network name\"\n"
1349 "\n"
1350 "Please see wpa_supplicant.conf documentation for full list "
1351 "of\navailable variables.\n");
1352 }
1353
1354
1355 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1356 char *argv[])
1357 {
1358 if (argc == 0) {
1359 wpa_cli_show_network_variables();
1360 return 0;
1361 }
1362
1363 if (argc < 3) {
1364 printf("Invalid SET_NETWORK command: needs three arguments\n"
1365 "(network id, variable name, and value)\n");
1366 return -1;
1367 }
1368
1369 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv);
1370 }
1371
1372
1373 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1374 char *argv[])
1375 {
1376 if (argc == 0) {
1377 wpa_cli_show_network_variables();
1378 return 0;
1379 }
1380
1381 if (argc != 2) {
1382 printf("Invalid GET_NETWORK command: needs two arguments\n"
1383 "(network id and variable name)\n");
1384 return -1;
1385 }
1386
1387 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv);
1388 }
1389
1390
1391 static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc,
1392 char *argv[])
1393 {
1394 return wpa_ctrl_command(ctrl, "LIST_CREDS");
1395 }
1396
1397
1398 static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1399 {
1400 return wpa_ctrl_command(ctrl, "ADD_CRED");
1401 }
1402
1403
1404 static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc,
1405 char *argv[])
1406 {
1407 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv);
1408 }
1409
1410
1411 static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[])
1412 {
1413 if (argc != 3) {
1414 printf("Invalid SET_CRED command: needs three arguments\n"
1415 "(cred id, variable name, and value)\n");
1416 return -1;
1417 }
1418
1419 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv);
1420 }
1421
1422
1423 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1424 char *argv[])
1425 {
1426 return wpa_ctrl_command(ctrl, "DISCONNECT");
1427 }
1428
1429
1430 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1431 char *argv[])
1432 {
1433 return wpa_ctrl_command(ctrl, "RECONNECT");
1434 }
1435
1436
1437 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1438 char *argv[])
1439 {
1440 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1441 }
1442
1443
1444 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1445 {
1446 return wpa_cli_cmd(ctrl, "SCAN", 0, argc, argv);
1447 }
1448
1449
1450 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1451 char *argv[])
1452 {
1453 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1454 }
1455
1456
1457 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1458 {
1459 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv);
1460 }
1461
1462
1463 static char ** wpa_cli_complete_bss(const char *str, int pos)
1464 {
1465 int arg = get_cmd_arg_num(str, pos);
1466 char **res = NULL;
1467
1468 switch (arg) {
1469 case 1:
1470 res = cli_txt_list_array(&bsses);
1471 break;
1472 }
1473
1474 return res;
1475 }
1476
1477
1478 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1479 char *argv[])
1480 {
1481 if (argc < 1 || argc > 2) {
1482 printf("Invalid GET_CAPABILITY command: need either one or "
1483 "two arguments\n");
1484 return -1;
1485 }
1486
1487 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1488 printf("Invalid GET_CAPABILITY command: second argument, "
1489 "if any, must be 'strict'\n");
1490 return -1;
1491 }
1492
1493 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv);
1494 }
1495
1496
1497 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1498 {
1499 printf("Available interfaces:\n");
1500 return wpa_ctrl_command(ctrl, "INTERFACES");
1501 }
1502
1503
1504 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1505 {
1506 if (argc < 1) {
1507 wpa_cli_list_interfaces(ctrl);
1508 return 0;
1509 }
1510
1511 wpa_cli_close_connection();
1512 os_free(ctrl_ifname);
1513 ctrl_ifname = os_strdup(argv[0]);
1514
1515 if (wpa_cli_open_connection(ctrl_ifname, 1)) {
1516 printf("Connected to interface '%s.\n", ctrl_ifname);
1517 } else {
1518 printf("Could not connect to interface '%s' - re-trying\n",
1519 ctrl_ifname);
1520 }
1521 return 0;
1522 }
1523
1524
1525 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1526 char *argv[])
1527 {
1528 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1529 }
1530
1531
1532 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1533 char *argv[])
1534 {
1535 return wpa_ctrl_command(ctrl, "TERMINATE");
1536 }
1537
1538
1539 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1540 char *argv[])
1541 {
1542 char cmd[256];
1543 int res;
1544
1545 if (argc < 1) {
1546 printf("Invalid INTERFACE_ADD command: needs at least one "
1547 "argument (interface name)\n"
1548 "All arguments: ifname confname driver ctrl_interface "
1549 "driver_param bridge_name\n");
1550 return -1;
1551 }
1552
1553 /*
1554 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1555 * <driver_param>TAB<bridge_name>
1556 */
1557 res = os_snprintf(cmd, sizeof(cmd),
1558 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1559 argv[0],
1560 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1561 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1562 argc > 5 ? argv[5] : "");
1563 if (res < 0 || (size_t) res >= sizeof(cmd))
1564 return -1;
1565 cmd[sizeof(cmd) - 1] = '\0';
1566 return wpa_ctrl_command(ctrl, cmd);
1567 }
1568
1569
1570 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1571 char *argv[])
1572 {
1573 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv);
1574 }
1575
1576
1577 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1578 char *argv[])
1579 {
1580 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1581 }
1582
1583
1584 #ifdef CONFIG_AP
1585 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1586 {
1587 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv);
1588 }
1589
1590
1591 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1592 char *addr, size_t addr_len)
1593 {
1594 char buf[4096], *pos;
1595 size_t len;
1596 int ret;
1597
1598 if (ctrl_conn == NULL) {
1599 printf("Not connected to hostapd - command dropped.\n");
1600 return -1;
1601 }
1602 len = sizeof(buf) - 1;
1603 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
1604 wpa_cli_msg_cb);
1605 if (ret == -2) {
1606 printf("'%s' command timed out.\n", cmd);
1607 return -2;
1608 } else if (ret < 0) {
1609 printf("'%s' command failed.\n", cmd);
1610 return -1;
1611 }
1612
1613 buf[len] = '\0';
1614 if (os_memcmp(buf, "FAIL", 4) == 0)
1615 return -1;
1616 printf("%s", buf);
1617
1618 pos = buf;
1619 while (*pos != '\0' && *pos != '\n')
1620 pos++;
1621 *pos = '\0';
1622 os_strlcpy(addr, buf, addr_len);
1623 return 0;
1624 }
1625
1626
1627 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1628 {
1629 char addr[32], cmd[64];
1630
1631 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1632 return 0;
1633 do {
1634 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1635 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1636
1637 return -1;
1638 }
1639
1640
1641 static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
1642 char *argv[])
1643 {
1644 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv);
1645 }
1646
1647
1648 static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
1649 char *argv[])
1650 {
1651 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv);
1652 }
1653 #endif /* CONFIG_AP */
1654
1655
1656 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[])
1657 {
1658 return wpa_ctrl_command(ctrl, "SUSPEND");
1659 }
1660
1661
1662 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[])
1663 {
1664 return wpa_ctrl_command(ctrl, "RESUME");
1665 }
1666
1667
1668 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1669 {
1670 return wpa_ctrl_command(ctrl, "DROP_SA");
1671 }
1672
1673
1674 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[])
1675 {
1676 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv);
1677 }
1678
1679
1680 #ifdef CONFIG_P2P
1681
1682 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[])
1683 {
1684 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv);
1685 }
1686
1687
1688 static char ** wpa_cli_complete_p2p_find(const char *str, int pos)
1689 {
1690 char **res = NULL;
1691 int arg = get_cmd_arg_num(str, pos);
1692
1693 res = os_calloc(6, sizeof(char *));
1694 if (res == NULL)
1695 return NULL;
1696 res[0] = os_strdup("type=social");
1697 if (res[0] == NULL) {
1698 os_free(res);
1699 return NULL;
1700 }
1701 res[1] = os_strdup("type=progressive");
1702 if (res[1] == NULL)
1703 return res;
1704 res[2] = os_strdup("delay=");
1705 if (res[2] == NULL)
1706 return res;
1707 res[3] = os_strdup("dev_id=");
1708 if (res[3] == NULL)
1709 return res;
1710 if (arg == 1)
1711 res[4] = os_strdup("[timeout]");
1712
1713 return res;
1714 }
1715
1716
1717 static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc,
1718 char *argv[])
1719 {
1720 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND");
1721 }
1722
1723
1724 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc,
1725 char *argv[])
1726 {
1727 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv);
1728 }
1729
1730
1731 static char ** wpa_cli_complete_p2p_connect(const char *str, int pos)
1732 {
1733 int arg = get_cmd_arg_num(str, pos);
1734 char **res = NULL;
1735
1736 switch (arg) {
1737 case 1:
1738 res = cli_txt_list_array(&p2p_peers);
1739 break;
1740 }
1741
1742 return res;
1743 }
1744
1745
1746 static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc,
1747 char *argv[])
1748 {
1749 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv);
1750 }
1751
1752
1753 static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc,
1754 char *argv[])
1755 {
1756 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv);
1757 }
1758
1759
1760 static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos)
1761 {
1762 int arg = get_cmd_arg_num(str, pos);
1763 char **res = NULL;
1764
1765 switch (arg) {
1766 case 1:
1767 res = cli_txt_list_array(&p2p_groups);
1768 break;
1769 }
1770
1771 return res;
1772 }
1773
1774
1775 static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc,
1776 char *argv[])
1777 {
1778 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv);
1779 }
1780
1781
1782 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc,
1783 char *argv[])
1784 {
1785 if (argc != 2 && argc != 3) {
1786 printf("Invalid P2P_PROV_DISC command: needs at least "
1787 "two arguments, address and config method\n"
1788 "(display, keypad, or pbc) and an optional join\n");
1789 return -1;
1790 }
1791
1792 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv);
1793 }
1794
1795
1796 static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc,
1797 char *argv[])
1798 {
1799 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE");
1800 }
1801
1802
1803 static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc,
1804 char *argv[])
1805 {
1806 char cmd[4096];
1807
1808 if (argc != 2 && argc != 4) {
1809 printf("Invalid P2P_SERV_DISC_REQ command: needs two "
1810 "arguments (address and TLVs) or four arguments "
1811 "(address, \"upnp\", version, search target "
1812 "(SSDP ST:)\n");
1813 return -1;
1814 }
1815
1816 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0)
1817 return -1;
1818 return wpa_ctrl_command(ctrl, cmd);
1819 }
1820
1821
1822 static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl,
1823 int argc, char *argv[])
1824 {
1825 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv);
1826 }
1827
1828
1829 static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc,
1830 char *argv[])
1831 {
1832 char cmd[4096];
1833 int res;
1834
1835 if (argc != 4) {
1836 printf("Invalid P2P_SERV_DISC_RESP command: needs four "
1837 "arguments (freq, address, dialog token, and TLVs)\n");
1838 return -1;
1839 }
1840
1841 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s",
1842 argv[0], argv[1], argv[2], argv[3]);
1843 if (res < 0 || (size_t) res >= sizeof(cmd))
1844 return -1;
1845 cmd[sizeof(cmd) - 1] = '\0';
1846 return wpa_ctrl_command(ctrl, cmd);
1847 }
1848
1849
1850 static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc,
1851 char *argv[])
1852 {
1853 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE");
1854 }
1855
1856
1857 static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl,
1858 int argc, char *argv[])
1859 {
1860 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv);
1861 }
1862
1863
1864 static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc,
1865 char *argv[])
1866 {
1867 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH");
1868 }
1869
1870
1871 static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc,
1872 char *argv[])
1873 {
1874 char cmd[4096];
1875 int res;
1876
1877 if (argc != 3 && argc != 4) {
1878 printf("Invalid P2P_SERVICE_ADD command: needs three or four "
1879 "arguments\n");
1880 return -1;
1881 }
1882
1883 if (argc == 4)
1884 res = os_snprintf(cmd, sizeof(cmd),
1885 "P2P_SERVICE_ADD %s %s %s %s",
1886 argv[0], argv[1], argv[2], argv[3]);
1887 else
1888 res = os_snprintf(cmd, sizeof(cmd),
1889 "P2P_SERVICE_ADD %s %s %s",
1890 argv[0], argv[1], argv[2]);
1891 if (res < 0 || (size_t) res >= sizeof(cmd))
1892 return -1;
1893 cmd[sizeof(cmd) - 1] = '\0';
1894 return wpa_ctrl_command(ctrl, cmd);
1895 }
1896
1897
1898 static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc,
1899 char *argv[])
1900 {
1901 char cmd[4096];
1902 int res;
1903
1904 if (argc != 2 && argc != 3) {
1905 printf("Invalid P2P_SERVICE_DEL command: needs two or three "
1906 "arguments\n");
1907 return -1;
1908 }
1909
1910 if (argc == 3)
1911 res = os_snprintf(cmd, sizeof(cmd),
1912 "P2P_SERVICE_DEL %s %s %s",
1913 argv[0], argv[1], argv[2]);
1914 else
1915 res = os_snprintf(cmd, sizeof(cmd),
1916 "P2P_SERVICE_DEL %s %s",
1917 argv[0], argv[1]);
1918 if (res < 0 || (size_t) res >= sizeof(cmd))
1919 return -1;
1920 cmd[sizeof(cmd) - 1] = '\0';
1921 return wpa_ctrl_command(ctrl, cmd);
1922 }
1923
1924
1925 static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl,
1926 int argc, char *argv[])
1927 {
1928 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv);
1929 }
1930
1931
1932 static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl,
1933 int argc, char *argv[])
1934 {
1935 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv);
1936 }
1937
1938
1939 static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[])
1940 {
1941 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv);
1942 }
1943
1944
1945 static char ** wpa_cli_complete_p2p_peer(const char *str, int pos)
1946 {
1947 int arg = get_cmd_arg_num(str, pos);
1948 char **res = NULL;
1949
1950 switch (arg) {
1951 case 1:
1952 res = cli_txt_list_array(&p2p_peers);
1953 break;
1954 }
1955
1956 return res;
1957 }
1958
1959
1960 static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd,
1961 char *addr, size_t addr_len,
1962 int discovered)
1963 {
1964 char buf[4096], *pos;
1965 size_t len;
1966 int ret;
1967
1968 if (ctrl_conn == NULL)
1969 return -1;
1970 len = sizeof(buf) - 1;
1971 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
1972 wpa_cli_msg_cb);
1973 if (ret == -2) {
1974 printf("'%s' command timed out.\n", cmd);
1975 return -2;
1976 } else if (ret < 0) {
1977 printf("'%s' command failed.\n", cmd);
1978 return -1;
1979 }
1980
1981 buf[len] = '\0';
1982 if (os_memcmp(buf, "FAIL", 4) == 0)
1983 return -1;
1984
1985 pos = buf;
1986 while (*pos != '\0' && *pos != '\n')
1987 pos++;
1988 *pos++ = '\0';
1989 os_strlcpy(addr, buf, addr_len);
1990 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL)
1991 printf("%s\n", addr);
1992 return 0;
1993 }
1994
1995
1996 static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[])
1997 {
1998 char addr[32], cmd[64];
1999 int discovered;
2000
2001 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0;
2002
2003 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST",
2004 addr, sizeof(addr), discovered))
2005 return -1;
2006 do {
2007 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr);
2008 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr),
2009 discovered) == 0);
2010
2011 return 0;
2012 }
2013
2014
2015 static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
2016 {
2017 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv);
2018 }
2019
2020
2021 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2022 {
2023 return wpa_ctrl_command(ctrl, "P2P_FLUSH");
2024 }
2025
2026
2027 static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc,
2028 char *argv[])
2029 {
2030 return wpa_ctrl_command(ctrl, "P2P_CANCEL");
2031 }
2032
2033
2034 static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc,
2035 char *argv[])
2036 {
2037 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv);
2038 }
2039
2040
2041 static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc,
2042 char *argv[])
2043 {
2044 if (argc != 0 && argc != 2 && argc != 4) {
2045 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments "
2046 "(preferred duration, interval; in microsecods).\n"
2047 "Optional second pair can be used to provide "
2048 "acceptable values.\n");
2049 return -1;
2050 }
2051
2052 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv);
2053 }
2054
2055
2056 static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc,
2057 char *argv[])
2058 {
2059 if (argc != 0 && argc != 2) {
2060 printf("Invalid P2P_EXT_LISTEN command: needs two arguments "
2061 "(availability period, availability interval; in "
2062 "millisecods).\n"
2063 "Extended Listen Timing can be cancelled with this "
2064 "command when used without parameters.\n");
2065 return -1;
2066 }
2067
2068 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv);
2069 }
2070
2071 #endif /* CONFIG_P2P */
2072
2073 #ifdef CONFIG_WIFI_DISPLAY
2074
2075 static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc,
2076 char *argv[])
2077 {
2078 char cmd[100];
2079 int res;
2080
2081 if (argc != 1 && argc != 2) {
2082 printf("Invalid WFD_SUBELEM_SET command: needs one or two "
2083 "arguments (subelem, hexdump)\n");
2084 return -1;
2085 }
2086
2087 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s",
2088 argv[0], argc > 1 ? argv[1] : "");
2089 if (res < 0 || (size_t) res >= sizeof(cmd))
2090 return -1;
2091 cmd[sizeof(cmd) - 1] = '\0';
2092 return wpa_ctrl_command(ctrl, cmd);
2093 }
2094
2095
2096 static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc,
2097 char *argv[])
2098 {
2099 char cmd[100];
2100 int res;
2101
2102 if (argc != 1) {
2103 printf("Invalid WFD_SUBELEM_GET command: needs one "
2104 "argument (subelem)\n");
2105 return -1;
2106 }
2107
2108 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s",
2109 argv[0]);
2110 if (res < 0 || (size_t) res >= sizeof(cmd))
2111 return -1;
2112 cmd[sizeof(cmd) - 1] = '\0';
2113 return wpa_ctrl_command(ctrl, cmd);
2114 }
2115 #endif /* CONFIG_WIFI_DISPLAY */
2116
2117
2118 #ifdef CONFIG_INTERWORKING
2119 static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2120 char *argv[])
2121 {
2122 return wpa_ctrl_command(ctrl, "FETCH_ANQP");
2123 }
2124
2125
2126 static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc,
2127 char *argv[])
2128 {
2129 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP");
2130 }
2131
2132
2133 static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc,
2134 char *argv[])
2135 {
2136 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv);
2137 }
2138
2139
2140 static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc,
2141 char *argv[])
2142 {
2143 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv);
2144 }
2145
2146
2147 static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
2148 {
2149 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv);
2150 }
2151
2152
2153 static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc,
2154 char *argv[])
2155 {
2156 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv);
2157 }
2158
2159
2160 static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc,
2161 char *argv[])
2162 {
2163 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv);
2164 }
2165 #endif /* CONFIG_INTERWORKING */
2166
2167
2168 #ifdef CONFIG_HS20
2169
2170 static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc,
2171 char *argv[])
2172 {
2173 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv);
2174 }
2175
2176
2177 static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc,
2178 char *argv[])
2179 {
2180 char cmd[512];
2181
2182 if (argc == 0) {
2183 printf("Command needs one or two arguments (dst mac addr and "
2184 "optional home realm)\n");
2185 return -1;
2186 }
2187
2188 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST",
2189 argc, argv) < 0)
2190 return -1;
2191
2192 return wpa_ctrl_command(ctrl, cmd);
2193 }
2194
2195 #endif /* CONFIG_HS20 */
2196
2197
2198 static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc,
2199 char *argv[])
2200 {
2201 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv);
2202 }
2203
2204
2205 static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc,
2206 char *argv[])
2207 {
2208 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv);
2209 }
2210
2211
2212 static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc,
2213 char *argv[])
2214 {
2215 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv);
2216 }
2217
2218
2219 static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc,
2220 char *argv[])
2221 {
2222 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv);
2223 }
2224
2225
2226 static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc,
2227 char *argv[])
2228 {
2229 return wpa_ctrl_command(ctrl, "SIGNAL_POLL");
2230 }
2231
2232
2233 static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc,
2234 char *argv[])
2235 {
2236 return wpa_ctrl_command(ctrl, "PKTCNT_POLL");
2237 }
2238
2239
2240 static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc,
2241 char *argv[])
2242 {
2243 return wpa_ctrl_command(ctrl, "REAUTHENTICATE");
2244 }
2245
2246
2247 #ifdef CONFIG_AUTOSCAN
2248
2249 static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[])
2250 {
2251 if (argc == 0)
2252 return wpa_ctrl_command(ctrl, "AUTOSCAN ");
2253
2254 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv);
2255 }
2256
2257 #endif /* CONFIG_AUTOSCAN */
2258
2259
2260 #ifdef CONFIG_WNM
2261
2262 static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[])
2263 {
2264 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv);
2265 }
2266
2267 #endif /* CONFIG_WNM */
2268
2269
2270 static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
2271 {
2272 if (argc == 0)
2273 return -1;
2274 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
2275 }
2276
2277
2278 static int wpa_cli_cmd_flush(struct wpa_ctrl *ctrl, int argc, char *argv[])
2279 {
2280 return wpa_ctrl_command(ctrl, "FLUSH");
2281 }
2282
2283
2284 enum wpa_cli_cmd_flags {
2285 cli_cmd_flag_none = 0x00,
2286 cli_cmd_flag_sensitive = 0x01
2287 };
2288
2289 struct wpa_cli_cmd {
2290 const char *cmd;
2291 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
2292 char ** (*completion)(const char *str, int pos);
2293 enum wpa_cli_cmd_flags flags;
2294 const char *usage;
2295 };
2296
2297 static struct wpa_cli_cmd wpa_cli_commands[] = {
2298 { "status", wpa_cli_cmd_status, NULL,
2299 cli_cmd_flag_none,
2300 "[verbose] = get current WPA/EAPOL/EAP status" },
2301 { "ifname", wpa_cli_cmd_ifname, NULL,
2302 cli_cmd_flag_none,
2303 "= get current interface name" },
2304 { "ping", wpa_cli_cmd_ping, NULL,
2305 cli_cmd_flag_none,
2306 "= pings wpa_supplicant" },
2307 { "relog", wpa_cli_cmd_relog, NULL,
2308 cli_cmd_flag_none,
2309 "= re-open log-file (allow rolling logs)" },
2310 { "note", wpa_cli_cmd_note, NULL,
2311 cli_cmd_flag_none,
2312 "<text> = add a note to wpa_supplicant debug log" },
2313 { "mib", wpa_cli_cmd_mib, NULL,
2314 cli_cmd_flag_none,
2315 "= get MIB variables (dot1x, dot11)" },
2316 { "help", wpa_cli_cmd_help, wpa_cli_complete_help,
2317 cli_cmd_flag_none,
2318 "[command] = show usage help" },
2319 { "interface", wpa_cli_cmd_interface, NULL,
2320 cli_cmd_flag_none,
2321 "[ifname] = show interfaces/select interface" },
2322 { "level", wpa_cli_cmd_level, NULL,
2323 cli_cmd_flag_none,
2324 "<debug level> = change debug level" },
2325 { "license", wpa_cli_cmd_license, NULL,
2326 cli_cmd_flag_none,
2327 "= show full wpa_cli license" },
2328 { "quit", wpa_cli_cmd_quit, NULL,
2329 cli_cmd_flag_none,
2330 "= exit wpa_cli" },
2331 { "set", wpa_cli_cmd_set, NULL,
2332 cli_cmd_flag_none,
2333 "= set variables (shows list of variables when run without "
2334 "arguments)" },
2335 { "get", wpa_cli_cmd_get, NULL,
2336 cli_cmd_flag_none,
2337 "<name> = get information" },
2338 { "logon", wpa_cli_cmd_logon, NULL,
2339 cli_cmd_flag_none,
2340 "= IEEE 802.1X EAPOL state machine logon" },
2341 { "logoff", wpa_cli_cmd_logoff, NULL,
2342 cli_cmd_flag_none,
2343 "= IEEE 802.1X EAPOL state machine logoff" },
2344 { "pmksa", wpa_cli_cmd_pmksa, NULL,
2345 cli_cmd_flag_none,
2346 "= show PMKSA cache" },
2347 { "reassociate", wpa_cli_cmd_reassociate, NULL,
2348 cli_cmd_flag_none,
2349 "= force reassociation" },
2350 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss,
2351 cli_cmd_flag_none,
2352 "<BSSID> = force preauthentication" },
2353 { "identity", wpa_cli_cmd_identity, NULL,
2354 cli_cmd_flag_none,
2355 "<network id> <identity> = configure identity for an SSID" },
2356 { "password", wpa_cli_cmd_password, NULL,
2357 cli_cmd_flag_sensitive,
2358 "<network id> <password> = configure password for an SSID" },
2359 { "new_password", wpa_cli_cmd_new_password, NULL,
2360 cli_cmd_flag_sensitive,
2361 "<network id> <password> = change password for an SSID" },
2362 { "pin", wpa_cli_cmd_pin, NULL,
2363 cli_cmd_flag_sensitive,
2364 "<network id> <pin> = configure pin for an SSID" },
2365 { "otp", wpa_cli_cmd_otp, NULL,
2366 cli_cmd_flag_sensitive,
2367 "<network id> <password> = configure one-time-password for an SSID"
2368 },
2369 { "passphrase", wpa_cli_cmd_passphrase, NULL,
2370 cli_cmd_flag_sensitive,
2371 "<network id> <passphrase> = configure private key passphrase\n"
2372 " for an SSID" },
2373 { "bssid", wpa_cli_cmd_bssid, NULL,
2374 cli_cmd_flag_none,
2375 "<network id> <BSSID> = set preferred BSSID for an SSID" },
2376 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss,
2377 cli_cmd_flag_none,
2378 "<BSSID> = add a BSSID to the blacklist\n"
2379 "blacklist clear = clear the blacklist\n"
2380 "blacklist = display the blacklist" },
2381 { "log_level", wpa_cli_cmd_log_level, NULL,
2382 cli_cmd_flag_none,
2383 "<level> [<timestamp>] = update the log level/timestamp\n"
2384 "log_level = display the current log level and log options" },
2385 { "list_networks", wpa_cli_cmd_list_networks, NULL,
2386 cli_cmd_flag_none,
2387 "= list configured networks" },
2388 { "select_network", wpa_cli_cmd_select_network, NULL,
2389 cli_cmd_flag_none,
2390 "<network id> = select a network (disable others)" },
2391 { "enable_network", wpa_cli_cmd_enable_network, NULL,
2392 cli_cmd_flag_none,
2393 "<network id> = enable a network" },
2394 { "disable_network", wpa_cli_cmd_disable_network, NULL,
2395 cli_cmd_flag_none,
2396 "<network id> = disable a network" },
2397 { "add_network", wpa_cli_cmd_add_network, NULL,
2398 cli_cmd_flag_none,
2399 "= add a network" },
2400 { "remove_network", wpa_cli_cmd_remove_network, NULL,
2401 cli_cmd_flag_none,
2402 "<network id> = remove a network" },
2403 { "set_network", wpa_cli_cmd_set_network, NULL,
2404 cli_cmd_flag_sensitive,
2405 "<network id> <variable> <value> = set network variables (shows\n"
2406 " list of variables when run without arguments)" },
2407 { "get_network", wpa_cli_cmd_get_network, NULL,
2408 cli_cmd_flag_none,
2409 "<network id> <variable> = get network variables" },
2410 { "list_creds", wpa_cli_cmd_list_creds, NULL,
2411 cli_cmd_flag_none,
2412 "= list configured credentials" },
2413 { "add_cred", wpa_cli_cmd_add_cred, NULL,
2414 cli_cmd_flag_none,
2415 "= add a credential" },
2416 { "remove_cred", wpa_cli_cmd_remove_cred, NULL,
2417 cli_cmd_flag_none,
2418 "<cred id> = remove a credential" },
2419 { "set_cred", wpa_cli_cmd_set_cred, NULL,
2420 cli_cmd_flag_sensitive,
2421 "<cred id> <variable> <value> = set credential variables" },
2422 { "save_config", wpa_cli_cmd_save_config, NULL,
2423 cli_cmd_flag_none,
2424 "= save the current configuration" },
2425 { "disconnect", wpa_cli_cmd_disconnect, NULL,
2426 cli_cmd_flag_none,
2427 "= disconnect and wait for reassociate/reconnect command before\n"
2428 " connecting" },
2429 { "reconnect", wpa_cli_cmd_reconnect, NULL,
2430 cli_cmd_flag_none,
2431 "= like reassociate, but only takes effect if already disconnected"
2432 },
2433 { "scan", wpa_cli_cmd_scan, NULL,
2434 cli_cmd_flag_none,
2435 "= request new BSS scan" },
2436 { "scan_results", wpa_cli_cmd_scan_results, NULL,
2437 cli_cmd_flag_none,
2438 "= get latest scan results" },
2439 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss,
2440 cli_cmd_flag_none,
2441 "<<idx> | <bssid>> = get detailed scan result info" },
2442 { "get_capability", wpa_cli_cmd_get_capability, NULL,
2443 cli_cmd_flag_none,
2444 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels/freq/modes> "
2445 "= get capabilies" },
2446 { "reconfigure", wpa_cli_cmd_reconfigure, NULL,
2447 cli_cmd_flag_none,
2448 "= force wpa_supplicant to re-read its configuration file" },
2449 { "terminate", wpa_cli_cmd_terminate, NULL,
2450 cli_cmd_flag_none,
2451 "= terminate wpa_supplicant" },
2452 { "interface_add", wpa_cli_cmd_interface_add, NULL,
2453 cli_cmd_flag_none,
2454 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
2455 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
2456 " are optional" },
2457 { "interface_remove", wpa_cli_cmd_interface_remove, NULL,
2458 cli_cmd_flag_none,
2459 "<ifname> = removes the interface" },
2460 { "interface_list", wpa_cli_cmd_interface_list, NULL,
2461 cli_cmd_flag_none,
2462 "= list available interfaces" },
2463 { "ap_scan", wpa_cli_cmd_ap_scan, NULL,
2464 cli_cmd_flag_none,
2465 "<value> = set ap_scan parameter" },
2466 { "scan_interval", wpa_cli_cmd_scan_interval, NULL,
2467 cli_cmd_flag_none,
2468 "<value> = set scan_interval parameter (in seconds)" },
2469 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL,
2470 cli_cmd_flag_none,
2471 "<value> = set BSS expiration age parameter" },
2472 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL,
2473 cli_cmd_flag_none,
2474 "<value> = set BSS expiration scan count parameter" },
2475 { "bss_flush", wpa_cli_cmd_bss_flush, NULL,
2476 cli_cmd_flag_none,
2477 "<value> = set BSS flush age (0 by default)" },
2478 { "stkstart", wpa_cli_cmd_stkstart, NULL,
2479 cli_cmd_flag_none,
2480 "<addr> = request STK negotiation with <addr>" },
2481 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss,
2482 cli_cmd_flag_none,
2483 "<addr> = request over-the-DS FT with <addr>" },
2484 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss,
2485 cli_cmd_flag_none,
2486 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
2487 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss,
2488 cli_cmd_flag_sensitive,
2489 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
2490 "hardcoded)" },
2491 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL,
2492 cli_cmd_flag_sensitive,
2493 "<PIN> = verify PIN checksum" },
2494 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none,
2495 "Cancels the pending WPS operation" },
2496 #ifdef CONFIG_WPS_NFC
2497 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss,
2498 cli_cmd_flag_none,
2499 "[BSSID] = start Wi-Fi Protected Setup: NFC" },
2500 { "wps_nfc_config_token", wpa_cli_cmd_wps_nfc_config_token, NULL,
2501 cli_cmd_flag_none,
2502 "<WPS|NDEF> = build configuration token" },
2503 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL,
2504 cli_cmd_flag_none,
2505 "<WPS|NDEF> = create password token" },
2506 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL,
2507 cli_cmd_flag_sensitive,
2508 "<hexdump of payload> = report read NFC tag with WPS data" },
2509 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL,
2510 cli_cmd_flag_none,
2511 "<NDEF> <WPS> = create NFC handover request" },
2512 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL,
2513 cli_cmd_flag_none,
2514 "<NDEF> <WPS> = create NFC handover select" },
2515 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL,
2516 cli_cmd_flag_none,
2517 "<hexdump of payload> = report received NFC handover request" },
2518 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL,
2519 cli_cmd_flag_none,
2520 "<hexdump of payload> = report received NFC handover select" },
2521 { "nfc_report_handover", wpa_cli_cmd_nfc_report_handover, NULL,
2522 cli_cmd_flag_none,
2523 "<role> <type> <hexdump of req> <hexdump of sel> = report completed "
2524 "NFC handover" },
2525 #endif /* CONFIG_WPS_NFC */
2526 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss,
2527 cli_cmd_flag_sensitive,
2528 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
2529 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL,
2530 cli_cmd_flag_sensitive,
2531 "[params..] = enable/disable AP PIN" },
2532 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL,
2533 cli_cmd_flag_none,
2534 "[IP address] = start Wi-Fi Protected Setup External Registrar" },
2535 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL,
2536 cli_cmd_flag_none,
2537 "= stop Wi-Fi Protected Setup External Registrar" },
2538 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL,
2539 cli_cmd_flag_sensitive,
2540 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
2541 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL,
2542 cli_cmd_flag_none,
2543 "<UUID> = accept an Enrollee PBC using External Registrar" },
2544 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL,
2545 cli_cmd_flag_sensitive,
2546 "<UUID> <PIN> = learn AP configuration" },
2547 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL,
2548 cli_cmd_flag_none,
2549 "<UUID> <network id> = set AP configuration for enrolling" },
2550 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL,
2551 cli_cmd_flag_sensitive,
2552 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" },
2553 #ifdef CONFIG_WPS_NFC
2554 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL,
2555 cli_cmd_flag_none,
2556 "<WPS/NDEF> <UUID> = build NFC configuration token" },
2557 #endif /* CONFIG_WPS_NFC */
2558 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL,
2559 cli_cmd_flag_none,
2560 "<addr> = request RSN authentication with <addr> in IBSS" },
2561 #ifdef CONFIG_AP
2562 { "sta", wpa_cli_cmd_sta, NULL,
2563 cli_cmd_flag_none,
2564 "<addr> = get information about an associated station (AP)" },
2565 { "all_sta", wpa_cli_cmd_all_sta, NULL,
2566 cli_cmd_flag_none,
2567 "= get information about all associated stations (AP)" },
2568 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL,
2569 cli_cmd_flag_none,
2570 "<addr> = deauthenticate a station" },
2571 { "disassociate", wpa_cli_cmd_disassociate, NULL,
2572 cli_cmd_flag_none,
2573 "<addr> = disassociate a station" },
2574 #endif /* CONFIG_AP */
2575 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none,
2576 "= notification of suspend/hibernate" },
2577 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none,
2578 "= notification of resume/thaw" },
2579 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none,
2580 "= drop SA without deauth/disassoc (test command)" },
2581 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss,
2582 cli_cmd_flag_none,
2583 "<addr> = roam to the specified BSS" },
2584 #ifdef CONFIG_P2P
2585 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find,
2586 cli_cmd_flag_none,
2587 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" },
2588 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none,
2589 "= stop P2P Devices search" },
2590 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect,
2591 cli_cmd_flag_none,
2592 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" },
2593 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none,
2594 "[timeout] = listen for P2P Devices for up-to timeout seconds" },
2595 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove,
2596 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none,
2597 "<ifname> = remove P2P group interface (terminate group if GO)" },
2598 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none,
2599 "[ht40] = add a new P2P group (local end as GO)" },
2600 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc,
2601 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2602 "<addr> <method> = request provisioning discovery" },
2603 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL,
2604 cli_cmd_flag_none,
2605 "= get the passphrase for a group (GO only)" },
2606 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req,
2607 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2608 "<addr> <TLVs> = schedule service discovery request" },
2609 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req,
2610 NULL, cli_cmd_flag_none,
2611 "<id> = cancel pending service discovery request" },
2612 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL,
2613 cli_cmd_flag_none,
2614 "<freq> <addr> <dialog token> <TLVs> = service discovery response" },
2615 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL,
2616 cli_cmd_flag_none,
2617 "= indicate change in local services" },
2618 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL,
2619 cli_cmd_flag_none,
2620 "<external> = set external processing of service discovery" },
2621 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL,
2622 cli_cmd_flag_none,
2623 "= remove all stored service entries" },
2624 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL,
2625 cli_cmd_flag_none,
2626 "<bonjour|upnp> <query|version> <response|service> = add a local "
2627 "service" },
2628 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL,
2629 cli_cmd_flag_none,
2630 "<bonjour|upnp> <query|version> [|service] = remove a local "
2631 "service" },
2632 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer,
2633 cli_cmd_flag_none,
2634 "<addr> = reject connection attempts from a specific peer" },
2635 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL,
2636 cli_cmd_flag_none,
2637 "<cmd> [peer=addr] = invite peer" },
2638 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none,
2639 "[discovered] = list known (optionally, only fully discovered) P2P "
2640 "peers" },
2641 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer,
2642 cli_cmd_flag_none,
2643 "<address> = show information about known P2P peer" },
2644 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none,
2645 "<field> <value> = set a P2P parameter" },
2646 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none,
2647 "= flush P2P state" },
2648 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none,
2649 "= cancel P2P group formation" },
2650 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize,
2651 wpa_cli_complete_p2p_peer, cli_cmd_flag_none,
2652 "<address> = unauthorize a peer" },
2653 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL,
2654 cli_cmd_flag_none,
2655 "[<duration> <interval>] [<duration> <interval>] = request GO "
2656 "presence" },
2657 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL,
2658 cli_cmd_flag_none,
2659 "[<period> <interval>] = set extended listen timing" },
2660 #endif /* CONFIG_P2P */
2661 #ifdef CONFIG_WIFI_DISPLAY
2662 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL,
2663 cli_cmd_flag_none,
2664 "<subelem> [contents] = set Wi-Fi Display subelement" },
2665 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL,
2666 cli_cmd_flag_none,
2667 "<subelem> = get Wi-Fi Display subelement" },
2668 #endif /* CONFIG_WIFI_DISPLAY */
2669 #ifdef CONFIG_INTERWORKING
2670 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none,
2671 "= fetch ANQP information for all APs" },
2672 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL,
2673 cli_cmd_flag_none,
2674 "= stop fetch_anqp operation" },
2675 { "interworking_select", wpa_cli_cmd_interworking_select, NULL,
2676 cli_cmd_flag_none,
2677 "[auto] = perform Interworking network selection" },
2678 { "interworking_connect", wpa_cli_cmd_interworking_connect,
2679 wpa_cli_complete_bss, cli_cmd_flag_none,
2680 "<BSSID> = connect using Interworking credentials" },
2681 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss,
2682 cli_cmd_flag_none,
2683 "<addr> <info id>[,<info id>]... = request ANQP information" },
2684 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss,
2685 cli_cmd_flag_none,
2686 "<addr> <AdvProtoID> [QueryReq] = GAS request" },
2687 { "gas_response_get", wpa_cli_cmd_gas_response_get,
2688 wpa_cli_complete_bss, cli_cmd_flag_none,
2689 "<addr> <dialog token> [start,len] = Fetch last GAS response" },
2690 #endif /* CONFIG_INTERWORKING */
2691 #ifdef CONFIG_HS20
2692 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss,
2693 cli_cmd_flag_none,
2694 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information"
2695 },
2696 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list,
2697 wpa_cli_complete_bss, cli_cmd_flag_none,
2698 "<addr> <home realm> = get HS20 nai home realm list" },
2699 #endif /* CONFIG_HS20 */
2700 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL,
2701 cli_cmd_flag_none,
2702 "<0/1> = disable/enable automatic reconnection" },
2703 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL,
2704 cli_cmd_flag_none,
2705 "<addr> = request TDLS discovery with <addr>" },
2706 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL,
2707 cli_cmd_flag_none,
2708 "<addr> = request TDLS setup with <addr>" },
2709 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL,
2710 cli_cmd_flag_none,
2711 "<addr> = tear down TDLS with <addr>" },
2712 { "signal_poll", wpa_cli_cmd_signal_poll, NULL,
2713 cli_cmd_flag_none,
2714 "= get signal parameters" },
2715 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL,
2716 cli_cmd_flag_none,
2717 "= get TX/RX packet counters" },
2718 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL,
2719 cli_cmd_flag_none,
2720 "= trigger IEEE 802.1X/EAPOL reauthentication" },
2721 #ifdef CONFIG_AUTOSCAN
2722 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none,
2723 "[params] = Set or unset (if none) autoscan parameters" },
2724 #endif /* CONFIG_AUTOSCAN */
2725 #ifdef CONFIG_WNM
2726 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none,
2727 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" },
2728 #endif /* CONFIG_WNM */
2729 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive,
2730 "<params..> = Sent unprocessed command" },
2731 { "flush", wpa_cli_cmd_flush, NULL, cli_cmd_flag_none,
2732 "= flush wpa_supplicant state" },
2733 { NULL, NULL, NULL, cli_cmd_flag_none, NULL }
2734 };
2735
2736
2737 /*
2738 * Prints command usage, lines are padded with the specified string.
2739 */
2740 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
2741 {
2742 char c;
2743 size_t n;
2744
2745 printf("%s%s ", pad, cmd->cmd);
2746 for (n = 0; (c = cmd->usage[n]); n++) {
2747 printf("%c", c);
2748 if (c == '\n')
2749 printf("%s", pad);
2750 }
2751 printf("\n");
2752 }
2753
2754
2755 static void print_help(const char *cmd)
2756 {
2757 int n;
2758 printf("commands:\n");
2759 for (n = 0; wpa_cli_commands[n].cmd; n++) {
2760 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd))
2761 print_cmd_help(&wpa_cli_commands[n], " ");
2762 }
2763 }
2764
2765
2766 static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd)
2767 {
2768 const char *c, *delim;
2769 int n;
2770 size_t len;
2771
2772 delim = os_strchr(cmd, ' ');
2773 if (delim)
2774 len = delim - cmd;
2775 else
2776 len = os_strlen(cmd);
2777
2778 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
2779 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
2780 return (wpa_cli_commands[n].flags &
2781 cli_cmd_flag_sensitive);
2782 }
2783 return 0;
2784 }
2785
2786
2787 static char ** wpa_list_cmd_list(void)
2788 {
2789 char **res;
2790 int i, count;
2791
2792 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]);
2793 res = os_calloc(count, sizeof(char *));
2794 if (res == NULL)
2795 return NULL;
2796
2797 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2798 res[i] = os_strdup(wpa_cli_commands[i].cmd);
2799 if (res[i] == NULL)
2800 break;
2801 }
2802
2803 return res;
2804 }
2805
2806
2807 static char ** wpa_cli_cmd_completion(const char *cmd, const char *str,
2808 int pos)
2809 {
2810 int i;
2811
2812 for (i = 0; wpa_cli_commands[i].cmd; i++) {
2813 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) {
2814 if (wpa_cli_commands[i].completion)
2815 return wpa_cli_commands[i].completion(str,
2816 pos);
2817 edit_clear_line();
2818 printf("\r%s\n", wpa_cli_commands[i].usage);
2819 edit_redraw();
2820 break;
2821 }
2822 }
2823
2824 return NULL;
2825 }
2826
2827
2828 static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos)
2829 {
2830 char **res;
2831 const char *end;
2832 char *cmd;
2833
2834 end = os_strchr(str, ' ');
2835 if (end == NULL || str + pos < end)
2836 return wpa_list_cmd_list();
2837
2838 cmd = os_malloc(pos + 1);
2839 if (cmd == NULL)
2840 return NULL;
2841 os_memcpy(cmd, str, pos);
2842 cmd[end - str] = '\0';
2843 res = wpa_cli_cmd_completion(cmd, str, pos);
2844 os_free(cmd);
2845 return res;
2846 }
2847
2848
2849 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
2850 {
2851 struct wpa_cli_cmd *cmd, *match = NULL;
2852 int count;
2853 int ret = 0;
2854
2855 count = 0;
2856 cmd = wpa_cli_commands;
2857 while (cmd->cmd) {
2858 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
2859 {
2860 match = cmd;
2861 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
2862 /* we have an exact match */
2863 count = 1;
2864 break;
2865 }
2866 count++;
2867 }
2868 cmd++;
2869 }
2870
2871 if (count > 1) {
2872 printf("Ambiguous command '%s'; possible commands:", argv[0]);
2873 cmd = wpa_cli_commands;
2874 while (cmd->cmd) {
2875 if (os_strncasecmp(cmd->cmd, argv[0],
2876 os_strlen(argv[0])) == 0) {
2877 printf(" %s", cmd->cmd);
2878 }
2879 cmd++;
2880 }
2881 printf("\n");
2882 ret = 1;
2883 } else if (count == 0) {
2884 printf("Unknown command '%s'\n", argv[0]);
2885 ret = 1;
2886 } else {
2887 ret = match->handler(ctrl, argc - 1, &argv[1]);
2888 }
2889
2890 return ret;
2891 }
2892
2893
2894 static int str_match(const char *a, const char *b)
2895 {
2896 return os_strncmp(a, b, os_strlen(b)) == 0;
2897 }
2898
2899
2900 static int wpa_cli_exec(const char *program, const char *arg1,
2901 const char *arg2)
2902 {
2903 char *cmd;
2904 size_t len;
2905 int res;
2906 int ret = 0;
2907
2908 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
2909 cmd = os_malloc(len);
2910 if (cmd == NULL)
2911 return -1;
2912 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
2913 if (res < 0 || (size_t) res >= len) {
2914 os_free(cmd);
2915 return -1;
2916 }
2917 cmd[len - 1] = '\0';
2918 #ifndef _WIN32_WCE
2919 if (system(cmd) < 0)
2920 ret = -1;
2921 #endif /* _WIN32_WCE */
2922 os_free(cmd);
2923
2924 return ret;
2925 }
2926
2927
2928 static void wpa_cli_action_process(const char *msg)
2929 {
2930 const char *pos;
2931 char *copy = NULL, *id, *pos2;
2932
2933 pos = msg;
2934 if (*pos == '<') {
2935 /* skip priority */
2936 pos = os_strchr(pos, '>');
2937 if (pos)
2938 pos++;
2939 else
2940 pos = msg;
2941 }
2942
2943 if (str_match(pos, WPA_EVENT_CONNECTED)) {
2944 int new_id = -1;
2945 os_unsetenv("WPA_ID");
2946 os_unsetenv("WPA_ID_STR");
2947 os_unsetenv("WPA_CTRL_DIR");
2948
2949 pos = os_strstr(pos, "[id=");
2950 if (pos)
2951 copy = os_strdup(pos + 4);
2952
2953 if (copy) {
2954 pos2 = id = copy;
2955 while (*pos2 && *pos2 != ' ')
2956 pos2++;
2957 *pos2++ = '\0';
2958 new_id = atoi(id);
2959 os_setenv("WPA_ID", id, 1);
2960 while (*pos2 && *pos2 != '=')
2961 pos2++;
2962 if (*pos2 == '=')
2963 pos2++;
2964 id = pos2;
2965 while (*pos2 && *pos2 != ']')
2966 pos2++;
2967 *pos2 = '\0';
2968 os_setenv("WPA_ID_STR", id, 1);
2969 os_free(copy);
2970 }
2971
2972 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
2973
2974 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
2975 wpa_cli_connected = 1;
2976 wpa_cli_last_id = new_id;
2977 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
2978 }
2979 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
2980 if (wpa_cli_connected) {
2981 wpa_cli_connected = 0;
2982 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
2983 }
2984 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) {
2985 wpa_cli_exec(action_file, ctrl_ifname, pos);
2986 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) {
2987 wpa_cli_exec(action_file, ctrl_ifname, pos);
2988 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) {
2989 wpa_cli_exec(action_file, ctrl_ifname, pos);
2990 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) {
2991 wpa_cli_exec(action_file, ctrl_ifname, pos);
2992 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) {
2993 wpa_cli_exec(action_file, ctrl_ifname, pos);
2994 } else if (str_match(pos, WPS_EVENT_SUCCESS)) {
2995 wpa_cli_exec(action_file, ctrl_ifname, pos);
2996 } else if (str_match(pos, WPS_EVENT_FAIL)) {
2997 wpa_cli_exec(action_file, ctrl_ifname, pos);
2998 } else if (str_match(pos, AP_STA_CONNECTED)) {
2999 wpa_cli_exec(action_file, ctrl_ifname, pos);
3000 } else if (str_match(pos, AP_STA_DISCONNECTED)) {
3001 wpa_cli_exec(action_file, ctrl_ifname, pos);
3002 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
3003 printf("wpa_supplicant is terminating - stop monitoring\n");
3004 wpa_cli_quit = 1;
3005 }
3006 }
3007
3008
3009 #ifndef CONFIG_ANSI_C_EXTRA
3010 static void wpa_cli_action_cb(char *msg, size_t len)
3011 {
3012 wpa_cli_action_process(msg);
3013 }
3014 #endif /* CONFIG_ANSI_C_EXTRA */
3015
3016
3017 static void wpa_cli_reconnect(void)
3018 {
3019 wpa_cli_close_connection();
3020 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0)
3021 return;
3022
3023 if (interactive) {
3024 edit_clear_line();
3025 printf("\rConnection to wpa_supplicant re-established\n");
3026 edit_redraw();
3027 }
3028 }
3029
3030
3031 static void cli_event(const char *str)
3032 {
3033 const char *start, *s;
3034
3035 start = os_strchr(str, '>');
3036 if (start == NULL)
3037 return;
3038
3039 start++;
3040
3041 if (str_starts(start, WPA_EVENT_BSS_ADDED)) {
3042 s = os_strchr(start, ' ');
3043 if (s == NULL)
3044 return;
3045 s = os_strchr(s + 1, ' ');
3046 if (s == NULL)
3047 return;
3048 cli_txt_list_add(&bsses, s + 1);
3049 return;
3050 }
3051
3052 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) {
3053 s = os_strchr(start, ' ');
3054 if (s == NULL)
3055 return;
3056 s = os_strchr(s + 1, ' ');
3057 if (s == NULL)
3058 return;
3059 cli_txt_list_del_addr(&bsses, s + 1);
3060 return;
3061 }
3062
3063 #ifdef CONFIG_P2P
3064 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) {
3065 s = os_strstr(start, " p2p_dev_addr=");
3066 if (s == NULL)
3067 return;
3068 cli_txt_list_add_addr(&p2p_peers, s + 14);
3069 return;
3070 }
3071
3072 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) {
3073 s = os_strstr(start, " p2p_dev_addr=");
3074 if (s == NULL)
3075 return;
3076 cli_txt_list_del_addr(&p2p_peers, s + 14);
3077 return;
3078 }
3079
3080 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) {
3081 s = os_strchr(start, ' ');
3082 if (s == NULL)
3083 return;
3084 cli_txt_list_add_word(&p2p_groups, s + 1);
3085 return;
3086 }
3087
3088 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) {
3089 s = os_strchr(start, ' ');
3090 if (s == NULL)
3091 return;
3092 cli_txt_list_del_word(&p2p_groups, s + 1);
3093 return;
3094 }
3095 #endif /* CONFIG_P2P */
3096 }
3097
3098
3099 static int check_terminating(const char *msg)
3100 {
3101 const char *pos = msg;
3102
3103 if (*pos == '<') {
3104 /* skip priority */
3105 pos = os_strchr(pos, '>');
3106 if (pos)
3107 pos++;
3108 else
3109 pos = msg;
3110 }
3111
3112 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) {
3113 edit_clear_line();
3114 printf("\rConnection to wpa_supplicant lost - trying to "
3115 "reconnect\n");
3116 edit_redraw();
3117 wpa_cli_attached = 0;
3118 wpa_cli_close_connection();
3119 return 1;
3120 }
3121
3122 return 0;
3123 }
3124
3125
3126 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor)
3127 {
3128 if (ctrl_conn == NULL) {
3129 wpa_cli_reconnect();
3130 return;
3131 }
3132 while (wpa_ctrl_pending(ctrl) > 0) {
3133 char buf[256];
3134 size_t len = sizeof(buf) - 1;
3135 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
3136 buf[len] = '\0';
3137 if (action_monitor)
3138 wpa_cli_action_process(buf);
3139 else {
3140 cli_event(buf);
3141 if (wpa_cli_show_event(buf)) {
3142 edit_clear_line();
3143 printf("\r%s\n", buf);
3144 edit_redraw();
3145 }
3146
3147 if (interactive && check_terminating(buf) > 0)
3148 return;
3149 }
3150 } else {
3151 printf("Could not read pending message.\n");
3152 break;
3153 }
3154 }
3155
3156 if (wpa_ctrl_pending(ctrl) < 0) {
3157 printf("Connection to wpa_supplicant lost - trying to "
3158 "reconnect\n");
3159 wpa_cli_reconnect();
3160 }
3161 }
3162
3163 #define max_args 10
3164
3165 static int tokenize_cmd(char *cmd, char *argv[])
3166 {
3167 char *pos;
3168 int argc = 0;
3169
3170 pos = cmd;
3171 for (;;) {
3172 while (*pos == ' ')
3173 pos++;
3174 if (*pos == '\0')
3175 break;
3176 argv[argc] = pos;
3177 argc++;
3178 if (argc == max_args)
3179 break;
3180 if (*pos == '"') {
3181 char *pos2 = os_strrchr(pos, '"');
3182 if (pos2)
3183 pos = pos2 + 1;
3184 }
3185 while (*pos != '\0' && *pos != ' ')
3186 pos++;
3187 if (*pos == ' ')
3188 *pos++ = '\0';
3189 }
3190
3191 return argc;
3192 }
3193
3194
3195 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx)
3196 {
3197 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
3198 printf("Connection to wpa_supplicant lost - trying to "
3199 "reconnect\n");
3200 wpa_cli_close_connection();
3201 }
3202 if (!ctrl_conn)
3203 wpa_cli_reconnect();
3204 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3205 }
3206
3207
3208 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx)
3209 {
3210 wpa_cli_recv_pending(mon_conn, 0);
3211 }
3212
3213
3214 static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd)
3215 {
3216 char *argv[max_args];
3217 int argc;
3218 argc = tokenize_cmd(cmd, argv);
3219 if (argc)
3220 wpa_request(ctrl_conn, argc, argv);
3221 }
3222
3223
3224 static void wpa_cli_edit_eof_cb(void *ctx)
3225 {
3226 eloop_terminate();
3227 }
3228
3229
3230 static int warning_displayed = 0;
3231 static char *hfile = NULL;
3232 static int edit_started = 0;
3233
3234 static void start_edit(void)
3235 {
3236 char *home;
3237 char *ps = NULL;
3238
3239 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
3240 ps = wpa_ctrl_get_remote_ifname(ctrl_conn);
3241 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
3242
3243 home = getenv("HOME");
3244 if (home) {
3245 const char *fname = ".wpa_cli_history";
3246 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
3247 hfile = os_malloc(hfile_len);
3248 if (hfile)
3249 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
3250 }
3251
3252 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb,
3253 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) {
3254 eloop_terminate();
3255 return;
3256 }
3257
3258 edit_started = 1;
3259 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL);
3260 }
3261
3262
3263 static void try_connection(void *eloop_ctx, void *timeout_ctx)
3264 {
3265 if (ctrl_ifname == NULL)
3266 ctrl_ifname = wpa_cli_get_default_ifname();
3267
3268 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) {
3269 if (!warning_displayed) {
3270 printf("Could not connect to wpa_supplicant: "
3271 "%s - re-trying\n", ctrl_ifname);
3272 warning_displayed = 1;
3273 }
3274 eloop_register_timeout(1, 0, try_connection, NULL, NULL);
3275 return;
3276 }
3277
3278 if (warning_displayed)
3279 printf("Connection established.\n");
3280
3281 start_edit();
3282 }
3283
3284
3285 static void wpa_cli_interactive(void)
3286 {
3287 printf("\nInteractive mode\n\n");
3288
3289 eloop_register_timeout(0, 0, try_connection, NULL, NULL);
3290 eloop_run();
3291 eloop_cancel_timeout(try_connection, NULL, NULL);
3292
3293 cli_txt_list_flush(&p2p_peers);
3294 cli_txt_list_flush(&p2p_groups);
3295 cli_txt_list_flush(&bsses);
3296 if (edit_started)
3297 edit_deinit(hfile, wpa_cli_edit_filter_history_cb);
3298 os_free(hfile);
3299 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL);
3300 wpa_cli_close_connection();
3301 }
3302
3303
3304 static void wpa_cli_action(struct wpa_ctrl *ctrl)
3305 {
3306 #ifdef CONFIG_ANSI_C_EXTRA
3307 /* TODO: ANSI C version(?) */
3308 printf("Action processing not supported in ANSI C build.\n");
3309 #else /* CONFIG_ANSI_C_EXTRA */
3310 fd_set rfds;
3311 int fd, res;
3312 struct timeval tv;
3313 char buf[256]; /* note: large enough to fit in unsolicited messages */
3314 size_t len;
3315
3316 fd = wpa_ctrl_get_fd(ctrl);
3317
3318 while (!wpa_cli_quit) {
3319 FD_ZERO(&rfds);
3320 FD_SET(fd, &rfds);
3321 tv.tv_sec = ping_interval;
3322 tv.tv_usec = 0;
3323 res = select(fd + 1, &rfds, NULL, NULL, &tv);
3324 if (res < 0 && errno != EINTR) {
3325 perror("select");
3326 break;
3327 }
3328
3329 if (FD_ISSET(fd, &rfds))
3330 wpa_cli_recv_pending(ctrl, 1);
3331 else {
3332 /* verify that connection is still working */
3333 len = sizeof(buf) - 1;
3334 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
3335 wpa_cli_action_cb) < 0 ||
3336 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
3337 printf("wpa_supplicant did not reply to PING "
3338 "command - exiting\n");
3339 break;
3340 }
3341 }
3342 }
3343 #endif /* CONFIG_ANSI_C_EXTRA */
3344 }
3345
3346
3347 static void wpa_cli_cleanup(void)
3348 {
3349 wpa_cli_close_connection();
3350 if (pid_file)
3351 os_daemonize_terminate(pid_file);
3352
3353 os_program_deinit();
3354 }
3355
3356
3357 static void wpa_cli_terminate(int sig, void *ctx)
3358 {
3359 eloop_terminate();
3360 }
3361
3362
3363 static char * wpa_cli_get_default_ifname(void)
3364 {
3365 char *ifname = NULL;
3366
3367 #ifdef CONFIG_CTRL_IFACE_UNIX
3368 struct dirent *dent;
3369 DIR *dir = opendir(ctrl_iface_dir);
3370 if (!dir) {
3371 #ifdef ANDROID
3372 char ifprop[PROPERTY_VALUE_MAX];
3373 if (property_get("wifi.interface", ifprop, NULL) != 0) {
3374 ifname = os_strdup(ifprop);
3375 printf("Using interface '%s'\n", ifname);
3376 return ifname;
3377 }
3378 #endif /* ANDROID */
3379 return NULL;
3380 }
3381 while ((dent = readdir(dir))) {
3382 #ifdef _DIRENT_HAVE_D_TYPE
3383 /*
3384 * Skip the file if it is not a socket. Also accept
3385 * DT_UNKNOWN (0) in case the C library or underlying
3386 * file system does not support d_type.
3387 */
3388 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
3389 continue;
3390 #endif /* _DIRENT_HAVE_D_TYPE */
3391 if (os_strcmp(dent->d_name, ".") == 0 ||
3392 os_strcmp(dent->d_name, "..") == 0)
3393 continue;
3394 printf("Selected interface '%s'\n", dent->d_name);
3395 ifname = os_strdup(dent->d_name);
3396 break;
3397 }
3398 closedir(dir);
3399 #endif /* CONFIG_CTRL_IFACE_UNIX */
3400
3401 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3402 char buf[2048], *pos;
3403 size_t len;
3404 struct wpa_ctrl *ctrl;
3405 int ret;
3406
3407 ctrl = wpa_ctrl_open(NULL);
3408 if (ctrl == NULL)
3409 return NULL;
3410
3411 len = sizeof(buf) - 1;
3412 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
3413 if (ret >= 0) {
3414 buf[len] = '\0';
3415 pos = os_strchr(buf, '\n');
3416 if (pos)
3417 *pos = '\0';
3418 ifname = os_strdup(buf);
3419 }
3420 wpa_ctrl_close(ctrl);
3421 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3422
3423 return ifname;
3424 }
3425
3426
3427 int main(int argc, char *argv[])
3428 {
3429 int c;
3430 int daemonize = 0;
3431 int ret = 0;
3432 const char *global = NULL;
3433
3434 if (os_program_init())
3435 return -1;
3436
3437 for (;;) {
3438 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
3439 if (c < 0)
3440 break;
3441 switch (c) {
3442 case 'a':
3443 action_file = optarg;
3444 break;
3445 case 'B':
3446 daemonize = 1;
3447 break;
3448 case 'g':
3449 global = optarg;
3450 break;
3451 case 'G':
3452 ping_interval = atoi(optarg);
3453 break;
3454 case 'h':
3455 usage();
3456 return 0;
3457 case 'v':
3458 printf("%s\n", wpa_cli_version);
3459 return 0;
3460 case 'i':
3461 os_free(ctrl_ifname);
3462 ctrl_ifname = os_strdup(optarg);
3463 break;
3464 case 'p':
3465 ctrl_iface_dir = optarg;
3466 break;
3467 case 'P':
3468 pid_file = optarg;
3469 break;
3470 default:
3471 usage();
3472 return -1;
3473 }
3474 }
3475
3476 interactive = (argc == optind) && (action_file == NULL);
3477
3478 if (interactive)
3479 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
3480
3481 if (eloop_init())
3482 return -1;
3483
3484 if (global) {
3485 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
3486 ctrl_conn = wpa_ctrl_open(NULL);
3487 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3488 ctrl_conn = wpa_ctrl_open(global);
3489 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
3490 if (ctrl_conn == NULL) {
3491 fprintf(stderr, "Failed to connect to wpa_supplicant "
3492 "global interface: %s error: %s\n",
3493 global, strerror(errno));
3494 return -1;
3495 }
3496 }
3497
3498 eloop_register_signal_terminate(wpa_cli_terminate, NULL);
3499
3500 if (ctrl_ifname == NULL)
3501 ctrl_ifname = wpa_cli_get_default_ifname();
3502
3503 if (interactive) {
3504 wpa_cli_interactive();
3505 } else {
3506 if (!global &&
3507 wpa_cli_open_connection(ctrl_ifname, 0) < 0) {
3508 fprintf(stderr, "Failed to connect to non-global "
3509 "ctrl_ifname: %s error: %s\n",
3510 ctrl_ifname, strerror(errno));
3511 return -1;
3512 }
3513
3514 if (action_file) {
3515 if (wpa_ctrl_attach(ctrl_conn) == 0) {
3516 wpa_cli_attached = 1;
3517 } else {
3518 printf("Warning: Failed to attach to "
3519 "wpa_supplicant.\n");
3520 return -1;
3521 }
3522 }
3523
3524 if (daemonize && os_daemonize(pid_file))
3525 return -1;
3526
3527 if (action_file)
3528 wpa_cli_action(ctrl_conn);
3529 else
3530 ret = wpa_request(ctrl_conn, argc - optind,
3531 &argv[optind]);
3532 }
3533
3534 os_free(ctrl_ifname);
3535 eloop_destroy();
3536 wpa_cli_cleanup();
3537
3538 return ret;
3539 }
3540
3541 #else /* CONFIG_CTRL_IFACE */
3542 int main(int argc, char *argv[])
3543 {
3544 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
3545 return -1;
3546 }
3547 #endif /* CONFIG_CTRL_IFACE */