]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
Split scan processing for RSN preauthentication into parts
[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
564cd7fa
JM
575static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc,
576 char *argv[])
577{
578 char cmd[256];
579 int res;
580
581 if (argc != 1) {
582 printf("Invalid WPS_ER_PBC command: need one argument:\n"
583 "- UUID: Specify the Enrollee\n");
584 return -1;
585 }
586
587 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_PBC %s",
588 argv[0]);
589 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
590 printf("Too long WPS_ER_PBC command.\n");
591 return -1;
592 }
593 return wpa_ctrl_command(ctrl, cmd);
594}
595
596
e64dcfd5
JM
597static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc,
598 char *argv[])
599{
600 char cmd[256];
601 int res;
602
603 if (argc != 2) {
604 printf("Invalid WPS_ER_LEARN command: need two arguments:\n"
605 "- UUID: specify which AP to use\n"
606 "- PIN: AP PIN\n");
607 return -1;
608 }
609
610 res = os_snprintf(cmd, sizeof(cmd), "WPS_ER_LEARN %s %s",
611 argv[0], argv[1]);
612 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
613 printf("Too long WPS_ER_LEARN command.\n");
614 return -1;
615 }
616 return wpa_ctrl_command(ctrl, cmd);
617}
618
619
11ef8d35
JM
620static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
621{
622 char cmd[256];
623 int res;
624
625 if (argc != 1) {
626 printf("Invalid IBSS_RSN command: needs one argument "
627 "(Peer STA MAC address)\n");
628 return -1;
629 }
630
631 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
632 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
633 printf("Too long IBSS_RSN command.\n");
634 return -1;
635 }
636 return wpa_ctrl_command(ctrl, cmd);
637}
638
639
6fc6879b
JM
640static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
641{
642 char cmd[256];
643 int res;
644
645 if (argc != 1) {
646 printf("Invalid LEVEL command: needs one argument (debug "
647 "level)\n");
648 return -1;
649 }
650 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
651 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
652 printf("Too long LEVEL command.\n");
653 return -1;
654 }
655 return wpa_ctrl_command(ctrl, cmd);
656}
657
658
659static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
660{
661 char cmd[256], *pos, *end;
662 int i, ret;
663
664 if (argc < 2) {
665 printf("Invalid IDENTITY command: needs two arguments "
666 "(network id and identity)\n");
667 return -1;
668 }
669
670 end = cmd + sizeof(cmd);
671 pos = cmd;
672 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
673 argv[0], argv[1]);
674 if (ret < 0 || ret >= end - pos) {
675 printf("Too long IDENTITY command.\n");
676 return -1;
677 }
678 pos += ret;
679 for (i = 2; i < argc; i++) {
680 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
681 if (ret < 0 || ret >= end - pos) {
682 printf("Too long IDENTITY command.\n");
683 return -1;
684 }
685 pos += ret;
686 }
687
688 return wpa_ctrl_command(ctrl, cmd);
689}
690
691
692static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
693{
694 char cmd[256], *pos, *end;
695 int i, ret;
696
697 if (argc < 2) {
698 printf("Invalid PASSWORD command: needs two arguments "
699 "(network id and password)\n");
700 return -1;
701 }
702
703 end = cmd + sizeof(cmd);
704 pos = cmd;
705 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
706 argv[0], argv[1]);
707 if (ret < 0 || ret >= end - pos) {
708 printf("Too long PASSWORD command.\n");
709 return -1;
710 }
711 pos += ret;
712 for (i = 2; i < argc; i++) {
713 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
714 if (ret < 0 || ret >= end - pos) {
715 printf("Too long PASSWORD command.\n");
716 return -1;
717 }
718 pos += ret;
719 }
720
721 return wpa_ctrl_command(ctrl, cmd);
722}
723
724
725static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
726 char *argv[])
727{
728 char cmd[256], *pos, *end;
729 int i, ret;
730
731 if (argc < 2) {
732 printf("Invalid NEW_PASSWORD command: needs two arguments "
733 "(network id and password)\n");
734 return -1;
735 }
736
737 end = cmd + sizeof(cmd);
738 pos = cmd;
739 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
740 argv[0], argv[1]);
741 if (ret < 0 || ret >= end - pos) {
742 printf("Too long NEW_PASSWORD command.\n");
743 return -1;
744 }
745 pos += ret;
746 for (i = 2; i < argc; i++) {
747 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
748 if (ret < 0 || ret >= end - pos) {
749 printf("Too long NEW_PASSWORD command.\n");
750 return -1;
751 }
752 pos += ret;
753 }
754
755 return wpa_ctrl_command(ctrl, cmd);
756}
757
758
759static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
760{
761 char cmd[256], *pos, *end;
762 int i, ret;
763
764 if (argc < 2) {
765 printf("Invalid PIN command: needs two arguments "
766 "(network id and pin)\n");
767 return -1;
768 }
769
770 end = cmd + sizeof(cmd);
771 pos = cmd;
772 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
773 argv[0], argv[1]);
774 if (ret < 0 || ret >= end - pos) {
775 printf("Too long PIN command.\n");
776 return -1;
777 }
778 pos += ret;
779 for (i = 2; i < argc; i++) {
780 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
781 if (ret < 0 || ret >= end - pos) {
782 printf("Too long PIN command.\n");
783 return -1;
784 }
785 pos += ret;
786 }
787 return wpa_ctrl_command(ctrl, cmd);
788}
789
790
791static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
792{
793 char cmd[256], *pos, *end;
794 int i, ret;
795
796 if (argc < 2) {
797 printf("Invalid OTP command: needs two arguments (network "
798 "id and password)\n");
799 return -1;
800 }
801
802 end = cmd + sizeof(cmd);
803 pos = cmd;
804 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
805 argv[0], argv[1]);
806 if (ret < 0 || ret >= end - pos) {
807 printf("Too long OTP command.\n");
808 return -1;
809 }
810 pos += ret;
811 for (i = 2; i < argc; i++) {
812 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
813 if (ret < 0 || ret >= end - pos) {
814 printf("Too long OTP command.\n");
815 return -1;
816 }
817 pos += ret;
818 }
819
820 return wpa_ctrl_command(ctrl, cmd);
821}
822
823
824static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
825 char *argv[])
826{
827 char cmd[256], *pos, *end;
828 int i, ret;
829
830 if (argc < 2) {
831 printf("Invalid PASSPHRASE command: needs two arguments "
832 "(network id and passphrase)\n");
833 return -1;
834 }
835
836 end = cmd + sizeof(cmd);
837 pos = cmd;
838 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
839 argv[0], argv[1]);
840 if (ret < 0 || ret >= end - pos) {
841 printf("Too long PASSPHRASE command.\n");
842 return -1;
843 }
844 pos += ret;
845 for (i = 2; i < argc; i++) {
846 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
847 if (ret < 0 || ret >= end - pos) {
848 printf("Too long PASSPHRASE command.\n");
849 return -1;
850 }
851 pos += ret;
852 }
853
854 return wpa_ctrl_command(ctrl, cmd);
855}
856
857
858static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
859{
860 char cmd[256], *pos, *end;
861 int i, ret;
862
863 if (argc < 2) {
864 printf("Invalid BSSID command: needs two arguments (network "
865 "id and BSSID)\n");
866 return -1;
867 }
868
869 end = cmd + sizeof(cmd);
870 pos = cmd;
871 ret = os_snprintf(pos, end - pos, "BSSID");
872 if (ret < 0 || ret >= end - pos) {
873 printf("Too long BSSID command.\n");
874 return -1;
875 }
876 pos += ret;
877 for (i = 0; i < argc; i++) {
878 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
879 if (ret < 0 || ret >= end - pos) {
880 printf("Too long BSSID command.\n");
881 return -1;
882 }
883 pos += ret;
884 }
885
886 return wpa_ctrl_command(ctrl, cmd);
887}
888
889
890static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
891 char *argv[])
892{
893 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
894}
895
896
897static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
898 char *argv[])
899{
900 char cmd[32];
901 int res;
902
903 if (argc < 1) {
904 printf("Invalid SELECT_NETWORK command: needs one argument "
905 "(network id)\n");
906 return -1;
907 }
908
909 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
910 if (res < 0 || (size_t) res >= sizeof(cmd))
911 return -1;
912 cmd[sizeof(cmd) - 1] = '\0';
913
914 return wpa_ctrl_command(ctrl, cmd);
915}
916
917
918static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
919 char *argv[])
920{
921 char cmd[32];
922 int res;
923
924 if (argc < 1) {
925 printf("Invalid ENABLE_NETWORK command: needs one argument "
926 "(network id)\n");
927 return -1;
928 }
929
930 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
931 if (res < 0 || (size_t) res >= sizeof(cmd))
932 return -1;
933 cmd[sizeof(cmd) - 1] = '\0';
934
935 return wpa_ctrl_command(ctrl, cmd);
936}
937
938
939static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
940 char *argv[])
941{
942 char cmd[32];
943 int res;
944
945 if (argc < 1) {
946 printf("Invalid DISABLE_NETWORK command: needs one argument "
947 "(network id)\n");
948 return -1;
949 }
950
951 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
952 if (res < 0 || (size_t) res >= sizeof(cmd))
953 return -1;
954 cmd[sizeof(cmd) - 1] = '\0';
955
956 return wpa_ctrl_command(ctrl, cmd);
957}
958
959
960static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
961 char *argv[])
962{
963 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
964}
965
966
967static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
968 char *argv[])
969{
970 char cmd[32];
971 int res;
972
973 if (argc < 1) {
974 printf("Invalid REMOVE_NETWORK command: needs one argument "
975 "(network id)\n");
976 return -1;
977 }
978
979 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
980 if (res < 0 || (size_t) res >= sizeof(cmd))
981 return -1;
982 cmd[sizeof(cmd) - 1] = '\0';
983
984 return wpa_ctrl_command(ctrl, cmd);
985}
986
987
988static void wpa_cli_show_network_variables(void)
989{
990 printf("set_network variables:\n"
991 " ssid (network name, SSID)\n"
992 " psk (WPA passphrase or pre-shared key)\n"
993 " key_mgmt (key management protocol)\n"
994 " identity (EAP identity)\n"
995 " password (EAP password)\n"
996 " ...\n"
997 "\n"
998 "Note: Values are entered in the same format as the "
999 "configuration file is using,\n"
1000 "i.e., strings values need to be inside double quotation "
1001 "marks.\n"
1002 "For example: set_network 1 ssid \"network name\"\n"
1003 "\n"
1004 "Please see wpa_supplicant.conf documentation for full list "
1005 "of\navailable variables.\n");
1006}
1007
1008
1009static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
1010 char *argv[])
1011{
1012 char cmd[256];
1013 int res;
1014
1015 if (argc == 0) {
1016 wpa_cli_show_network_variables();
1017 return 0;
1018 }
1019
1020 if (argc != 3) {
1021 printf("Invalid SET_NETWORK command: needs three arguments\n"
1022 "(network id, variable name, and value)\n");
1023 return -1;
1024 }
1025
1026 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
1027 argv[0], argv[1], argv[2]);
1028 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1029 printf("Too long SET_NETWORK command.\n");
1030 return -1;
1031 }
1032 return wpa_ctrl_command(ctrl, cmd);
1033}
1034
1035
1036static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
1037 char *argv[])
1038{
1039 char cmd[256];
1040 int res;
1041
1042 if (argc == 0) {
1043 wpa_cli_show_network_variables();
1044 return 0;
1045 }
1046
1047 if (argc != 2) {
1048 printf("Invalid GET_NETWORK command: needs two arguments\n"
1049 "(network id and variable name)\n");
1050 return -1;
1051 }
1052
1053 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
1054 argv[0], argv[1]);
1055 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
1056 printf("Too long GET_NETWORK command.\n");
1057 return -1;
1058 }
1059 return wpa_ctrl_command(ctrl, cmd);
1060}
1061
1062
1063static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
1064 char *argv[])
1065{
1066 return wpa_ctrl_command(ctrl, "DISCONNECT");
1067}
1068
1069
1070static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
1071 char *argv[])
1072{
1073 return wpa_ctrl_command(ctrl, "RECONNECT");
1074}
1075
1076
1077static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
1078 char *argv[])
1079{
1080 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
1081}
1082
1083
1084static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
1085{
1086 return wpa_ctrl_command(ctrl, "SCAN");
1087}
1088
1089
1090static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
1091 char *argv[])
1092{
1093 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
1094}
1095
1096
1097static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
1098{
1099 char cmd[64];
1100 int res;
1101
1102 if (argc != 1) {
1103 printf("Invalid BSS command: need one argument (index or "
1104 "BSSID)\n");
1105 return -1;
1106 }
1107
1108 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
1109 if (res < 0 || (size_t) res >= sizeof(cmd))
1110 return -1;
1111 cmd[sizeof(cmd) - 1] = '\0';
1112
1113 return wpa_ctrl_command(ctrl, cmd);
1114}
1115
1116
1117static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
1118 char *argv[])
1119{
1120 char cmd[64];
1121 int res;
1122
1123 if (argc < 1 || argc > 2) {
1124 printf("Invalid GET_CAPABILITY command: need either one or "
1125 "two arguments\n");
1126 return -1;
1127 }
1128
1129 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
1130 printf("Invalid GET_CAPABILITY command: second argument, "
1131 "if any, must be 'strict'\n");
1132 return -1;
1133 }
1134
1135 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
1136 (argc == 2) ? " strict" : "");
1137 if (res < 0 || (size_t) res >= sizeof(cmd))
1138 return -1;
1139 cmd[sizeof(cmd) - 1] = '\0';
1140
1141 return wpa_ctrl_command(ctrl, cmd);
1142}
1143
1144
1145static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
1146{
1147 printf("Available interfaces:\n");
1148 return wpa_ctrl_command(ctrl, "INTERFACES");
1149}
1150
1151
1152static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1153{
1154 if (argc < 1) {
1155 wpa_cli_list_interfaces(ctrl);
1156 return 0;
1157 }
1158
1159 wpa_cli_close_connection();
1160 os_free(ctrl_ifname);
1161 ctrl_ifname = os_strdup(argv[0]);
1162
1163 if (wpa_cli_open_connection(ctrl_ifname)) {
1164 printf("Connected to interface '%s.\n", ctrl_ifname);
1165 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1166 wpa_cli_attached = 1;
1167 } else {
1168 printf("Warning: Failed to attach to "
1169 "wpa_supplicant.\n");
1170 }
1171 } else {
1172 printf("Could not connect to interface '%s' - re-trying\n",
1173 ctrl_ifname);
1174 }
1175 return 0;
1176}
1177
1178
1179static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1180 char *argv[])
1181{
1182 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1183}
1184
1185
1186static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1187 char *argv[])
1188{
1189 return wpa_ctrl_command(ctrl, "TERMINATE");
1190}
1191
1192
1193static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1194 char *argv[])
1195{
1196 char cmd[256];
1197 int res;
1198
1199 if (argc < 1) {
1200 printf("Invalid INTERFACE_ADD command: needs at least one "
1201 "argument (interface name)\n"
1202 "All arguments: ifname confname driver ctrl_interface "
1203 "driver_param bridge_name\n");
1204 return -1;
1205 }
1206
1207 /*
1208 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1209 * <driver_param>TAB<bridge_name>
1210 */
1211 res = os_snprintf(cmd, sizeof(cmd),
1212 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1213 argv[0],
1214 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1215 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1216 argc > 5 ? argv[5] : "");
1217 if (res < 0 || (size_t) res >= sizeof(cmd))
1218 return -1;
1219 cmd[sizeof(cmd) - 1] = '\0';
1220 return wpa_ctrl_command(ctrl, cmd);
1221}
1222
1223
1224static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1225 char *argv[])
1226{
1227 char cmd[128];
1228 int res;
1229
1230 if (argc != 1) {
1231 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1232 "(interface name)\n");
1233 return -1;
1234 }
1235
1236 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1237 if (res < 0 || (size_t) res >= sizeof(cmd))
1238 return -1;
1239 cmd[sizeof(cmd) - 1] = '\0';
1240 return wpa_ctrl_command(ctrl, cmd);
1241}
1242
1243
4b4a8ae5
JM
1244static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1245 char *argv[])
1246{
1247 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1248}
1249
1250
e653b622
JM
1251#ifdef CONFIG_AP
1252static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1253{
1254 char buf[64];
1255 if (argc != 1) {
1256 printf("Invalid 'sta' command - exactly one argument, STA "
1257 "address, is required.\n");
1258 return -1;
1259 }
1260 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
1261 return wpa_ctrl_command(ctrl, buf);
1262}
1263
1264
1265static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
1266 char *addr, size_t addr_len)
1267{
1268 char buf[4096], *pos;
1269 size_t len;
1270 int ret;
1271
1272 if (ctrl_conn == NULL) {
1273 printf("Not connected to hostapd - command dropped.\n");
1274 return -1;
1275 }
1276 len = sizeof(buf) - 1;
1277 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
1278 wpa_cli_msg_cb);
1279 if (ret == -2) {
1280 printf("'%s' command timed out.\n", cmd);
1281 return -2;
1282 } else if (ret < 0) {
1283 printf("'%s' command failed.\n", cmd);
1284 return -1;
1285 }
1286
1287 buf[len] = '\0';
1288 if (memcmp(buf, "FAIL", 4) == 0)
1289 return -1;
1290 printf("%s", buf);
1291
1292 pos = buf;
1293 while (*pos != '\0' && *pos != '\n')
1294 pos++;
1295 *pos = '\0';
1296 os_strlcpy(addr, buf, addr_len);
1297 return 0;
1298}
1299
1300
1301static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
1302{
1303 char addr[32], cmd[64];
1304
1305 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
1306 return 0;
1307 do {
1308 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
1309 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
1310
1311 return -1;
1312}
1313#endif /* CONFIG_AP */
1314
1315
40fd868c
ER
1316enum wpa_cli_cmd_flags {
1317 cli_cmd_flag_none = 0x00,
1318 cli_cmd_flag_sensitive = 0x01
1319};
1320
6fc6879b
JM
1321struct wpa_cli_cmd {
1322 const char *cmd;
1323 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
40fd868c 1324 enum wpa_cli_cmd_flags flags;
dfa141b1 1325 const char *usage;
6fc6879b
JM
1326};
1327
1328static struct wpa_cli_cmd wpa_cli_commands[] = {
40fd868c 1329 { "status", wpa_cli_cmd_status,
dfa141b1
ER
1330 cli_cmd_flag_none,
1331 "[verbose] = get current WPA/EAPOL/EAP status" },
40fd868c 1332 { "ping", wpa_cli_cmd_ping,
dfa141b1
ER
1333 cli_cmd_flag_none,
1334 "= pings wpa_supplicant" },
40fd868c 1335 { "mib", wpa_cli_cmd_mib,
dfa141b1
ER
1336 cli_cmd_flag_none,
1337 "= get MIB variables (dot1x, dot11)" },
40fd868c 1338 { "help", wpa_cli_cmd_help,
dfa141b1
ER
1339 cli_cmd_flag_none,
1340 "= show this usage help" },
40fd868c 1341 { "interface", wpa_cli_cmd_interface,
dfa141b1
ER
1342 cli_cmd_flag_none,
1343 "[ifname] = show interfaces/select interface" },
40fd868c 1344 { "level", wpa_cli_cmd_level,
dfa141b1
ER
1345 cli_cmd_flag_none,
1346 "<debug level> = change debug level" },
40fd868c 1347 { "license", wpa_cli_cmd_license,
dfa141b1
ER
1348 cli_cmd_flag_none,
1349 "= show full wpa_cli license" },
40fd868c 1350 { "quit", wpa_cli_cmd_quit,
dfa141b1
ER
1351 cli_cmd_flag_none,
1352 "= exit wpa_cli" },
40fd868c 1353 { "set", wpa_cli_cmd_set,
dfa141b1
ER
1354 cli_cmd_flag_none,
1355 "= set variables (shows list of variables when run without "
1356 "arguments)" },
40fd868c 1357 { "logon", wpa_cli_cmd_logon,
dfa141b1
ER
1358 cli_cmd_flag_none,
1359 "= IEEE 802.1X EAPOL state machine logon" },
40fd868c 1360 { "logoff", wpa_cli_cmd_logoff,
dfa141b1
ER
1361 cli_cmd_flag_none,
1362 "= IEEE 802.1X EAPOL state machine logoff" },
40fd868c 1363 { "pmksa", wpa_cli_cmd_pmksa,
dfa141b1
ER
1364 cli_cmd_flag_none,
1365 "= show PMKSA cache" },
40fd868c 1366 { "reassociate", wpa_cli_cmd_reassociate,
dfa141b1
ER
1367 cli_cmd_flag_none,
1368 "= force reassociation" },
40fd868c 1369 { "preauthenticate", wpa_cli_cmd_preauthenticate,
dfa141b1
ER
1370 cli_cmd_flag_none,
1371 "<BSSID> = force preauthentication" },
40fd868c 1372 { "identity", wpa_cli_cmd_identity,
dfa141b1
ER
1373 cli_cmd_flag_none,
1374 "<network id> <identity> = configure identity for an SSID" },
40fd868c 1375 { "password", wpa_cli_cmd_password,
dfa141b1
ER
1376 cli_cmd_flag_sensitive,
1377 "<network id> <password> = configure password for an SSID" },
40fd868c 1378 { "new_password", wpa_cli_cmd_new_password,
dfa141b1
ER
1379 cli_cmd_flag_sensitive,
1380 "<network id> <password> = change password for an SSID" },
40fd868c 1381 { "pin", wpa_cli_cmd_pin,
dfa141b1
ER
1382 cli_cmd_flag_sensitive,
1383 "<network id> <pin> = configure pin for an SSID" },
40fd868c 1384 { "otp", wpa_cli_cmd_otp,
dfa141b1
ER
1385 cli_cmd_flag_sensitive,
1386 "<network id> <password> = configure one-time-password for an SSID"
1387 },
40fd868c 1388 { "passphrase", wpa_cli_cmd_passphrase,
dfa141b1
ER
1389 cli_cmd_flag_sensitive,
1390 "<network id> <passphrase> = configure private key passphrase\n"
1391 " for an SSID" },
40fd868c 1392 { "bssid", wpa_cli_cmd_bssid,
dfa141b1
ER
1393 cli_cmd_flag_none,
1394 "<network id> <BSSID> = set preferred BSSID for an SSID" },
40fd868c 1395 { "list_networks", wpa_cli_cmd_list_networks,
dfa141b1
ER
1396 cli_cmd_flag_none,
1397 "= list configured networks" },
40fd868c 1398 { "select_network", wpa_cli_cmd_select_network,
dfa141b1
ER
1399 cli_cmd_flag_none,
1400 "<network id> = select a network (disable others)" },
40fd868c 1401 { "enable_network", wpa_cli_cmd_enable_network,
dfa141b1
ER
1402 cli_cmd_flag_none,
1403 "<network id> = enable a network" },
40fd868c 1404 { "disable_network", wpa_cli_cmd_disable_network,
dfa141b1
ER
1405 cli_cmd_flag_none,
1406 "<network id> = disable a network" },
40fd868c 1407 { "add_network", wpa_cli_cmd_add_network,
dfa141b1
ER
1408 cli_cmd_flag_none,
1409 "= add a network" },
40fd868c 1410 { "remove_network", wpa_cli_cmd_remove_network,
dfa141b1
ER
1411 cli_cmd_flag_none,
1412 "<network id> = remove a network" },
40fd868c 1413 { "set_network", wpa_cli_cmd_set_network,
dfa141b1
ER
1414 cli_cmd_flag_sensitive,
1415 "<network id> <variable> <value> = set network variables (shows\n"
1416 " list of variables when run without arguments)" },
40fd868c 1417 { "get_network", wpa_cli_cmd_get_network,
dfa141b1
ER
1418 cli_cmd_flag_none,
1419 "<network id> <variable> = get network variables" },
40fd868c 1420 { "save_config", wpa_cli_cmd_save_config,
dfa141b1
ER
1421 cli_cmd_flag_none,
1422 "= save the current configuration" },
40fd868c 1423 { "disconnect", wpa_cli_cmd_disconnect,
dfa141b1
ER
1424 cli_cmd_flag_none,
1425 "= disconnect and wait for reassociate/reconnect command before\n"
1426 " connecting" },
40fd868c 1427 { "reconnect", wpa_cli_cmd_reconnect,
dfa141b1
ER
1428 cli_cmd_flag_none,
1429 "= like reassociate, but only takes effect if already disconnected"
1430 },
40fd868c 1431 { "scan", wpa_cli_cmd_scan,
dfa141b1
ER
1432 cli_cmd_flag_none,
1433 "= request new BSS scan" },
40fd868c 1434 { "scan_results", wpa_cli_cmd_scan_results,
dfa141b1
ER
1435 cli_cmd_flag_none,
1436 "= get latest scan results" },
40fd868c 1437 { "bss", wpa_cli_cmd_bss,
dfa141b1
ER
1438 cli_cmd_flag_none,
1439 "<<idx> | <bssid>> = get detailed scan result info" },
40fd868c 1440 { "get_capability", wpa_cli_cmd_get_capability,
dfa141b1
ER
1441 cli_cmd_flag_none,
1442 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
40fd868c 1443 { "reconfigure", wpa_cli_cmd_reconfigure,
dfa141b1
ER
1444 cli_cmd_flag_none,
1445 "= force wpa_supplicant to re-read its configuration file" },
40fd868c 1446 { "terminate", wpa_cli_cmd_terminate,
dfa141b1
ER
1447 cli_cmd_flag_none,
1448 "= terminate wpa_supplicant" },
40fd868c 1449 { "interface_add", wpa_cli_cmd_interface_add,
dfa141b1
ER
1450 cli_cmd_flag_none,
1451 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1452 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
1453 " are optional" },
40fd868c 1454 { "interface_remove", wpa_cli_cmd_interface_remove,
dfa141b1
ER
1455 cli_cmd_flag_none,
1456 "<ifname> = removes the interface" },
40fd868c 1457 { "interface_list", wpa_cli_cmd_interface_list,
dfa141b1
ER
1458 cli_cmd_flag_none,
1459 "= list available interfaces" },
40fd868c 1460 { "ap_scan", wpa_cli_cmd_ap_scan,
dfa141b1
ER
1461 cli_cmd_flag_none,
1462 "<value> = set ap_scan parameter" },
40fd868c 1463 { "stkstart", wpa_cli_cmd_stkstart,
dfa141b1
ER
1464 cli_cmd_flag_none,
1465 "<addr> = request STK negotiation with <addr>" },
40fd868c 1466 { "ft_ds", wpa_cli_cmd_ft_ds,
dfa141b1
ER
1467 cli_cmd_flag_none,
1468 "<addr> = request over-the-DS FT with <addr>" },
40fd868c 1469 { "wps_pbc", wpa_cli_cmd_wps_pbc,
dfa141b1
ER
1470 cli_cmd_flag_none,
1471 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
40fd868c 1472 { "wps_pin", wpa_cli_cmd_wps_pin,
dfa141b1
ER
1473 cli_cmd_flag_sensitive,
1474 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1475 "hardcoded)" },
116f7bb0 1476#ifdef CONFIG_WPS_OOB
46bdb83a
MH
1477 { "wps_oob", wpa_cli_cmd_wps_oob,
1478 cli_cmd_flag_sensitive,
e1ee6b60 1479 "<DEV_TYPE> <PATH> <METHOD> [DEV_NAME] = start WPS OOB" },
116f7bb0 1480#endif /* CONFIG_WPS_OOB */
40fd868c 1481 { "wps_reg", wpa_cli_cmd_wps_reg,
dfa141b1
ER
1482 cli_cmd_flag_sensitive,
1483 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
e9bcfebf
JM
1484 { "wps_er_start", wpa_cli_cmd_wps_er_start,
1485 cli_cmd_flag_none,
1486 "= start Wi-Fi Protected Setup External Registrar" },
1487 { "wps_er_stop", wpa_cli_cmd_wps_er_stop,
1488 cli_cmd_flag_none,
1489 "= stop Wi-Fi Protected Setup External Registrar" },
72df2f5f
JM
1490 { "wps_er_pin", wpa_cli_cmd_wps_er_pin,
1491 cli_cmd_flag_sensitive,
1492 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" },
564cd7fa
JM
1493 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc,
1494 cli_cmd_flag_none,
1495 "<UUID> = accept an Enrollee PBC using External Registrar" },
e64dcfd5
JM
1496 { "wps_er_learn", wpa_cli_cmd_wps_er_learn,
1497 cli_cmd_flag_sensitive,
1498 "<UUID> <PIN> = learn AP configuration" },
11ef8d35
JM
1499 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
1500 cli_cmd_flag_none,
1501 "<addr> = request RSN authentication with <addr> in IBSS" },
e653b622
JM
1502#ifdef CONFIG_AP
1503 { "sta", wpa_cli_cmd_sta,
1504 cli_cmd_flag_none,
1505 "<addr> = get information about an associated station (AP)" },
1506 { "all_sta", wpa_cli_cmd_all_sta,
1507 cli_cmd_flag_none,
1508 "= get information about all associated stations (AP)" },
1509#endif /* CONFIG_AP */
dfa141b1 1510 { NULL, NULL, cli_cmd_flag_none, NULL }
6fc6879b
JM
1511};
1512
1513
dfa141b1
ER
1514/*
1515 * Prints command usage, lines are padded with the specified string.
1516 */
1517static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1518{
1519 char c;
1520 size_t n;
1521
1522 printf("%s%s ", pad, cmd->cmd);
1523 for (n = 0; (c = cmd->usage[n]); n++) {
1524 printf("%c", c);
1525 if (c == '\n')
1526 printf("%s", pad);
1527 }
1528 printf("\n");
1529}
1530
1531
1532static void print_help(void)
1533{
1534 int n;
1535 printf("commands:\n");
1536 for (n = 0; wpa_cli_commands[n].cmd; n++)
1537 print_cmd_help(&wpa_cli_commands[n], " ");
1538}
1539
1540
40fd868c
ER
1541#ifdef CONFIG_READLINE
1542static int cmd_has_sensitive_data(const char *cmd)
1543{
1544 const char *c, *delim;
1545 int n;
1546 size_t len;
1547
1548 delim = os_strchr(cmd, ' ');
1549 if (delim)
1550 len = delim - cmd;
1551 else
1552 len = os_strlen(cmd);
1553
1554 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1555 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1556 return (wpa_cli_commands[n].flags &
1557 cli_cmd_flag_sensitive);
1558 }
1559 return 0;
1560}
1561#endif /* CONFIG_READLINE */
1562
1563
6fc6879b
JM
1564static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1565{
1566 struct wpa_cli_cmd *cmd, *match = NULL;
1567 int count;
1568 int ret = 0;
1569
1570 count = 0;
1571 cmd = wpa_cli_commands;
1572 while (cmd->cmd) {
1573 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1574 {
1575 match = cmd;
1576 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1577 /* we have an exact match */
1578 count = 1;
1579 break;
1580 }
1581 count++;
1582 }
1583 cmd++;
1584 }
1585
1586 if (count > 1) {
1587 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1588 cmd = wpa_cli_commands;
1589 while (cmd->cmd) {
1590 if (os_strncasecmp(cmd->cmd, argv[0],
1591 os_strlen(argv[0])) == 0) {
1592 printf(" %s", cmd->cmd);
1593 }
1594 cmd++;
1595 }
1596 printf("\n");
1597 ret = 1;
1598 } else if (count == 0) {
1599 printf("Unknown command '%s'\n", argv[0]);
1600 ret = 1;
1601 } else {
1602 ret = match->handler(ctrl, argc - 1, &argv[1]);
1603 }
1604
1605 return ret;
1606}
1607
1608
1609static int str_match(const char *a, const char *b)
1610{
1611 return os_strncmp(a, b, os_strlen(b)) == 0;
1612}
1613
1614
1615static int wpa_cli_exec(const char *program, const char *arg1,
1616 const char *arg2)
1617{
1618 char *cmd;
1619 size_t len;
1620 int res;
308a4ec8 1621 int ret = 0;
6fc6879b
JM
1622
1623 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1624 cmd = os_malloc(len);
1625 if (cmd == NULL)
1626 return -1;
1627 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1628 if (res < 0 || (size_t) res >= len) {
1629 os_free(cmd);
1630 return -1;
1631 }
1632 cmd[len - 1] = '\0';
1633#ifndef _WIN32_WCE
308a4ec8
JM
1634 if (system(cmd) < 0)
1635 ret = -1;
6fc6879b
JM
1636#endif /* _WIN32_WCE */
1637 os_free(cmd);
1638
308a4ec8 1639 return ret;
6fc6879b
JM
1640}
1641
1642
1643static void wpa_cli_action_process(const char *msg)
1644{
1645 const char *pos;
1646 char *copy = NULL, *id, *pos2;
1647
1648 pos = msg;
1649 if (*pos == '<') {
1650 /* skip priority */
1651 pos = os_strchr(pos, '>');
1652 if (pos)
1653 pos++;
1654 else
1655 pos = msg;
1656 }
1657
1658 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1659 int new_id = -1;
1660 os_unsetenv("WPA_ID");
1661 os_unsetenv("WPA_ID_STR");
1662 os_unsetenv("WPA_CTRL_DIR");
1663
1664 pos = os_strstr(pos, "[id=");
1665 if (pos)
1666 copy = os_strdup(pos + 4);
1667
1668 if (copy) {
1669 pos2 = id = copy;
1670 while (*pos2 && *pos2 != ' ')
1671 pos2++;
1672 *pos2++ = '\0';
1673 new_id = atoi(id);
1674 os_setenv("WPA_ID", id, 1);
1675 while (*pos2 && *pos2 != '=')
1676 pos2++;
1677 if (*pos2 == '=')
1678 pos2++;
1679 id = pos2;
1680 while (*pos2 && *pos2 != ']')
1681 pos2++;
1682 *pos2 = '\0';
1683 os_setenv("WPA_ID_STR", id, 1);
1684 os_free(copy);
1685 }
1686
1687 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1688
1689 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1690 wpa_cli_connected = 1;
1691 wpa_cli_last_id = new_id;
1692 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1693 }
1694 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1695 if (wpa_cli_connected) {
1696 wpa_cli_connected = 0;
1697 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1698 }
1699 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1700 printf("wpa_supplicant is terminating - stop monitoring\n");
1701 wpa_cli_quit = 1;
1702 }
1703}
1704
1705
1706#ifndef CONFIG_ANSI_C_EXTRA
1707static void wpa_cli_action_cb(char *msg, size_t len)
1708{
1709 wpa_cli_action_process(msg);
1710}
1711#endif /* CONFIG_ANSI_C_EXTRA */
1712
1713
1714static void wpa_cli_reconnect(void)
1715{
1716 wpa_cli_close_connection();
1717 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1718 if (ctrl_conn) {
1719 printf("Connection to wpa_supplicant re-established\n");
1720 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1721 wpa_cli_attached = 1;
1722 } else {
1723 printf("Warning: Failed to attach to "
1724 "wpa_supplicant.\n");
1725 }
1726 }
1727}
1728
1729
1730static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1731 int action_monitor)
1732{
1733 int first = 1;
1734 if (ctrl_conn == NULL) {
1735 wpa_cli_reconnect();
1736 return;
1737 }
1738 while (wpa_ctrl_pending(ctrl) > 0) {
1739 char buf[256];
1740 size_t len = sizeof(buf) - 1;
1741 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1742 buf[len] = '\0';
1743 if (action_monitor)
1744 wpa_cli_action_process(buf);
1745 else {
1746 if (in_read && first)
1747 printf("\n");
1748 first = 0;
1749 printf("%s\n", buf);
1750 }
1751 } else {
1752 printf("Could not read pending message.\n");
1753 break;
1754 }
1755 }
1756
1757 if (wpa_ctrl_pending(ctrl) < 0) {
1758 printf("Connection to wpa_supplicant lost - trying to "
1759 "reconnect\n");
1760 wpa_cli_reconnect();
1761 }
1762}
1763
1764
1765#ifdef CONFIG_READLINE
1766static char * wpa_cli_cmd_gen(const char *text, int state)
1767{
1768 static int i, len;
1769 const char *cmd;
1770
1771 if (state == 0) {
1772 i = 0;
1773 len = os_strlen(text);
1774 }
1775
1776 while ((cmd = wpa_cli_commands[i].cmd)) {
1777 i++;
1778 if (os_strncasecmp(cmd, text, len) == 0)
1779 return os_strdup(cmd);
1780 }
1781
1782 return NULL;
1783}
1784
1785
1786static char * wpa_cli_dummy_gen(const char *text, int state)
1787{
1788 return NULL;
1789}
1790
1791
1792static char ** wpa_cli_completion(const char *text, int start, int end)
1793{
1794 return rl_completion_matches(text, start == 0 ?
1795 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1796}
1797#endif /* CONFIG_READLINE */
1798
1799
1800static void wpa_cli_interactive(void)
1801{
1802#define max_args 10
1803 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1804 int argc;
1805#ifdef CONFIG_READLINE
1806 char *home, *hfile = NULL;
1807#endif /* CONFIG_READLINE */
1808
1809 printf("\nInteractive mode\n\n");
1810
1811#ifdef CONFIG_READLINE
1812 rl_attempted_completion_function = wpa_cli_completion;
1813 home = getenv("HOME");
1814 if (home) {
1815 const char *fname = ".wpa_cli_history";
1816 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1817 hfile = os_malloc(hfile_len);
1818 if (hfile) {
1819 int res;
1820 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1821 fname);
1822 if (res >= 0 && res < hfile_len) {
1823 hfile[hfile_len - 1] = '\0';
1824 read_history(hfile);
1825 stifle_history(100);
1826 }
1827 }
1828 }
1829#endif /* CONFIG_READLINE */
1830
1831 do {
1832 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1833#ifndef CONFIG_NATIVE_WINDOWS
1cc84c1c 1834 alarm(ping_interval);
6fc6879b
JM
1835#endif /* CONFIG_NATIVE_WINDOWS */
1836#ifdef CONFIG_READLINE
1837 cmd = readline("> ");
1838 if (cmd && *cmd) {
1839 HIST_ENTRY *h;
1840 while (next_history())
1841 ;
1842 h = previous_history();
1843 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1844 add_history(cmd);
1845 next_history();
1846 }
1847#else /* CONFIG_READLINE */
1848 printf("> ");
1849 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1850#endif /* CONFIG_READLINE */
1851#ifndef CONFIG_NATIVE_WINDOWS
1852 alarm(0);
1853#endif /* CONFIG_NATIVE_WINDOWS */
1854 if (cmd == NULL)
1855 break;
1856 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1857 pos = cmd;
1858 while (*pos != '\0') {
1859 if (*pos == '\n') {
1860 *pos = '\0';
1861 break;
1862 }
1863 pos++;
1864 }
1865 argc = 0;
1866 pos = cmd;
1867 for (;;) {
1868 while (*pos == ' ')
1869 pos++;
1870 if (*pos == '\0')
1871 break;
1872 argv[argc] = pos;
1873 argc++;
1874 if (argc == max_args)
1875 break;
1876 if (*pos == '"') {
1877 char *pos2 = os_strrchr(pos, '"');
1878 if (pos2)
1879 pos = pos2 + 1;
1880 }
1881 while (*pos != '\0' && *pos != ' ')
1882 pos++;
1883 if (*pos == ' ')
1884 *pos++ = '\0';
1885 }
1886 if (argc)
1887 wpa_request(ctrl_conn, argc, argv);
1888
1889 if (cmd != cmdbuf)
1890 os_free(cmd);
1891 } while (!wpa_cli_quit);
1892
1893#ifdef CONFIG_READLINE
1894 if (hfile) {
1895 /* Save command history, excluding lines that may contain
1896 * passwords. */
1897 HIST_ENTRY *h;
1898 history_set_pos(0);
413653e8 1899 while ((h = current_history())) {
6fc6879b
JM
1900 char *p = h->line;
1901 while (*p == ' ' || *p == '\t')
1902 p++;
40fd868c 1903 if (cmd_has_sensitive_data(p)) {
6fc6879b
JM
1904 h = remove_history(where_history());
1905 if (h) {
1906 os_free(h->line);
1907 os_free(h->data);
1908 os_free(h);
413653e8
ER
1909 } else
1910 next_history();
1911 } else
1912 next_history();
6fc6879b
JM
1913 }
1914 write_history(hfile);
1915 os_free(hfile);
1916 }
1917#endif /* CONFIG_READLINE */
1918}
1919
1920
1921static void wpa_cli_action(struct wpa_ctrl *ctrl)
1922{
1923#ifdef CONFIG_ANSI_C_EXTRA
1924 /* TODO: ANSI C version(?) */
1925 printf("Action processing not supported in ANSI C build.\n");
1926#else /* CONFIG_ANSI_C_EXTRA */
1927 fd_set rfds;
1928 int fd, res;
1929 struct timeval tv;
1930 char buf[256]; /* note: large enough to fit in unsolicited messages */
1931 size_t len;
1932
1933 fd = wpa_ctrl_get_fd(ctrl);
1934
1935 while (!wpa_cli_quit) {
1936 FD_ZERO(&rfds);
1937 FD_SET(fd, &rfds);
1cc84c1c 1938 tv.tv_sec = ping_interval;
6fc6879b
JM
1939 tv.tv_usec = 0;
1940 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1941 if (res < 0 && errno != EINTR) {
1942 perror("select");
1943 break;
1944 }
1945
1946 if (FD_ISSET(fd, &rfds))
1947 wpa_cli_recv_pending(ctrl, 0, 1);
1948 else {
1949 /* verify that connection is still working */
1950 len = sizeof(buf) - 1;
1951 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1952 wpa_cli_action_cb) < 0 ||
1953 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1954 printf("wpa_supplicant did not reply to PING "
1955 "command - exiting\n");
1956 break;
1957 }
1958 }
1959 }
1960#endif /* CONFIG_ANSI_C_EXTRA */
1961}
1962
1963
1964static void wpa_cli_cleanup(void)
1965{
1966 wpa_cli_close_connection();
1967 if (pid_file)
1968 os_daemonize_terminate(pid_file);
1969
1970 os_program_deinit();
1971}
1972
1973static void wpa_cli_terminate(int sig)
1974{
1975 wpa_cli_cleanup();
1976 exit(0);
1977}
1978
1979
1980#ifndef CONFIG_NATIVE_WINDOWS
1981static void wpa_cli_alarm(int sig)
1982{
1983 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1984 printf("Connection to wpa_supplicant lost - trying to "
1985 "reconnect\n");
1986 wpa_cli_close_connection();
1987 }
1988 if (!ctrl_conn)
1989 wpa_cli_reconnect();
1990 if (ctrl_conn)
1991 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1cc84c1c 1992 alarm(ping_interval);
6fc6879b
JM
1993}
1994#endif /* CONFIG_NATIVE_WINDOWS */
1995
1996
1997static char * wpa_cli_get_default_ifname(void)
1998{
1999 char *ifname = NULL;
2000
2001#ifdef CONFIG_CTRL_IFACE_UNIX
2002 struct dirent *dent;
2003 DIR *dir = opendir(ctrl_iface_dir);
2004 if (!dir)
2005 return NULL;
2006 while ((dent = readdir(dir))) {
2007#ifdef _DIRENT_HAVE_D_TYPE
2008 /*
2009 * Skip the file if it is not a socket. Also accept
2010 * DT_UNKNOWN (0) in case the C library or underlying
2011 * file system does not support d_type.
2012 */
2013 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
2014 continue;
2015#endif /* _DIRENT_HAVE_D_TYPE */
2016 if (os_strcmp(dent->d_name, ".") == 0 ||
2017 os_strcmp(dent->d_name, "..") == 0)
2018 continue;
2019 printf("Selected interface '%s'\n", dent->d_name);
2020 ifname = os_strdup(dent->d_name);
2021 break;
2022 }
2023 closedir(dir);
2024#endif /* CONFIG_CTRL_IFACE_UNIX */
2025
2026#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2027 char buf[2048], *pos;
2028 size_t len;
2029 struct wpa_ctrl *ctrl;
2030 int ret;
2031
2032 ctrl = wpa_ctrl_open(NULL);
2033 if (ctrl == NULL)
2034 return NULL;
2035
2036 len = sizeof(buf) - 1;
2037 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
2038 if (ret >= 0) {
2039 buf[len] = '\0';
2040 pos = os_strchr(buf, '\n');
2041 if (pos)
2042 *pos = '\0';
2043 ifname = os_strdup(buf);
2044 }
2045 wpa_ctrl_close(ctrl);
2046#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2047
2048 return ifname;
2049}
2050
2051
2052int main(int argc, char *argv[])
2053{
2054 int interactive;
2055 int warning_displayed = 0;
2056 int c;
2057 int daemonize = 0;
2058 int ret = 0;
2059 const char *global = NULL;
2060
2061 if (os_program_init())
2062 return -1;
2063
2064 for (;;) {
1cc84c1c 2065 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v");
6fc6879b
JM
2066 if (c < 0)
2067 break;
2068 switch (c) {
2069 case 'a':
2070 action_file = optarg;
2071 break;
2072 case 'B':
2073 daemonize = 1;
2074 break;
2075 case 'g':
2076 global = optarg;
2077 break;
1cc84c1c
JM
2078 case 'G':
2079 ping_interval = atoi(optarg);
2080 break;
6fc6879b
JM
2081 case 'h':
2082 usage();
2083 return 0;
2084 case 'v':
2085 printf("%s\n", wpa_cli_version);
2086 return 0;
2087 case 'i':
2088 os_free(ctrl_ifname);
2089 ctrl_ifname = os_strdup(optarg);
2090 break;
2091 case 'p':
2092 ctrl_iface_dir = optarg;
2093 break;
2094 case 'P':
2095 pid_file = optarg;
2096 break;
2097 default:
2098 usage();
2099 return -1;
2100 }
2101 }
2102
2103 interactive = (argc == optind) && (action_file == NULL);
2104
2105 if (interactive)
2106 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
2107
2108 if (global) {
2109#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
2110 ctrl_conn = wpa_ctrl_open(NULL);
2111#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2112 ctrl_conn = wpa_ctrl_open(global);
2113#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
2114 if (ctrl_conn == NULL) {
2115 perror("Failed to connect to wpa_supplicant - "
2116 "wpa_ctrl_open");
2117 return -1;
2118 }
2119 }
2120
2121 for (; !global;) {
2122 if (ctrl_ifname == NULL)
2123 ctrl_ifname = wpa_cli_get_default_ifname();
2124 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
2125 if (ctrl_conn) {
2126 if (warning_displayed)
2127 printf("Connection established.\n");
2128 break;
2129 }
2130
2131 if (!interactive) {
2132 perror("Failed to connect to wpa_supplicant - "
2133 "wpa_ctrl_open");
2134 return -1;
2135 }
2136
2137 if (!warning_displayed) {
2138 printf("Could not connect to wpa_supplicant - "
2139 "re-trying\n");
2140 warning_displayed = 1;
2141 }
2142 os_sleep(1, 0);
2143 continue;
2144 }
2145
2146#ifndef _WIN32_WCE
2147 signal(SIGINT, wpa_cli_terminate);
2148 signal(SIGTERM, wpa_cli_terminate);
2149#endif /* _WIN32_WCE */
2150#ifndef CONFIG_NATIVE_WINDOWS
2151 signal(SIGALRM, wpa_cli_alarm);
2152#endif /* CONFIG_NATIVE_WINDOWS */
2153
2154 if (interactive || action_file) {
2155 if (wpa_ctrl_attach(ctrl_conn) == 0) {
2156 wpa_cli_attached = 1;
2157 } else {
2158 printf("Warning: Failed to attach to "
2159 "wpa_supplicant.\n");
2160 if (!interactive)
2161 return -1;
2162 }
2163 }
2164
2165 if (daemonize && os_daemonize(pid_file))
2166 return -1;
2167
2168 if (interactive)
2169 wpa_cli_interactive();
2170 else if (action_file)
2171 wpa_cli_action(ctrl_conn);
2172 else
2173 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
2174
2175 os_free(ctrl_ifname);
2176 wpa_cli_cleanup();
2177
2178 return ret;
2179}
2180
2181#else /* CONFIG_CTRL_IFACE */
2182int main(int argc, char *argv[])
2183{
2184 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
2185 return -1;
2186}
2187#endif /* CONFIG_CTRL_IFACE */