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