]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
WPS ER: Only send Enrollee notification on Probe Request and M1
[thirdparty/hostap.git] / wpa_supplicant / wpa_cli.c
CommitLineData
6fc6879b
JM
1/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
6f78f2fb 3 * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
6fc6879b
JM
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16
17#ifdef CONFIG_CTRL_IFACE
18
19#ifdef CONFIG_CTRL_IFACE_UNIX
20#include <dirent.h>
21#endif /* CONFIG_CTRL_IFACE_UNIX */
22#ifdef CONFIG_READLINE
23#include <readline/readline.h>
24#include <readline/history.h>
25#endif /* CONFIG_READLINE */
26
27#include "wpa_ctrl.h"
28#include "common.h"
29#include "version.h"
30
31
32static const char *wpa_cli_version =
33"wpa_cli v" VERSION_STR "\n"
6f78f2fb 34"Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> and contributors";
6fc6879b
JM
35
36
37static const char *wpa_cli_license =
38"This program is free software. You can distribute it and/or modify it\n"
39"under the terms of the GNU General Public License version 2.\n"
40"\n"
41"Alternatively, this software may be distributed under the terms of the\n"
42"BSD license. See README and COPYING for more details.\n";
43
44static const char *wpa_cli_full_license =
45"This program is free software; you can redistribute it and/or modify\n"
46"it under the terms of the GNU General Public License version 2 as\n"
47"published by the Free Software Foundation.\n"
48"\n"
49"This program is distributed in the hope that it will be useful,\n"
50"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
51"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
52"GNU General Public License for more details.\n"
53"\n"
54"You should have received a copy of the GNU General Public License\n"
55"along with this program; if not, write to the Free Software\n"
56"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
57"\n"
58"Alternatively, this software may be distributed under the terms of the\n"
59"BSD license.\n"
60"\n"
61"Redistribution and use in source and binary forms, with or without\n"
62"modification, are permitted provided that the following conditions are\n"
63"met:\n"
64"\n"
65"1. Redistributions of source code must retain the above copyright\n"
66" notice, this list of conditions and the following disclaimer.\n"
67"\n"
68"2. Redistributions in binary form must reproduce the above copyright\n"
69" notice, this list of conditions and the following disclaimer in the\n"
70" documentation and/or other materials provided with the distribution.\n"
71"\n"
72"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
73" names of its contributors may be used to endorse or promote products\n"
74" derived from this software without specific prior written permission.\n"
75"\n"
76"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
77"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
78"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
79"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
80"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
81"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
82"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
83"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
84"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
85"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
86"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
87"\n";
88
6fc6879b
JM
89static struct wpa_ctrl *ctrl_conn;
90static int wpa_cli_quit = 0;
91static int wpa_cli_attached = 0;
92static int wpa_cli_connected = 0;
93static int wpa_cli_last_id = 0;
94static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
95static char *ctrl_ifname = NULL;
96static const char *pid_file = NULL;
97static const char *action_file = NULL;
1cc84c1c 98static int ping_interval = 5;
6fc6879b
JM
99
100
dfa141b1
ER
101static void print_help();
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"
116 " default path: /var/run/wpa_supplicant\n"
dfa141b1
ER
117 " default interface: first interface found in socket path\n");
118 print_help();
6fc6879b
JM
119}
120
121
122static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
123{
124#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
125 ctrl_conn = wpa_ctrl_open(ifname);
126 return ctrl_conn;
127#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
128 char *cfile;
129 int flen, res;
130
131 if (ifname == NULL)
132 return NULL;
133
134 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
135 cfile = os_malloc(flen);
136 if (cfile == NULL)
137 return NULL;
138 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
139 if (res < 0 || res >= flen) {
140 os_free(cfile);
141 return NULL;
142 }
143
144 ctrl_conn = wpa_ctrl_open(cfile);
145 os_free(cfile);
146 return ctrl_conn;
147#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
148}
149
150
151static void wpa_cli_close_connection(void)
152{
153 if (ctrl_conn == NULL)
154 return;
155
156 if (wpa_cli_attached) {
157 wpa_ctrl_detach(ctrl_conn);
158 wpa_cli_attached = 0;
159 }
160 wpa_ctrl_close(ctrl_conn);
161 ctrl_conn = NULL;
162}
163
164
165static void wpa_cli_msg_cb(char *msg, size_t len)
166{
167 printf("%s\n", msg);
168}
169
170
171static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
172{
173 char buf[2048];
174 size_t len;
175 int ret;
176
177 if (ctrl_conn == NULL) {
178 printf("Not connected to wpa_supplicant - command dropped.\n");
179 return -1;
180 }
181 len = sizeof(buf) - 1;
182 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
183 wpa_cli_msg_cb);
184 if (ret == -2) {
185 printf("'%s' command timed out.\n", cmd);
186 return -2;
187 } else if (ret < 0) {
188 printf("'%s' command failed.\n", cmd);
189 return -1;
190 }
191 if (print) {
192 buf[len] = '\0';
193 printf("%s", buf);
194 }
195 return 0;
196}
197
198
199static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
200{
201 return _wpa_ctrl_command(ctrl, cmd, 1);
202}
203
204
205static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
206{
207 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
208 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
209}
210
211
212static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
213{
214 return wpa_ctrl_command(ctrl, "PING");
215}
216
217
218static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
219{
220 return wpa_ctrl_command(ctrl, "MIB");
221}
222
223
224static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
225{
226 return wpa_ctrl_command(ctrl, "PMKSA");
227}
228
229
230static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
231{
dfa141b1 232 print_help();
6fc6879b
JM
233 return 0;
234}
235
236
237static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
238{
239 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
240 return 0;
241}
242
243
244static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
245{
246 wpa_cli_quit = 1;
247 return 0;
248}
249
250
251static void wpa_cli_show_variables(void)
252{
253 printf("set variables:\n"
254 " EAPOL::heldPeriod (EAPOL state machine held period, "
255 "in seconds)\n"
256 " EAPOL::authPeriod (EAPOL state machine authentication "
257 "period, in seconds)\n"
258 " EAPOL::startPeriod (EAPOL state machine start period, in "
259 "seconds)\n"
260 " EAPOL::maxStart (EAPOL state machine maximum start "
261 "attempts)\n");
262 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
263 "seconds)\n"
264 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
265 " threshold\n\tpercentage)\n"
266 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
267 "security\n\tassociation in seconds)\n");
268}
269
270
271static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
272{
273 char cmd[256];
274 int res;
275
276 if (argc == 0) {
277 wpa_cli_show_variables();
278 return 0;
279 }
280
281 if (argc != 2) {
282 printf("Invalid SET command: needs two arguments (variable "
283 "name and value)\n");
284 return -1;
285 }
286
287 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
288 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
289 printf("Too long SET command.\n");
290 return -1;
291 }
292 return wpa_ctrl_command(ctrl, cmd);
293}
294
295
296static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
297{
298 return wpa_ctrl_command(ctrl, "LOGOFF");
299}
300
301
302static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
303{
304 return wpa_ctrl_command(ctrl, "LOGON");
305}
306
307
308static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
309 char *argv[])
310{
311 return wpa_ctrl_command(ctrl, "REASSOCIATE");
312}
313
314
315static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
316 char *argv[])
317{
318 char cmd[256];
319 int res;
320
321 if (argc != 1) {
322 printf("Invalid PREAUTH command: needs one argument "
323 "(BSSID)\n");
324 return -1;
325 }
326
327 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
328 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
329 printf("Too long PREAUTH command.\n");
330 return -1;
331 }
332 return wpa_ctrl_command(ctrl, cmd);
333}
334
335
336static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
337{
338 char cmd[256];
339 int res;
340
341 if (argc != 1) {
342 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
343 "value)\n");
344 return -1;
345 }
346 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
347 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
348 printf("Too long AP_SCAN command.\n");
349 return -1;
350 }
351 return wpa_ctrl_command(ctrl, cmd);
352}
353
354
355static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
356 char *argv[])
357{
358 char cmd[256];
359 int res;
360
361 if (argc != 1) {
362 printf("Invalid STKSTART command: needs one argument "
363 "(Peer STA MAC address)\n");
364 return -1;
365 }
366
367 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
368 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
369 printf("Too long STKSTART command.\n");
370 return -1;
371 }
372 return wpa_ctrl_command(ctrl, cmd);
373}
374
375
376static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
377{
378 char cmd[256];
379 int res;
380
381 if (argc != 1) {
382 printf("Invalid FT_DS command: needs one argument "
383 "(Target AP MAC address)\n");
384 return -1;
385 }
386
387 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
388 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
389 printf("Too long FT_DS command.\n");
390 return -1;
391 }
392 return wpa_ctrl_command(ctrl, cmd);
393}
394
395
fcc60db4
JM
396static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
397{
398 char cmd[256];
399 int res;
400
401 if (argc == 0) {
402 /* Any BSSID */
403 return wpa_ctrl_command(ctrl, "WPS_PBC");
404 }
405
406 /* Specific BSSID */
407 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
408 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
409 printf("Too long WPS_PBC command.\n");
410 return -1;
411 }
412 return wpa_ctrl_command(ctrl, cmd);
413}
414
415
416static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
417{
418 char cmd[256];
419 int res;
420
421 if (argc == 0) {
422 printf("Invalid WPS_PIN command: need one or two arguments:\n"
423 "- BSSID: use 'any' to select any\n"
424 "- PIN: optional, used only with devices that have no "
425 "display\n");
426 return -1;
427 }
428
429 if (argc == 1) {
430 /* Use dynamically generated PIN (returned as reply) */
431 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
432 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
433 printf("Too long WPS_PIN command.\n");
434 return -1;
435 }
436 return wpa_ctrl_command(ctrl, cmd);
437 }
438
439 /* Use hardcoded PIN from a label */
440 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
441 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
442 printf("Too long WPS_PIN command.\n");
443 return -1;
444 }
445 return wpa_ctrl_command(ctrl, cmd);
446}
447
448
116f7bb0 449#ifdef CONFIG_WPS_OOB
46bdb83a
MH
450static int wpa_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc, char *argv[])
451{
452 char cmd[256];
453 int res;
454
e1ee6b60
MH
455 if (argc != 3 && argc != 4) {
456 printf("Invalid WPS_OOB command: need three or four "
457 "arguments:\n"
458 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
459 "- PATH: path of OOB device like '/mnt'\n"
460 "- METHOD: OOB method 'pin-e' or 'pin-r', "
461 "'cred'\n"
462 "- DEV_NAME: (only for NFC) device name like "
463 "'pn531'\n");
46bdb83a
MH
464 return -1;
465 }
466
e1ee6b60
MH
467 if (argc == 3)
468 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
469 argv[0], argv[1], argv[2]);
470 else
471 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
472 argv[0], argv[1], argv[2], argv[3]);
46bdb83a
MH
473 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
474 printf("Too long WPS_OOB command.\n");
475 return -1;
476 }
477 return wpa_ctrl_command(ctrl, cmd);
478}
116f7bb0 479#endif /* CONFIG_WPS_OOB */
46bdb83a
MH
480
481
fcc60db4
JM
482static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
483{
484 char cmd[256];
485 int res;
486
52eb293d
JM
487 if (argc == 2)
488 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s",
489 argv[0], argv[1]);
490 else if (argc == 6) {
491 char ssid_hex[2 * 32 + 1];
492 char key_hex[2 * 64 + 1];
493 int i;
494
495 ssid_hex[0] = '\0';
496 for (i = 0; i < 32; i++) {
497 if (argv[2][i] == '\0')
498 break;
499 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]);
500 }
501
502 key_hex[0] = '\0';
503 for (i = 0; i < 64; i++) {
504 if (argv[5][i] == '\0')
505 break;
506 os_snprintf(&key_hex[i * 2], 3, "%02x", argv[5][i]);
507 }
508
509 res = os_snprintf(cmd, sizeof(cmd),
510 "WPS_REG %s %s %s %s %s %s",
511 argv[0], argv[1], ssid_hex, argv[3], argv[4],
512 key_hex);
513 } else {
fcc60db4
JM
514 printf("Invalid WPS_REG command: need two arguments:\n"
515 "- BSSID: use 'any' to select any\n"
516 "- AP PIN\n");
52eb293d
JM
517 printf("Alternatively, six arguments can be used to "
518 "reconfigure the AP:\n"
519 "- BSSID: use 'any' to select any\n"
520 "- AP PIN\n"
521 "- new SSID\n"
522 "- new auth (OPEN, WPAPSK, WPA2PSK)\n"
523 "- new encr (NONE, WEP, TKIP, CCMP)\n"
524 "- new key\n");
fcc60db4
JM
525 return -1;
526 }
527
fcc60db4
JM
528 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
529 printf("Too long WPS_REG command.\n");
530 return -1;
531 }
532 return wpa_ctrl_command(ctrl, cmd);
533}
534
535
e9bcfebf
JM
536static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc,
537 char *argv[])
538{
539 return wpa_ctrl_command(ctrl, "WPS_ER_START");
540
541}
542
543
544static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc,
545 char *argv[])
546{
547 return wpa_ctrl_command(ctrl, "WPS_ER_STOP");
548
549}
550
551
72df2f5f
JM
552static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc,
553 char *argv[])
554{
555 char cmd[256];
556 int res;
557
558 if (argc != 2) {
559 printf("Invalid WPS_ER_PIN command: need two arguments:\n"
560 "- UUID: use 'any' to select any\n"
561 "- PIN: Enrollee PIN\n");
562 return -1;
563 }
564
565 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
566 argv[0], argv[1]);
567 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
568 printf("Too long WPS_ER_PIN command.\n");
569 return -1;
570 }
571 return wpa_ctrl_command(ctrl, cmd);
572}
573
574
11ef8d35
JM
575static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
576{
577 char cmd[256];
578 int res;
579
580 if (argc != 1) {
581 printf("Invalid IBSS_RSN command: needs one argument "
582 "(Peer STA MAC address)\n");
583 return -1;
584 }
585
586 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
587 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
588 printf("Too long IBSS_RSN command.\n");
589 return -1;
590 }
591 return wpa_ctrl_command(ctrl, cmd);
592}
593
594
6fc6879b
JM
595static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
596{
597 char cmd[256];
598 int res;
599
600 if (argc != 1) {
601 printf("Invalid LEVEL command: needs one argument (debug "
602 "level)\n");
603 return -1;
604 }
605 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
606 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
607 printf("Too long LEVEL command.\n");
608 return -1;
609 }
610 return wpa_ctrl_command(ctrl, cmd);
611}
612
613
614static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
615{
616 char cmd[256], *pos, *end;
617 int i, ret;
618
619 if (argc < 2) {
620 printf("Invalid IDENTITY command: needs two arguments "
621 "(network id and identity)\n");
622 return -1;
623 }
624
625 end = cmd + sizeof(cmd);
626 pos = cmd;
627 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
628 argv[0], argv[1]);
629 if (ret < 0 || ret >= end - pos) {
630 printf("Too long IDENTITY command.\n");
631 return -1;
632 }
633 pos += ret;
634 for (i = 2; i < argc; i++) {
635 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
636 if (ret < 0 || ret >= end - pos) {
637 printf("Too long IDENTITY command.\n");
638 return -1;
639 }
640 pos += ret;
641 }
642
643 return wpa_ctrl_command(ctrl, cmd);
644}
645
646
647static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
648{
649 char cmd[256], *pos, *end;
650 int i, ret;
651
652 if (argc < 2) {
653 printf("Invalid PASSWORD command: needs two arguments "
654 "(network id and password)\n");
655 return -1;
656 }
657
658 end = cmd + sizeof(cmd);
659 pos = cmd;
660 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
661 argv[0], argv[1]);
662 if (ret < 0 || ret >= end - pos) {
663 printf("Too long PASSWORD command.\n");
664 return -1;
665 }
666 pos += ret;
667 for (i = 2; i < argc; i++) {
668 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
669 if (ret < 0 || ret >= end - pos) {
670 printf("Too long PASSWORD command.\n");
671 return -1;
672 }
673 pos += ret;
674 }
675
676 return wpa_ctrl_command(ctrl, cmd);
677}
678
679
680static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
681 char *argv[])
682{
683 char cmd[256], *pos, *end;
684 int i, ret;
685
686 if (argc < 2) {
687 printf("Invalid NEW_PASSWORD command: needs two arguments "
688 "(network id and password)\n");
689 return -1;
690 }
691
692 end = cmd + sizeof(cmd);
693 pos = cmd;
694 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
695 argv[0], argv[1]);
696 if (ret < 0 || ret >= end - pos) {
697 printf("Too long NEW_PASSWORD command.\n");
698 return -1;
699 }
700 pos += ret;
701 for (i = 2; i < argc; i++) {
702 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
703 if (ret < 0 || ret >= end - pos) {
704 printf("Too long NEW_PASSWORD command.\n");
705 return -1;
706 }
707 pos += ret;
708 }
709
710 return wpa_ctrl_command(ctrl, cmd);
711}
712
713
714static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
715{
716 char cmd[256], *pos, *end;
717 int i, ret;
718
719 if (argc < 2) {
720 printf("Invalid PIN command: needs two arguments "
721 "(network id and pin)\n");
722 return -1;
723 }
724
725 end = cmd + sizeof(cmd);
726 pos = cmd;
727 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
728 argv[0], argv[1]);
729 if (ret < 0 || ret >= end - pos) {
730 printf("Too long PIN command.\n");
731 return -1;
732 }
733 pos += ret;
734 for (i = 2; i < argc; i++) {
735 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
736 if (ret < 0 || ret >= end - pos) {
737 printf("Too long PIN command.\n");
738 return -1;
739 }
740 pos += ret;
741 }
742 return wpa_ctrl_command(ctrl, cmd);
743}
744
745
746static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
747{
748 char cmd[256], *pos, *end;
749 int i, ret;
750
751 if (argc < 2) {
752 printf("Invalid OTP command: needs two arguments (network "
753 "id and password)\n");
754 return -1;
755 }
756
757 end = cmd + sizeof(cmd);
758 pos = cmd;
759 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
760 argv[0], argv[1]);
761 if (ret < 0 || ret >= end - pos) {
762 printf("Too long OTP command.\n");
763 return -1;
764 }
765 pos += ret;
766 for (i = 2; i < argc; i++) {
767 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
768 if (ret < 0 || ret >= end - pos) {
769 printf("Too long OTP command.\n");
770 return -1;
771 }
772 pos += ret;
773 }
774
775 return wpa_ctrl_command(ctrl, cmd);
776}
777
778
779static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
780 char *argv[])
781{
782 char cmd[256], *pos, *end;
783 int i, ret;
784
785 if (argc < 2) {
786 printf("Invalid PASSPHRASE command: needs two arguments "
787 "(network id and passphrase)\n");
788 return -1;
789 }
790
791 end = cmd + sizeof(cmd);
792 pos = cmd;
793 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
794 argv[0], argv[1]);
795 if (ret < 0 || ret >= end - pos) {
796 printf("Too long PASSPHRASE command.\n");
797 return -1;
798 }
799 pos += ret;
800 for (i = 2; i < argc; i++) {
801 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
802 if (ret < 0 || ret >= end - pos) {
803 printf("Too long PASSPHRASE command.\n");
804 return -1;
805 }
806 pos += ret;
807 }
808
809 return wpa_ctrl_command(ctrl, cmd);
810}
811
812
813static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
814{
815 char cmd[256], *pos, *end;
816 int i, ret;
817
818 if (argc < 2) {
819 printf("Invalid BSSID command: needs two arguments (network "
820 "id and BSSID)\n");
821 return -1;
822 }
823
824 end = cmd + sizeof(cmd);
825 pos = cmd;
826 ret = os_snprintf(pos, end - pos, "BSSID");
827 if (ret < 0 || ret >= end - pos) {
828 printf("Too long BSSID command.\n");
829 return -1;
830 }
831 pos += ret;
832 for (i = 0; i < argc; i++) {
833 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
834 if (ret < 0 || ret >= end - pos) {
835 printf("Too long BSSID command.\n");
836 return -1;
837 }
838 pos += ret;
839 }
840
841 return wpa_ctrl_command(ctrl, cmd);
842}
843
844
845static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
846 char *argv[])
847{
848 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
849}
850
851
852static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
853 char *argv[])
854{
855 char cmd[32];
856 int res;
857
858 if (argc < 1) {
859 printf("Invalid SELECT_NETWORK command: needs one argument "
860 "(network id)\n");
861 return -1;
862 }
863
864 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
865 if (res < 0 || (size_t) res >= sizeof(cmd))
866 return -1;
867 cmd[sizeof(cmd) - 1] = '\0';
868
869 return wpa_ctrl_command(ctrl, cmd);
870}
871
872
873static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
874 char *argv[])
875{
876 char cmd[32];
877 int res;
878
879 if (argc < 1) {
880 printf("Invalid ENABLE_NETWORK command: needs one argument "
881 "(network id)\n");
882 return -1;
883 }
884
885 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
886 if (res < 0 || (size_t) res >= sizeof(cmd))
887 return -1;
888 cmd[sizeof(cmd) - 1] = '\0';
889
890 return wpa_ctrl_command(ctrl, cmd);
891}
892
893
894static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
895 char *argv[])
896{
897 char cmd[32];
898 int res;
899
900 if (argc < 1) {
901 printf("Invalid DISABLE_NETWORK command: needs one argument "
902 "(network id)\n");
903 return -1;
904 }
905
906 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
907 if (res < 0 || (size_t) res >= sizeof(cmd))
908 return -1;
909 cmd[sizeof(cmd) - 1] = '\0';
910
911 return wpa_ctrl_command(ctrl, cmd);
912}
913
914
915static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
916 char *argv[])
917{
918 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
919}
920
921
922static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
923 char *argv[])
924{
925 char cmd[32];
926 int res;
927
928 if (argc < 1) {
929 printf("Invalid REMOVE_NETWORK command: needs one argument "
930 "(network id)\n");
931 return -1;
932 }
933
934 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
935 if (res < 0 || (size_t) res >= sizeof(cmd))
936 return -1;
937 cmd[sizeof(cmd) - 1] = '\0';
938
939 return wpa_ctrl_command(ctrl, cmd);
940}
941
942
943static void wpa_cli_show_network_variables(void)
944{
945 printf("set_network variables:\n"
946 " ssid (network name, SSID)\n"
947 " psk (WPA passphrase or pre-shared key)\n"
948 " key_mgmt (key management protocol)\n"
949 " identity (EAP identity)\n"
950 " password (EAP password)\n"
951 " ...\n"
952 "\n"
953 "Note: Values are entered in the same format as the "
954 "configuration file is using,\n"
955 "i.e., strings values need to be inside double quotation "
956 "marks.\n"
957 "For example: set_network 1 ssid \"network name\"\n"
958 "\n"
959 "Please see wpa_supplicant.conf documentation for full list "
960 "of\navailable variables.\n");
961}
962
963
964static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
965 char *argv[])
966{
967 char cmd[256];
968 int res;
969
970 if (argc == 0) {
971 wpa_cli_show_network_variables();
972 return 0;
973 }
974
975 if (argc != 3) {
976 printf("Invalid SET_NETWORK command: needs three arguments\n"
977 "(network id, variable name, and value)\n");
978 return -1;
979 }
980
981 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
982 argv[0], argv[1], argv[2]);
983 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
984 printf("Too long SET_NETWORK command.\n");
985 return -1;
986 }
987 return wpa_ctrl_command(ctrl, cmd);
988}
989
990
991static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
992 char *argv[])
993{
994 char cmd[256];
995 int res;
996
997 if (argc == 0) {
998 wpa_cli_show_network_variables();
999 return 0;
1000 }
1001
1002 if (argc != 2) {
1003 printf("Invalid GET_NETWORK command: needs two arguments\n"
1004 "(network id and variable name)\n");
1005 return -1;
1006 }
1007
1008 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1009 argv[0], argv[1]);
1010 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1011 printf("Too long GET_NETWORK command.\n");
1012 return -1;
1013 }
1014 return wpa_ctrl_command(ctrl, cmd);
1015}
1016
1017
1018static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1019 char *argv[])
1020{
1021 return wpa_ctrl_command(ctrl, "DISCONNECT");
1022}
1023
1024
1025static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1026 char *argv[])
1027{
1028 return wpa_ctrl_command(ctrl, "RECONNECT");
1029}
1030
1031
1032static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1033 char *argv[])
1034{
1035 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1036}
1037
1038
1039static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1040{
1041 return wpa_ctrl_command(ctrl, "SCAN");
1042}
1043
1044
1045static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1046 char *argv[])
1047{
1048 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1049}
1050
1051
1052static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1053{
1054 char cmd[64];
1055 int res;
1056
1057 if (argc != 1) {
1058 printf("Invalid BSS command: need one argument (index or "
1059 "BSSID)\n");
1060 return -1;
1061 }
1062
1063 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1064 if (res < 0 || (size_t) res >= sizeof(cmd))
1065 return -1;
1066 cmd[sizeof(cmd) - 1] = '\0';
1067
1068 return wpa_ctrl_command(ctrl, cmd);
1069}
1070
1071
1072static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1073 char *argv[])
1074{
1075 char cmd[64];
1076 int res;
1077
1078 if (argc < 1 || argc > 2) {
1079 printf("Invalid GET_CAPABILITY command: need either one or "
1080 "two arguments\n");
1081 return -1;
1082 }
1083
1084 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1085 printf("Invalid GET_CAPABILITY command: second argument, "
1086 "if any, must be 'strict'\n");
1087 return -1;
1088 }
1089
1090 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1091 (argc == 2) ? " strict" : "");
1092 if (res < 0 || (size_t) res >= sizeof(cmd))
1093 return -1;
1094 cmd[sizeof(cmd) - 1] = '\0';
1095
1096 return wpa_ctrl_command(ctrl, cmd);
1097}
1098
1099
1100static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1101{
1102 printf("Available interfaces:\n");
1103 return wpa_ctrl_command(ctrl, "INTERFACES");
1104}
1105
1106
1107static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1108{
1109 if (argc < 1) {
1110 wpa_cli_list_interfaces(ctrl);
1111 return 0;
1112 }
1113
1114 wpa_cli_close_connection();
1115 os_free(ctrl_ifname);
1116 ctrl_ifname = os_strdup(argv[0]);
1117
1118 if (wpa_cli_open_connection(ctrl_ifname)) {
1119 printf("Connected to interface '%s.\n", ctrl_ifname);
1120 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1121 wpa_cli_attached = 1;
1122 } else {
1123 printf("Warning: Failed to attach to "
1124 "wpa_supplicant.\n");
1125 }
1126 } else {
1127 printf("Could not connect to interface '%s' - re-trying\n",
1128 ctrl_ifname);
1129 }
1130 return 0;
1131}
1132
1133
1134static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1135 char *argv[])
1136{
1137 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1138}
1139
1140
1141static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1142 char *argv[])
1143{
1144 return wpa_ctrl_command(ctrl, "TERMINATE");
1145}
1146
1147
1148static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1149 char *argv[])
1150{
1151 char cmd[256];
1152 int res;
1153
1154 if (argc < 1) {
1155 printf("Invalid INTERFACE_ADD command: needs at least one "
1156 "argument (interface name)\n"
1157 "All arguments: ifname confname driver ctrl_interface "
1158 "driver_param bridge_name\n");
1159 return -1;
1160 }
1161
1162 /*
1163 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1164 * <driver_param>TAB<bridge_name>
1165 */
1166 res = os_snprintf(cmd, sizeof(cmd),
1167 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1168 argv[0],
1169 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1170 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1171 argc > 5 ? argv[5] : "");
1172 if (res < 0 || (size_t) res >= sizeof(cmd))
1173 return -1;
1174 cmd[sizeof(cmd) - 1] = '\0';
1175 return wpa_ctrl_command(ctrl, cmd);
1176}
1177
1178
1179static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1180 char *argv[])
1181{
1182 char cmd[128];
1183 int res;
1184
1185 if (argc != 1) {
1186 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1187 "(interface name)\n");
1188 return -1;
1189 }
1190
1191 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1192 if (res < 0 || (size_t) res >= sizeof(cmd))
1193 return -1;
1194 cmd[sizeof(cmd) - 1] = '\0';
1195 return wpa_ctrl_command(ctrl, cmd);
1196}
1197
1198
4b4a8ae5
JM
1199static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1200 char *argv[])
1201{
1202 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1203}
1204
1205
e653b622
JM
1206#ifdef CONFIG_AP
1207static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1208{
1209 char buf[64];
1210 if (argc != 1) {
1211 printf("Invalid 'sta' command - exactly one argument, STA "
1212 "address, is required.\n");
1213 return -1;
1214 }
1215 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
1216 return wpa_ctrl_command(ctrl, buf);
1217}
1218
1219
1220static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1221 char *addr, size_t addr_len)
1222{
1223 char buf[4096], *pos;
1224 size_t len;
1225 int ret;
1226
1227 if (ctrl_conn == NULL) {
1228 printf("Not connected to hostapd - command dropped.\n");
1229 return -1;
1230 }
1231 len = sizeof(buf) - 1;
1232 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1233 wpa_cli_msg_cb);
1234 if (ret == -2) {
1235 printf("'%s' command timed out.\n", cmd);
1236 return -2;
1237 } else if (ret < 0) {
1238 printf("'%s' command failed.\n", cmd);
1239 return -1;
1240 }
1241
1242 buf[len] = '\0';
1243 if (memcmp(buf, "FAIL", 4) == 0)
1244 return -1;
1245 printf("%s", buf);
1246
1247 pos = buf;
1248 while (*pos != '\0' && *pos != '\n')
1249 pos++;
1250 *pos = '\0';
1251 os_strlcpy(addr, buf, addr_len);
1252 return 0;
1253}
1254
1255
1256static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1257{
1258 char addr[32], cmd[64];
1259
1260 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1261 return 0;
1262 do {
1263 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1264 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1265
1266 return -1;
1267}
1268#endif /* CONFIG_AP */
1269
1270
40fd868c
ER
1271enum wpa_cli_cmd_flags {
1272 cli_cmd_flag_none = 0x00,
1273 cli_cmd_flag_sensitive = 0x01
1274};
1275
6fc6879b
JM
1276struct wpa_cli_cmd {
1277 const char *cmd;
1278 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
40fd868c 1279 enum wpa_cli_cmd_flags flags;
dfa141b1 1280 const char *usage;
6fc6879b
JM
1281};
1282
1283static struct wpa_cli_cmd wpa_cli_commands[] = {
40fd868c 1284 { "status", wpa_cli_cmd_status,
dfa141b1
ER
1285 cli_cmd_flag_none,
1286 "[verbose] = get current WPA/EAPOL/EAP status" },
40fd868c 1287 { "ping", wpa_cli_cmd_ping,
dfa141b1
ER
1288 cli_cmd_flag_none,
1289 "= pings wpa_supplicant" },
40fd868c 1290 { "mib", wpa_cli_cmd_mib,
dfa141b1
ER
1291 cli_cmd_flag_none,
1292 "= get MIB variables (dot1x, dot11)" },
40fd868c 1293 { "help", wpa_cli_cmd_help,
dfa141b1
ER
1294 cli_cmd_flag_none,
1295 "= show this usage help" },
40fd868c 1296 { "interface", wpa_cli_cmd_interface,
dfa141b1
ER
1297 cli_cmd_flag_none,
1298 "[ifname] = show interfaces/select interface" },
40fd868c 1299 { "level", wpa_cli_cmd_level,
dfa141b1
ER
1300 cli_cmd_flag_none,
1301 "<debug level> = change debug level" },
40fd868c 1302 { "license", wpa_cli_cmd_license,
dfa141b1
ER
1303 cli_cmd_flag_none,
1304 "= show full wpa_cli license" },
40fd868c 1305 { "quit", wpa_cli_cmd_quit,
dfa141b1
ER
1306 cli_cmd_flag_none,
1307 "= exit wpa_cli" },
40fd868c 1308 { "set", wpa_cli_cmd_set,
dfa141b1
ER
1309 cli_cmd_flag_none,
1310 "= set variables (shows list of variables when run without "
1311 "arguments)" },
40fd868c 1312 { "logon", wpa_cli_cmd_logon,
dfa141b1
ER
1313 cli_cmd_flag_none,
1314 "= IEEE 802.1X EAPOL state machine logon" },
40fd868c 1315 { "logoff", wpa_cli_cmd_logoff,
dfa141b1
ER
1316 cli_cmd_flag_none,
1317 "= IEEE 802.1X EAPOL state machine logoff" },
40fd868c 1318 { "pmksa", wpa_cli_cmd_pmksa,
dfa141b1
ER
1319 cli_cmd_flag_none,
1320 "= show PMKSA cache" },
40fd868c 1321 { "reassociate", wpa_cli_cmd_reassociate,
dfa141b1
ER
1322 cli_cmd_flag_none,
1323 "= force reassociation" },
40fd868c 1324 { "preauthenticate", wpa_cli_cmd_preauthenticate,
dfa141b1
ER
1325 cli_cmd_flag_none,
1326 "<BSSID> = force preauthentication" },
40fd868c 1327 { "identity", wpa_cli_cmd_identity,
dfa141b1
ER
1328 cli_cmd_flag_none,
1329 "<network id> <identity> = configure identity for an SSID" },
40fd868c 1330 { "password", wpa_cli_cmd_password,
dfa141b1
ER
1331 cli_cmd_flag_sensitive,
1332 "<network id> <password> = configure password for an SSID" },
40fd868c 1333 { "new_password", wpa_cli_cmd_new_password,
dfa141b1
ER
1334 cli_cmd_flag_sensitive,
1335 "<network id> <password> = change password for an SSID" },
40fd868c 1336 { "pin", wpa_cli_cmd_pin,
dfa141b1
ER
1337 cli_cmd_flag_sensitive,
1338 "<network id> <pin> = configure pin for an SSID" },
40fd868c 1339 { "otp", wpa_cli_cmd_otp,
dfa141b1
ER
1340 cli_cmd_flag_sensitive,
1341 "<network id> <password> = configure one-time-password for an SSID"
1342 },
40fd868c 1343 { "passphrase", wpa_cli_cmd_passphrase,
dfa141b1
ER
1344 cli_cmd_flag_sensitive,
1345 "<network id> <passphrase> = configure private key passphrase\n"
1346 " for an SSID" },
40fd868c 1347 { "bssid", wpa_cli_cmd_bssid,
dfa141b1
ER
1348 cli_cmd_flag_none,
1349 "<network id> <BSSID> = set preferred BSSID for an SSID" },
40fd868c 1350 { "list_networks", wpa_cli_cmd_list_networks,
dfa141b1
ER
1351 cli_cmd_flag_none,
1352 "= list configured networks" },
40fd868c 1353 { "select_network", wpa_cli_cmd_select_network,
dfa141b1
ER
1354 cli_cmd_flag_none,
1355 "<network id> = select a network (disable others)" },
40fd868c 1356 { "enable_network", wpa_cli_cmd_enable_network,
dfa141b1
ER
1357 cli_cmd_flag_none,
1358 "<network id> = enable a network" },
40fd868c 1359 { "disable_network", wpa_cli_cmd_disable_network,
dfa141b1
ER
1360 cli_cmd_flag_none,
1361 "<network id> = disable a network" },
40fd868c 1362 { "add_network", wpa_cli_cmd_add_network,
dfa141b1
ER
1363 cli_cmd_flag_none,
1364 "= add a network" },
40fd868c 1365 { "remove_network", wpa_cli_cmd_remove_network,
dfa141b1
ER
1366 cli_cmd_flag_none,
1367 "<network id> = remove a network" },
40fd868c 1368 { "set_network", wpa_cli_cmd_set_network,
dfa141b1
ER
1369 cli_cmd_flag_sensitive,
1370 "<network id> <variable> <value> = set network variables (shows\n"
1371 " list of variables when run without arguments)" },
40fd868c 1372 { "get_network", wpa_cli_cmd_get_network,
dfa141b1
ER
1373 cli_cmd_flag_none,
1374 "<network id> <variable> = get network variables" },
40fd868c 1375 { "save_config", wpa_cli_cmd_save_config,
dfa141b1
ER
1376 cli_cmd_flag_none,
1377 "= save the current configuration" },
40fd868c 1378 { "disconnect", wpa_cli_cmd_disconnect,
dfa141b1
ER
1379 cli_cmd_flag_none,
1380 "= disconnect and wait for reassociate/reconnect command before\n"
1381 " connecting" },
40fd868c 1382 { "reconnect", wpa_cli_cmd_reconnect,
dfa141b1
ER
1383 cli_cmd_flag_none,
1384 "= like reassociate, but only takes effect if already disconnected"
1385 },
40fd868c 1386 { "scan", wpa_cli_cmd_scan,
dfa141b1
ER
1387 cli_cmd_flag_none,
1388 "= request new BSS scan" },
40fd868c 1389 { "scan_results", wpa_cli_cmd_scan_results,
dfa141b1
ER
1390 cli_cmd_flag_none,
1391 "= get latest scan results" },
40fd868c 1392 { "bss", wpa_cli_cmd_bss,
dfa141b1
ER
1393 cli_cmd_flag_none,
1394 "<<idx> | <bssid>> = get detailed scan result info" },
40fd868c 1395 { "get_capability", wpa_cli_cmd_get_capability,
dfa141b1
ER
1396 cli_cmd_flag_none,
1397 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
40fd868c 1398 { "reconfigure", wpa_cli_cmd_reconfigure,
dfa141b1
ER
1399 cli_cmd_flag_none,
1400 "= force wpa_supplicant to re-read its configuration file" },
40fd868c 1401 { "terminate", wpa_cli_cmd_terminate,
dfa141b1
ER
1402 cli_cmd_flag_none,
1403 "= terminate wpa_supplicant" },
40fd868c 1404 { "interface_add", wpa_cli_cmd_interface_add,
dfa141b1
ER
1405 cli_cmd_flag_none,
1406 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1407 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
1408 " are optional" },
40fd868c 1409 { "interface_remove", wpa_cli_cmd_interface_remove,
dfa141b1
ER
1410 cli_cmd_flag_none,
1411 "<ifname> = removes the interface" },
40fd868c 1412 { "interface_list", wpa_cli_cmd_interface_list,
dfa141b1
ER
1413 cli_cmd_flag_none,
1414 "= list available interfaces" },
40fd868c 1415 { "ap_scan", wpa_cli_cmd_ap_scan,
dfa141b1
ER
1416 cli_cmd_flag_none,
1417 "<value> = set ap_scan parameter" },
40fd868c 1418 { "stkstart", wpa_cli_cmd_stkstart,
dfa141b1
ER
1419 cli_cmd_flag_none,
1420 "<addr> = request STK negotiation with <addr>" },
40fd868c 1421 { "ft_ds", wpa_cli_cmd_ft_ds,
dfa141b1
ER
1422 cli_cmd_flag_none,
1423 "<addr> = request over-the-DS FT with <addr>" },
40fd868c 1424 { "wps_pbc", wpa_cli_cmd_wps_pbc,
dfa141b1
ER
1425 cli_cmd_flag_none,
1426 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
40fd868c 1427 { "wps_pin", wpa_cli_cmd_wps_pin,
dfa141b1
ER
1428 cli_cmd_flag_sensitive,
1429 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1430 "hardcoded)" },
116f7bb0 1431#ifdef CONFIG_WPS_OOB
46bdb83a
MH
1432 { "wps_oob", wpa_cli_cmd_wps_oob,
1433 cli_cmd_flag_sensitive,
e1ee6b60 1434 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
116f7bb0 1435#endif /* CONFIG_WPS_OOB */
40fd868c 1436 { "wps_reg", wpa_cli_cmd_wps_reg,
dfa141b1
ER
1437 cli_cmd_flag_sensitive,
1438 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
e9bcfebf
JM
1439 { "wps_er_start", wpa_cli_cmd_wps_er_start,
1440 cli_cmd_flag_none,
1441 "= start Wi-Fi Protected Setup External Registrar" },
1442 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
1443 cli_cmd_flag_none,
1444 "= stop Wi-Fi Protected Setup External Registrar" },
72df2f5f
JM
1445 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
1446 cli_cmd_flag_sensitive,
1447 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
11ef8d35
JM
1448 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
1449 cli_cmd_flag_none,
1450 "<addr> = request RSN authentication with <addr> in IBSS" },
e653b622
JM
1451#ifdef CONFIG_AP
1452 { "sta", wpa_cli_cmd_sta,
1453 cli_cmd_flag_none,
1454 "<addr> = get information about an associated station (AP)" },
1455 { "all_sta", wpa_cli_cmd_all_sta,
1456 cli_cmd_flag_none,
1457 "= get information about all associated stations (AP)" },
1458#endif /* CONFIG_AP */
dfa141b1 1459 { NULL, NULL, cli_cmd_flag_none, NULL }
6fc6879b
JM
1460};
1461
1462
dfa141b1
ER
1463/*
1464 * Prints command usage, lines are padded with the specified string.
1465 */
1466static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1467{
1468 char c;
1469 size_t n;
1470
1471 printf("%s%s ", pad, cmd->cmd);
1472 for (n = 0; (c = cmd->usage[n]); n++) {
1473 printf("%c", c);
1474 if (c == '\n')
1475 printf("%s", pad);
1476 }
1477 printf("\n");
1478}
1479
1480
1481static void print_help(void)
1482{
1483 int n;
1484 printf("commands:\n");
1485 for (n = 0; wpa_cli_commands[n].cmd; n++)
1486 print_cmd_help(&wpa_cli_commands[n], " ");
1487}
1488
1489
40fd868c
ER
1490#ifdef CONFIG_READLINE
1491static int cmd_has_sensitive_data(const char *cmd)
1492{
1493 const char *c, *delim;
1494 int n;
1495 size_t len;
1496
1497 delim = os_strchr(cmd, ' ');
1498 if (delim)
1499 len = delim - cmd;
1500 else
1501 len = os_strlen(cmd);
1502
1503 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1504 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1505 return (wpa_cli_commands[n].flags &
1506 cli_cmd_flag_sensitive);
1507 }
1508 return 0;
1509}
1510#endif /* CONFIG_READLINE */
1511
1512
6fc6879b
JM
1513static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1514{
1515 struct wpa_cli_cmd *cmd, *match = NULL;
1516 int count;
1517 int ret = 0;
1518
1519 count = 0;
1520 cmd = wpa_cli_commands;
1521 while (cmd->cmd) {
1522 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1523 {
1524 match = cmd;
1525 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1526 /* we have an exact match */
1527 count = 1;
1528 break;
1529 }
1530 count++;
1531 }
1532 cmd++;
1533 }
1534
1535 if (count > 1) {
1536 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1537 cmd = wpa_cli_commands;
1538 while (cmd->cmd) {
1539 if (os_strncasecmp(cmd->cmd, argv[0],
1540 os_strlen(argv[0])) == 0) {
1541 printf(" %s", cmd->cmd);
1542 }
1543 cmd++;
1544 }
1545 printf("\n");
1546 ret = 1;
1547 } else if (count == 0) {
1548 printf("Unknown command '%s'\n", argv[0]);
1549 ret = 1;
1550 } else {
1551 ret = match->handler(ctrl, argc - 1, &argv[1]);
1552 }
1553
1554 return ret;
1555}
1556
1557
1558static int str_match(const char *a, const char *b)
1559{
1560 return os_strncmp(a, b, os_strlen(b)) == 0;
1561}
1562
1563
1564static int wpa_cli_exec(const char *program, const char *arg1,
1565 const char *arg2)
1566{
1567 char *cmd;
1568 size_t len;
1569 int res;
308a4ec8 1570 int ret = 0;
6fc6879b
JM
1571
1572 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1573 cmd = os_malloc(len);
1574 if (cmd == NULL)
1575 return -1;
1576 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1577 if (res < 0 || (size_t) res >= len) {
1578 os_free(cmd);
1579 return -1;
1580 }
1581 cmd[len - 1] = '\0';
1582#ifndef _WIN32_WCE
308a4ec8
JM
1583 if (system(cmd) < 0)
1584 ret = -1;
6fc6879b
JM
1585#endif /* _WIN32_WCE */
1586 os_free(cmd);
1587
308a4ec8 1588 return ret;
6fc6879b
JM
1589}
1590
1591
1592static void wpa_cli_action_process(const char *msg)
1593{
1594 const char *pos;
1595 char *copy = NULL, *id, *pos2;
1596
1597 pos = msg;
1598 if (*pos == '<') {
1599 /* skip priority */
1600 pos = os_strchr(pos, '>');
1601 if (pos)
1602 pos++;
1603 else
1604 pos = msg;
1605 }
1606
1607 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1608 int new_id = -1;
1609 os_unsetenv("WPA_ID");
1610 os_unsetenv("WPA_ID_STR");
1611 os_unsetenv("WPA_CTRL_DIR");
1612
1613 pos = os_strstr(pos, "[id=");
1614 if (pos)
1615 copy = os_strdup(pos + 4);
1616
1617 if (copy) {
1618 pos2 = id = copy;
1619 while (*pos2 && *pos2 != ' ')
1620 pos2++;
1621 *pos2++ = '\0';
1622 new_id = atoi(id);
1623 os_setenv("WPA_ID", id, 1);
1624 while (*pos2 && *pos2 != '=')
1625 pos2++;
1626 if (*pos2 == '=')
1627 pos2++;
1628 id = pos2;
1629 while (*pos2 && *pos2 != ']')
1630 pos2++;
1631 *pos2 = '\0';
1632 os_setenv("WPA_ID_STR", id, 1);
1633 os_free(copy);
1634 }
1635
1636 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1637
1638 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1639 wpa_cli_connected = 1;
1640 wpa_cli_last_id = new_id;
1641 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1642 }
1643 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1644 if (wpa_cli_connected) {
1645 wpa_cli_connected = 0;
1646 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1647 }
1648 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1649 printf("wpa_supplicant is terminating - stop monitoring\n");
1650 wpa_cli_quit = 1;
1651 }
1652}
1653
1654
1655#ifndef CONFIG_ANSI_C_EXTRA
1656static void wpa_cli_action_cb(char *msg, size_t len)
1657{
1658 wpa_cli_action_process(msg);
1659}
1660#endif /* CONFIG_ANSI_C_EXTRA */
1661
1662
1663static void wpa_cli_reconnect(void)
1664{
1665 wpa_cli_close_connection();
1666 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1667 if (ctrl_conn) {
1668 printf("Connection to wpa_supplicant re-established\n");
1669 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1670 wpa_cli_attached = 1;
1671 } else {
1672 printf("Warning: Failed to attach to "
1673 "wpa_supplicant.\n");
1674 }
1675 }
1676}
1677
1678
1679static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1680 int action_monitor)
1681{
1682 int first = 1;
1683 if (ctrl_conn == NULL) {
1684 wpa_cli_reconnect();
1685 return;
1686 }
1687 while (wpa_ctrl_pending(ctrl) > 0) {
1688 char buf[256];
1689 size_t len = sizeof(buf) - 1;
1690 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1691 buf[len] = '\0';
1692 if (action_monitor)
1693 wpa_cli_action_process(buf);
1694 else {
1695 if (in_read && first)
1696 printf("\n");
1697 first = 0;
1698 printf("%s\n", buf);
1699 }
1700 } else {
1701 printf("Could not read pending message.\n");
1702 break;
1703 }
1704 }
1705
1706 if (wpa_ctrl_pending(ctrl) < 0) {
1707 printf("Connection to wpa_supplicant lost - trying to "
1708 "reconnect\n");
1709 wpa_cli_reconnect();
1710 }
1711}
1712
1713
1714#ifdef CONFIG_READLINE
1715static char * wpa_cli_cmd_gen(const char *text, int state)
1716{
1717 static int i, len;
1718 const char *cmd;
1719
1720 if (state == 0) {
1721 i = 0;
1722 len = os_strlen(text);
1723 }
1724
1725 while ((cmd = wpa_cli_commands[i].cmd)) {
1726 i++;
1727 if (os_strncasecmp(cmd, text, len) == 0)
1728 return os_strdup(cmd);
1729 }
1730
1731 return NULL;
1732}
1733
1734
1735static char * wpa_cli_dummy_gen(const char *text, int state)
1736{
1737 return NULL;
1738}
1739
1740
1741static char ** wpa_cli_completion(const char *text, int start, int end)
1742{
1743 return rl_completion_matches(text, start == 0 ?
1744 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1745}
1746#endif /* CONFIG_READLINE */
1747
1748
1749static void wpa_cli_interactive(void)
1750{
1751#define max_args 10
1752 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1753 int argc;
1754#ifdef CONFIG_READLINE
1755 char *home, *hfile = NULL;
1756#endif /* CONFIG_READLINE */
1757
1758 printf("\nInteractive mode\n\n");
1759
1760#ifdef CONFIG_READLINE
1761 rl_attempted_completion_function = wpa_cli_completion;
1762 home = getenv("HOME");
1763 if (home) {
1764 const char *fname = ".wpa_cli_history";
1765 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1766 hfile = os_malloc(hfile_len);
1767 if (hfile) {
1768 int res;
1769 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1770 fname);
1771 if (res >= 0 && res < hfile_len) {
1772 hfile[hfile_len - 1] = '\0';
1773 read_history(hfile);
1774 stifle_history(100);
1775 }
1776 }
1777 }
1778#endif /* CONFIG_READLINE */
1779
1780 do {
1781 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1782#ifndef CONFIG_NATIVE_WINDOWS
1cc84c1c 1783 alarm(ping_interval);
6fc6879b
JM
1784#endif /* CONFIG_NATIVE_WINDOWS */
1785#ifdef CONFIG_READLINE
1786 cmd = readline("> ");
1787 if (cmd && *cmd) {
1788 HIST_ENTRY *h;
1789 while (next_history())
1790 ;
1791 h = previous_history();
1792 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1793 add_history(cmd);
1794 next_history();
1795 }
1796#else /* CONFIG_READLINE */
1797 printf("> ");
1798 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1799#endif /* CONFIG_READLINE */
1800#ifndef CONFIG_NATIVE_WINDOWS
1801 alarm(0);
1802#endif /* CONFIG_NATIVE_WINDOWS */
1803 if (cmd == NULL)
1804 break;
1805 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1806 pos = cmd;
1807 while (*pos != '\0') {
1808 if (*pos == '\n') {
1809 *pos = '\0';
1810 break;
1811 }
1812 pos++;
1813 }
1814 argc = 0;
1815 pos = cmd;
1816 for (;;) {
1817 while (*pos == ' ')
1818 pos++;
1819 if (*pos == '\0')
1820 break;
1821 argv[argc] = pos;
1822 argc++;
1823 if (argc == max_args)
1824 break;
1825 if (*pos == '"') {
1826 char *pos2 = os_strrchr(pos, '"');
1827 if (pos2)
1828 pos = pos2 + 1;
1829 }
1830 while (*pos != '\0' && *pos != ' ')
1831 pos++;
1832 if (*pos == ' ')
1833 *pos++ = '\0';
1834 }
1835 if (argc)
1836 wpa_request(ctrl_conn, argc, argv);
1837
1838 if (cmd != cmdbuf)
1839 os_free(cmd);
1840 } while (!wpa_cli_quit);
1841
1842#ifdef CONFIG_READLINE
1843 if (hfile) {
1844 /* Save command history, excluding lines that may contain
1845 * passwords. */
1846 HIST_ENTRY *h;
1847 history_set_pos(0);
413653e8 1848 while ((h = current_history())) {
6fc6879b
JM
1849 char *p = h->line;
1850 while (*p == ' ' || *p == '\t')
1851 p++;
40fd868c 1852 if (cmd_has_sensitive_data(p)) {
6fc6879b
JM
1853 h = remove_history(where_history());
1854 if (h) {
1855 os_free(h->line);
1856 os_free(h->data);
1857 os_free(h);
413653e8
ER
1858 } else
1859 next_history();
1860 } else
1861 next_history();
6fc6879b
JM
1862 }
1863 write_history(hfile);
1864 os_free(hfile);
1865 }
1866#endif /* CONFIG_READLINE */
1867}
1868
1869
1870static void wpa_cli_action(struct wpa_ctrl *ctrl)
1871{
1872#ifdef CONFIG_ANSI_C_EXTRA
1873 /* TODO: ANSI C version(?) */
1874 printf("Action processing not supported in ANSI C build.\n");
1875#else /* CONFIG_ANSI_C_EXTRA */
1876 fd_set rfds;
1877 int fd, res;
1878 struct timeval tv;
1879 char buf[256]; /* note: large enough to fit in unsolicited messages */
1880 size_t len;
1881
1882 fd = wpa_ctrl_get_fd(ctrl);
1883
1884 while (!wpa_cli_quit) {
1885 FD_ZERO(&rfds);
1886 FD_SET(fd, &rfds);
1cc84c1c 1887 tv.tv_sec = ping_interval;
6fc6879b
JM
1888 tv.tv_usec = 0;
1889 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1890 if (res < 0 && errno != EINTR) {
1891 perror("select");
1892 break;
1893 }
1894
1895 if (FD_ISSET(fd, &rfds))
1896 wpa_cli_recv_pending(ctrl, 0, 1);
1897 else {
1898 /* verify that connection is still working */
1899 len = sizeof(buf) - 1;
1900 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1901 wpa_cli_action_cb) < 0 ||
1902 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1903 printf("wpa_supplicant did not reply to PING "
1904 "command - exiting\n");
1905 break;
1906 }
1907 }
1908 }
1909#endif /* CONFIG_ANSI_C_EXTRA */
1910}
1911
1912
1913static void wpa_cli_cleanup(void)
1914{
1915 wpa_cli_close_connection();
1916 if (pid_file)
1917 os_daemonize_terminate(pid_file);
1918
1919 os_program_deinit();
1920}
1921
1922static void wpa_cli_terminate(int sig)
1923{
1924 wpa_cli_cleanup();
1925 exit(0);
1926}
1927
1928
1929#ifndef CONFIG_NATIVE_WINDOWS
1930static void wpa_cli_alarm(int sig)
1931{
1932 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1933 printf("Connection to wpa_supplicant lost - trying to "
1934 "reconnect\n");
1935 wpa_cli_close_connection();
1936 }
1937 if (!ctrl_conn)
1938 wpa_cli_reconnect();
1939 if (ctrl_conn)
1940 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1cc84c1c 1941 alarm(ping_interval);
6fc6879b
JM
1942}
1943#endif /* CONFIG_NATIVE_WINDOWS */
1944
1945
1946static char * wpa_cli_get_default_ifname(void)
1947{
1948 char *ifname = NULL;
1949
1950#ifdef CONFIG_CTRL_IFACE_UNIX
1951 struct dirent *dent;
1952 DIR *dir = opendir(ctrl_iface_dir);
1953 if (!dir)
1954 return NULL;
1955 while ((dent = readdir(dir))) {
1956#ifdef _DIRENT_HAVE_D_TYPE
1957 /*
1958 * Skip the file if it is not a socket. Also accept
1959 * DT_UNKNOWN (0) in case the C library or underlying
1960 * file system does not support d_type.
1961 */
1962 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1963 continue;
1964#endif /* _DIRENT_HAVE_D_TYPE */
1965 if (os_strcmp(dent->d_name, ".") == 0 ||
1966 os_strcmp(dent->d_name, "..") == 0)
1967 continue;
1968 printf("Selected interface '%s'\n", dent->d_name);
1969 ifname = os_strdup(dent->d_name);
1970 break;
1971 }
1972 closedir(dir);
1973#endif /* CONFIG_CTRL_IFACE_UNIX */
1974
1975#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1976 char buf[2048], *pos;
1977 size_t len;
1978 struct wpa_ctrl *ctrl;
1979 int ret;
1980
1981 ctrl = wpa_ctrl_open(NULL);
1982 if (ctrl == NULL)
1983 return NULL;
1984
1985 len = sizeof(buf) - 1;
1986 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1987 if (ret >= 0) {
1988 buf[len] = '\0';
1989 pos = os_strchr(buf, '\n');
1990 if (pos)
1991 *pos = '\0';
1992 ifname = os_strdup(buf);
1993 }
1994 wpa_ctrl_close(ctrl);
1995#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1996
1997 return ifname;
1998}
1999
2000
2001int main(int argc, char *argv[])
2002{
2003 int interactive;
2004 int warning_displayed = 0;
2005 int c;
2006 int daemonize = 0;
2007 int ret = 0;
2008 const char *global = NULL;
2009
2010 if (os_program_init())
2011 return -1;
2012
2013 for (;;) {
1cc84c1c 2014 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
6fc6879b
JM
2015 if (c < 0)
2016 break;
2017 switch (c) {
2018 case 'a':
2019 action_file = optarg;
2020 break;
2021 case 'B':
2022 daemonize = 1;
2023 break;
2024 case 'g':
2025 global = optarg;
2026 break;
1cc84c1c
JM
2027 case 'G':
2028 ping_interval = atoi(optarg);
2029 break;
6fc6879b
JM
2030 case 'h':
2031 usage();
2032 return 0;
2033 case 'v':
2034 printf("%s\n", wpa_cli_version);
2035 return 0;
2036 case 'i':
2037 os_free(ctrl_ifname);
2038 ctrl_ifname = os_strdup(optarg);
2039 break;
2040 case 'p':
2041 ctrl_iface_dir = optarg;
2042 break;
2043 case 'P':
2044 pid_file = optarg;
2045 break;
2046 default:
2047 usage();
2048 return -1;
2049 }
2050 }
2051
2052 interactive = (argc == optind) && (action_file == NULL);
2053
2054 if (interactive)
2055 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
2056
2057 if (global) {
2058#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2059 ctrl_conn = wpa_ctrl_open(NULL);
2060#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2061 ctrl_conn = wpa_ctrl_open(global);
2062#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2063 if (ctrl_conn == NULL) {
2064 perror("Failed to connect to wpa_supplicant - "
2065 "wpa_ctrl_open");
2066 return -1;
2067 }
2068 }
2069
2070 for (; !global;) {
2071 if (ctrl_ifname == NULL)
2072 ctrl_ifname = wpa_cli_get_default_ifname();
2073 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
2074 if (ctrl_conn) {
2075 if (warning_displayed)
2076 printf("Connection established.\n");
2077 break;
2078 }
2079
2080 if (!interactive) {
2081 perror("Failed to connect to wpa_supplicant - "
2082 "wpa_ctrl_open");
2083 return -1;
2084 }
2085
2086 if (!warning_displayed) {
2087 printf("Could not connect to wpa_supplicant - "
2088 "re-trying\n");
2089 warning_displayed = 1;
2090 }
2091 os_sleep(1, 0);
2092 continue;
2093 }
2094
2095#ifndef _WIN32_WCE
2096 signal(SIGINT, wpa_cli_terminate);
2097 signal(SIGTERM, wpa_cli_terminate);
2098#endif /* _WIN32_WCE */
2099#ifndef CONFIG_NATIVE_WINDOWS
2100 signal(SIGALRM, wpa_cli_alarm);
2101#endif /* CONFIG_NATIVE_WINDOWS */
2102
2103 if (interactive || action_file) {
2104 if (wpa_ctrl_attach(ctrl_conn) == 0) {
2105 wpa_cli_attached = 1;
2106 } else {
2107 printf("Warning: Failed to attach to "
2108 "wpa_supplicant.\n");
2109 if (!interactive)
2110 return -1;
2111 }
2112 }
2113
2114 if (daemonize && os_daemonize(pid_file))
2115 return -1;
2116
2117 if (interactive)
2118 wpa_cli_interactive();
2119 else if (action_file)
2120 wpa_cli_action(ctrl_conn);
2121 else
2122 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
2123
2124 os_free(ctrl_ifname);
2125 wpa_cli_cleanup();
2126
2127 return ret;
2128}
2129
2130#else /* CONFIG_CTRL_IFACE */
2131int main(int argc, char *argv[])
2132{
2133 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
2134 return -1;
2135}
2136#endif /* CONFIG_CTRL_IFACE */