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