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