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