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