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