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