1 /*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
3 * Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi>
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 #define CTRL_INTERFACE_2_SOCKETS
28
29 #include "wpa_ctrl.h"
30 #include "common.h"
31 #include "version.h"
32 #ifdef ANDROID
33 #include <cutils/properties.h>
34 #endif
35
36 static const char *wpa_cli_version =
37 "wpa_cli v" VERSION_STR "\n"
38 "Copyright (c) 2004-2008, Jouni Malinen <j@w1.fi> and contributors";
39
40
41 static const char *wpa_cli_license =
42 "This program is free software. You can distribute it and/or modify it\n"
43 "under the terms of the GNU General Public License version 2.\n"
44 "\n"
45 "Alternatively, this software may be distributed under the terms of the\n"
46 "BSD license. See README and COPYING for more details.\n";
47
48 static const char *wpa_cli_full_license =
49 "This program is free software; you can redistribute it and/or modify\n"
50 "it under the terms of the GNU General Public License version 2 as\n"
51 "published by the Free Software Foundation.\n"
52 "\n"
53 "This program is distributed in the hope that it will be useful,\n"
54 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
55 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
56 "GNU General Public License for more details.\n"
57 "\n"
58 "You should have received a copy of the GNU General Public License\n"
59 "along with this program; if not, write to the Free Software\n"
60 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
61 "\n"
62 "Alternatively, this software may be distributed under the terms of the\n"
63 "BSD license.\n"
64 "\n"
65 "Redistribution and use in source and binary forms, with or without\n"
66 "modification, are permitted provided that the following conditions are\n"
67 "met:\n"
68 "\n"
69 "1. Redistributions of source code must retain the above copyright\n"
70 " notice, this list of conditions and the following disclaimer.\n"
71 "\n"
72 "2. Redistributions in binary form must reproduce the above copyright\n"
73 " notice, this list of conditions and the following disclaimer in the\n"
74 " documentation and/or other materials provided with the distribution.\n"
75 "\n"
76 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
77 " names of its contributors may be used to endorse or promote products\n"
78 " derived from this software without specific prior written permission.\n"
79 "\n"
80 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
81 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
82 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
83 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
84 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
85 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
86 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
87 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
88 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
89 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
90 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
91 "\n";
92
93 static const char *commands_help =
94 "commands:\n"
95 " status [verbose] = get current WPA/EAPOL/EAP status\n"
96 " mib = get MIB variables (dot1x, dot11)\n"
97 " help = show this usage help\n"
98 " interface [ifname] = show interfaces/select interface\n"
99 " level <debug level> = change debug level\n"
100 " license = show full wpa_cli license\n"
101 " logoff = IEEE 802.1X EAPOL state machine logoff\n"
102 " logon = IEEE 802.1X EAPOL state machine logon\n"
103 " set = set variables (shows list of variables when run without arguments)\n"
104 " pmksa = show PMKSA cache\n"
105 " reassociate = force reassociation\n"
106 " reconfigure = force wpa_supplicant to re-read its configuration file\n"
107 " preauthenticate <BSSID> = force preauthentication\n"
108 " identity <network id> <identity> = configure identity for an SSID\n"
109 " password <network id> <password> = configure password for an SSID\n"
110 " new_password <network id> <password> = change password for an SSID\n"
111 " pin <network id> <pin> = configure pin for an SSID\n"
112 " otp <network id> <password> = configure one-time-password for an SSID\n"
113 " passphrase <network id> <passphrase> = configure private key passphrase\n"
114 " for an SSID\n"
115 " bssid <network id> <BSSID> = set preferred BSSID for an SSID\n"
116 " blacklist [<BSSID>] = add a BSSID to the blacklist\n"
117 " blacklist clear = clear the blacklist\n"
118 " blacklist = display the blacklist\n"
119 " list_networks = list configured networks\n"
120 " select_network <network id> = select a network (disable others)\n"
121 " enable_network <network id> = enable a network\n"
122 " disable_network <network id> = disable a network\n"
123 " add_network = add a network\n"
124 " remove_network <network id> = remove a network\n"
125 " set_network <network id> <variable> <value> = set network variables "
126 "(shows\n"
127 " list of variables when run without arguments)\n"
128 " get_network <network id> <variable> = get network variables\n"
129 " save_config = save the current configuration\n"
130 " disconnect = disconnect and wait for reassociate/reconnect command before\n "
131 " connecting\n"
132 " reconnect = like reassociate, but only takes effect if already "
133 "disconnected\n"
134 " scan = request new BSS scan\n"
135 " scan_results = get latest scan results\n"
136 " get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = "
137 "get capabilies\n"
138 " ap_scan <value> = set ap_scan parameter\n"
139 " stkstart <addr> = request STK negotiation with <addr>\n"
140 " terminate = terminate wpa_supplicant\n"
141 " quit = exit wpa_cli\n";
142
143 static struct wpa_ctrl *ctrl_conn;
144 static struct wpa_ctrl *monitor_conn;
145 static int wpa_cli_quit = 0;
146 static int wpa_cli_attached = 0;
147 static int wpa_cli_connected = 0;
148 static int wpa_cli_last_id = 0;
149 #ifdef ANDROID
150 static const char *ctrl_iface_dir = "/data/misc/wifi/wpa_supplicant";
151 #else
152 static const char *ctrl_iface_dir = "/tmp/run/wpa_supplicant";
153 #endif
154 static char *ctrl_ifname = NULL;
155 static const char *pid_file = NULL;
156 static const char *action_file = NULL;
157
158
usage(void)159 static void usage(void)
160 {
161 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
162 "[-a<action file>] \\\n"
163 " [-P<pid file>] [-g<global ctrl>] [command..]\n"
164 " -h = help (show this usage text)\n"
165 " -v = shown version information\n"
166 " -a = run in daemon mode executing the action file based on "
167 "events from\n"
168 " wpa_supplicant\n"
169 " -B = run a daemon in the background\n"
170 " default path: /var/run/wpa_supplicant\n"
171 " default interface: first interface found in socket path\n"
172 "%s",
173 commands_help);
174 }
175
176
wpa_cli_open_connection(const char * ifname)177 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
178 {
179 struct wpa_ctrl *cur_conn;
180 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
181 cur_conn = wpa_ctrl_open(ifname);
182 return cur_conn;
183 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
184 char *cfile;
185 int flen;
186
187 if (ifname == NULL)
188 return NULL;
189
190 #ifdef ANDROID
191 if (access(ctrl_iface_dir, F_OK) < 0)
192 cfile = (char *)ifname;
193 else {
194 #endif
195 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
196 cfile = os_malloc(flen);
197 if (cfile == NULL)
198 return NULL;
199 os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
200 #ifdef ANDROID
201 }
202 #endif
203
204 cur_conn = wpa_ctrl_open(cfile); /* Dm: */
205 #ifdef CTRL_INTERFACE_2_SOCKETS
206 monitor_conn = wpa_ctrl_open(cfile);
207 #else
208 monitor_conn = cur_conn;
209 #endif
210 #ifdef ANDROID
211 if (cfile != ifname)
212 #endif
213 os_free(cfile);
214 return cur_conn;
215 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
216 }
217
218
wpa_cli_close_connection(void)219 static void wpa_cli_close_connection(void)
220 {
221 if (ctrl_conn == NULL)
222 return;
223
224 if (wpa_cli_attached) {
225 wpa_ctrl_detach(monitor_conn);
226 wpa_cli_attached = 0;
227 }
228 #ifdef CTRL_INTERFACE_2_SOCKETS
229 wpa_ctrl_close(monitor_conn);
230 #endif
231 wpa_ctrl_close(ctrl_conn);
232 ctrl_conn = monitor_conn = NULL;
233 }
234
235
wpa_cli_msg_cb(char * msg,size_t len)236 static void wpa_cli_msg_cb(char *msg, size_t len)
237 {
238 printf("%s\n", msg);
239 }
240
241
_wpa_ctrl_command(struct wpa_ctrl * ctrl,char * cmd,int print)242 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
243 {
244 char buf[4096];
245 size_t len;
246 int ret;
247
248 if (ctrl_conn == NULL) {
249 printf("Not connected to wpa_supplicant - command dropped.\n");
250 return -1;
251 }
252 len = sizeof(buf) - 1;
253 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
254 wpa_cli_msg_cb);
255 if (ret == -2) {
256 printf("'%s' command timed out.\n", cmd);
257 return -2;
258 } else if (ret < 0) {
259 printf("'%s' command failed.\n", cmd);
260 return -1;
261 }
262 if (print) {
263 buf[len] = '\0';
264 printf("%s", buf);
265 }
266 return 0;
267 }
268
269
wpa_ctrl_command(struct wpa_ctrl * ctrl,char * cmd)270 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
271 {
272 return _wpa_ctrl_command(ctrl, cmd, 1);
273 }
274
275
wpa_cli_cmd_status(struct wpa_ctrl * ctrl,int argc,char * argv[])276 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
277 {
278 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
279 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
280 }
281
282
wpa_cli_cmd_ping(struct wpa_ctrl * ctrl,int argc,char * argv[])283 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
284 {
285 return wpa_ctrl_command(ctrl, "PING");
286 }
287
288
wpa_cli_cmd_mib(struct wpa_ctrl * ctrl,int argc,char * argv[])289 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
290 {
291 return wpa_ctrl_command(ctrl, "MIB");
292 }
293
294
wpa_cli_cmd_pmksa(struct wpa_ctrl * ctrl,int argc,char * argv[])295 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
296 {
297 return wpa_ctrl_command(ctrl, "PMKSA");
298 }
299
300
wpa_cli_cmd_help(struct wpa_ctrl * ctrl,int argc,char * argv[])301 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
302 {
303 printf("%s", commands_help);
304 return 0;
305 }
306
307
wpa_cli_cmd_license(struct wpa_ctrl * ctrl,int argc,char * argv[])308 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
309 {
310 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
311 return 0;
312 }
313
314
wpa_cli_cmd_quit(struct wpa_ctrl * ctrl,int argc,char * argv[])315 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
316 {
317 wpa_cli_quit = 1;
318 return 0;
319 }
320
321
wpa_cli_show_variables(void)322 static void wpa_cli_show_variables(void)
323 {
324 printf("set variables:\n"
325 " EAPOL::heldPeriod (EAPOL state machine held period, "
326 "in seconds)\n"
327 " EAPOL::authPeriod (EAPOL state machine authentication "
328 "period, in seconds)\n"
329 " EAPOL::startPeriod (EAPOL state machine start period, in "
330 "seconds)\n"
331 " EAPOL::maxStart (EAPOL state machine maximum start "
332 "attempts)\n");
333 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
334 "seconds)\n"
335 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
336 " threshold\n\tpercentage)\n"
337 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
338 "security\n\tassociation in seconds)\n");
339 }
340
341
wpa_cli_cmd_set(struct wpa_ctrl * ctrl,int argc,char * argv[])342 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
343 {
344 char cmd[256];
345 int res;
346
347 if (argc == 0) {
348 wpa_cli_show_variables();
349 return 0;
350 }
351
352 if (argc != 2) {
353 printf("Invalid SET command: needs two arguments (variable "
354 "name and value)\n");
355 return -1;
356 }
357
358 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
359 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
360 printf("Too long SET command.\n");
361 return -1;
362 }
363 return wpa_ctrl_command(ctrl, cmd);
364 }
365
366
wpa_cli_cmd_logoff(struct wpa_ctrl * ctrl,int argc,char * argv[])367 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
368 {
369 return wpa_ctrl_command(ctrl, "LOGOFF");
370 }
371
372
wpa_cli_cmd_logon(struct wpa_ctrl * ctrl,int argc,char * argv[])373 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
374 {
375 return wpa_ctrl_command(ctrl, "LOGON");
376 }
377
378
wpa_cli_cmd_reassociate(struct wpa_ctrl * ctrl,int argc,char * argv[])379 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
380 char *argv[])
381 {
382 return wpa_ctrl_command(ctrl, "REASSOCIATE");
383 }
384
385
wpa_cli_cmd_preauthenticate(struct wpa_ctrl * ctrl,int argc,char * argv[])386 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
387 char *argv[])
388 {
389 char cmd[256];
390 int res;
391
392 if (argc != 1) {
393 printf("Invalid PREAUTH command: needs one argument "
394 "(BSSID)\n");
395 return -1;
396 }
397
398 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
399 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
400 printf("Too long PREAUTH command.\n");
401 return -1;
402 }
403 return wpa_ctrl_command(ctrl, cmd);
404 }
405
406
wpa_cli_cmd_ap_scan(struct wpa_ctrl * ctrl,int argc,char * argv[])407 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
408 {
409 char cmd[256];
410 int res;
411
412 if (argc != 1) {
413 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
414 "value)\n");
415 return -1;
416 }
417 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
418 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
419 printf("Too long AP_SCAN command.\n");
420 return -1;
421 }
422 return wpa_ctrl_command(ctrl, cmd);
423 }
424
425
wpa_cli_cmd_stkstart(struct wpa_ctrl * ctrl,int argc,char * argv[])426 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
427 char *argv[])
428 {
429 char cmd[256];
430 int res;
431
432 if (argc != 1) {
433 printf("Invalid STKSTART command: needs one argument "
434 "(Peer STA MAC address)\n");
435 return -1;
436 }
437
438 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
439 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
440 printf("Too long STKSTART command.\n");
441 return -1;
442 }
443 return wpa_ctrl_command(ctrl, cmd);
444 }
445
446
wpa_cli_cmd_level(struct wpa_ctrl * ctrl,int argc,char * argv[])447 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
448 {
449 char cmd[256];
450 int res;
451
452 if (argc != 1) {
453 printf("Invalid LEVEL command: needs one argument (debug "
454 "level)\n");
455 return -1;
456 }
457 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
458 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
459 printf("Too long LEVEL command.\n");
460 return -1;
461 }
462 return wpa_ctrl_command(ctrl, cmd);
463 }
464
465
wpa_cli_cmd_identity(struct wpa_ctrl * ctrl,int argc,char * argv[])466 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
467 {
468 char cmd[256], *pos, *end;
469 int i, ret;
470
471 if (argc < 2) {
472 printf("Invalid IDENTITY command: needs two arguments "
473 "(network id and identity)\n");
474 return -1;
475 }
476
477 end = cmd + sizeof(cmd);
478 pos = cmd;
479 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
480 argv[0], argv[1]);
481 if (ret < 0 || ret >= end - pos) {
482 printf("Too long IDENTITY command.\n");
483 return -1;
484 }
485 pos += ret;
486 for (i = 2; i < argc; i++) {
487 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
488 if (ret < 0 || ret >= end - pos) {
489 printf("Too long IDENTITY command.\n");
490 return -1;
491 }
492 pos += ret;
493 }
494
495 return wpa_ctrl_command(ctrl, cmd);
496 }
497
498
wpa_cli_cmd_password(struct wpa_ctrl * ctrl,int argc,char * argv[])499 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
500 {
501 char cmd[256], *pos, *end;
502 int i, ret;
503
504 if (argc < 2) {
505 printf("Invalid PASSWORD command: needs two arguments "
506 "(network id and password)\n");
507 return -1;
508 }
509
510 end = cmd + sizeof(cmd);
511 pos = cmd;
512 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
513 argv[0], argv[1]);
514 if (ret < 0 || ret >= end - pos) {
515 printf("Too long PASSWORD command.\n");
516 return -1;
517 }
518 pos += ret;
519 for (i = 2; i < argc; i++) {
520 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
521 if (ret < 0 || ret >= end - pos) {
522 printf("Too long PASSWORD command.\n");
523 return -1;
524 }
525 pos += ret;
526 }
527
528 return wpa_ctrl_command(ctrl, cmd);
529 }
530
531
wpa_cli_cmd_new_password(struct wpa_ctrl * ctrl,int argc,char * argv[])532 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
533 char *argv[])
534 {
535 char cmd[256], *pos, *end;
536 int i, ret;
537
538 if (argc < 2) {
539 printf("Invalid NEW_PASSWORD command: needs two arguments "
540 "(network id and password)\n");
541 return -1;
542 }
543
544 end = cmd + sizeof(cmd);
545 pos = cmd;
546 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
547 argv[0], argv[1]);
548 if (ret < 0 || ret >= end - pos) {
549 printf("Too long NEW_PASSWORD command.\n");
550 return -1;
551 }
552 pos += ret;
553 for (i = 2; i < argc; i++) {
554 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
555 if (ret < 0 || ret >= end - pos) {
556 printf("Too long NEW_PASSWORD command.\n");
557 return -1;
558 }
559 pos += ret;
560 }
561
562 return wpa_ctrl_command(ctrl, cmd);
563 }
564
565
wpa_cli_cmd_pin(struct wpa_ctrl * ctrl,int argc,char * argv[])566 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
567 {
568 char cmd[256], *pos, *end;
569 int i, ret;
570
571 if (argc < 2) {
572 printf("Invalid PIN command: needs two arguments "
573 "(network id and pin)\n");
574 return -1;
575 }
576
577 end = cmd + sizeof(cmd);
578 pos = cmd;
579 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
580 argv[0], argv[1]);
581 if (ret < 0 || ret >= end - pos) {
582 printf("Too long PIN command.\n");
583 return -1;
584 }
585 pos += ret;
586 for (i = 2; i < argc; i++) {
587 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
588 if (ret < 0 || ret >= end - pos) {
589 printf("Too long PIN command.\n");
590 return -1;
591 }
592 pos += ret;
593 }
594 return wpa_ctrl_command(ctrl, cmd);
595 }
596
597
wpa_cli_cmd_otp(struct wpa_ctrl * ctrl,int argc,char * argv[])598 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
599 {
600 char cmd[256], *pos, *end;
601 int i, ret;
602
603 if (argc < 2) {
604 printf("Invalid OTP command: needs two arguments (network "
605 "id and password)\n");
606 return -1;
607 }
608
609 end = cmd + sizeof(cmd);
610 pos = cmd;
611 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
612 argv[0], argv[1]);
613 if (ret < 0 || ret >= end - pos) {
614 printf("Too long OTP command.\n");
615 return -1;
616 }
617 pos += ret;
618 for (i = 2; i < argc; i++) {
619 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
620 if (ret < 0 || ret >= end - pos) {
621 printf("Too long OTP command.\n");
622 return -1;
623 }
624 pos += ret;
625 }
626
627 return wpa_ctrl_command(ctrl, cmd);
628 }
629
630
wpa_cli_cmd_passphrase(struct wpa_ctrl * ctrl,int argc,char * argv[])631 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
632 char *argv[])
633 {
634 char cmd[256], *pos, *end;
635 int i, ret;
636
637 if (argc < 2) {
638 printf("Invalid PASSPHRASE command: needs two arguments "
639 "(network id and passphrase)\n");
640 return -1;
641 }
642
643 end = cmd + sizeof(cmd);
644 pos = cmd;
645 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
646 argv[0], argv[1]);
647 if (ret < 0 || ret >= end - pos) {
648 printf("Too long PASSPHRASE command.\n");
649 return -1;
650 }
651 pos += ret;
652 for (i = 2; i < argc; i++) {
653 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
654 if (ret < 0 || ret >= end - pos) {
655 printf("Too long PASSPHRASE command.\n");
656 return -1;
657 }
658 pos += ret;
659 }
660
661 return wpa_ctrl_command(ctrl, cmd);
662 }
663
664
wpa_cli_cmd_bssid(struct wpa_ctrl * ctrl,int argc,char * argv[])665 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
666 {
667 char cmd[256], *pos, *end;
668 int i, ret;
669
670 if (argc < 2) {
671 printf("Invalid BSSID command: needs two arguments (network "
672 "id and BSSID)\n");
673 return -1;
674 }
675
676 end = cmd + sizeof(cmd);
677 pos = cmd;
678 ret = os_snprintf(pos, end - pos, "BSSID");
679 if (ret < 0 || ret >= end - pos) {
680 printf("Too long BSSID command.\n");
681 return -1;
682 }
683 pos += ret;
684 for (i = 0; i < argc; i++) {
685 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
686 if (ret < 0 || ret >= end - pos) {
687 printf("Too long BSSID command.\n");
688 return -1;
689 }
690 pos += ret;
691 }
692
693 return wpa_ctrl_command(ctrl, cmd);
694 }
695
696 #ifdef ANDROID
wpa_cli_cmd_blacklist(struct wpa_ctrl * ctrl,int argc,char * argv[])697 static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[])
698 {
699 char cmd[256], *pos, *end;
700 int i, ret;
701
702 end = cmd + sizeof(cmd);
703 pos = cmd;
704 ret = os_snprintf(pos, end - pos, "BLACKLIST");
705 if (ret < 0 || ret >= end - pos) {
706 printf("Too long BLACKLIST command.\n");
707 return -1;
708 }
709 pos += ret;
710 for (i = 0; i < argc; i++) {
711 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
712 if (ret < 0 || ret >= end - pos) {
713 printf("Too long BLACKLIST command.\n");
714 return -1;
715 }
716 pos += ret;
717 }
718
719 return wpa_ctrl_command(ctrl, cmd);
720 }
721 #endif
722
wpa_cli_cmd_list_networks(struct wpa_ctrl * ctrl,int argc,char * argv[])723 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
724 char *argv[])
725 {
726 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
727 }
728
729
wpa_cli_cmd_select_network(struct wpa_ctrl * ctrl,int argc,char * argv[])730 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
731 char *argv[])
732 {
733 char cmd[32];
734
735 if (argc < 1) {
736 printf("Invalid SELECT_NETWORK command: needs one argument "
737 "(network id)\n");
738 return -1;
739 }
740
741 os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
742 cmd[sizeof(cmd) - 1] = '\0';
743
744 return wpa_ctrl_command(ctrl, cmd);
745 }
746
747
wpa_cli_cmd_enable_network(struct wpa_ctrl * ctrl,int argc,char * argv[])748 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
749 char *argv[])
750 {
751 char cmd[32];
752
753 if (argc < 1) {
754 printf("Invalid ENABLE_NETWORK command: needs one argument "
755 "(network id)\n");
756 return -1;
757 }
758
759 os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
760 cmd[sizeof(cmd) - 1] = '\0';
761
762 return wpa_ctrl_command(ctrl, cmd);
763 }
764
765
wpa_cli_cmd_disable_network(struct wpa_ctrl * ctrl,int argc,char * argv[])766 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
767 char *argv[])
768 {
769 char cmd[32];
770
771 if (argc < 1) {
772 printf("Invalid DISABLE_NETWORK command: needs one argument "
773 "(network id)\n");
774 return -1;
775 }
776
777 os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
778 cmd[sizeof(cmd) - 1] = '\0';
779
780 return wpa_ctrl_command(ctrl, cmd);
781 }
782
783
wpa_cli_cmd_add_network(struct wpa_ctrl * ctrl,int argc,char * argv[])784 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
785 char *argv[])
786 {
787 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
788 }
789
790
wpa_cli_cmd_remove_network(struct wpa_ctrl * ctrl,int argc,char * argv[])791 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
792 char *argv[])
793 {
794 char cmd[32];
795
796 if (argc < 1) {
797 printf("Invalid REMOVE_NETWORK command: needs one argument "
798 "(network id)\n");
799 return -1;
800 }
801
802 os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
803 cmd[sizeof(cmd) - 1] = '\0';
804
805 return wpa_ctrl_command(ctrl, cmd);
806 }
807
808
wpa_cli_show_network_variables(void)809 static void wpa_cli_show_network_variables(void)
810 {
811 printf("set_network variables:\n"
812 " ssid (network name, SSID)\n"
813 " psk (WPA passphrase or pre-shared key)\n"
814 " key_mgmt (key management protocol)\n"
815 " identity (EAP identity)\n"
816 " password (EAP password)\n"
817 " ...\n"
818 "\n"
819 "Note: Values are entered in the same format as the "
820 "configuration file is using,\n"
821 "i.e., strings values need to be inside double quotation "
822 "marks.\n"
823 "For example: set_network 1 ssid \"network name\"\n"
824 "\n"
825 "Please see wpa_supplicant.conf documentation for full list "
826 "of\navailable variables.\n");
827 }
828
829
wpa_cli_cmd_set_network(struct wpa_ctrl * ctrl,int argc,char * argv[])830 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
831 char *argv[])
832 {
833 char cmd[256];
834 int res;
835
836 if (argc == 0) {
837 wpa_cli_show_network_variables();
838 return 0;
839 }
840
841 if (argc != 3) {
842 printf("Invalid SET_NETWORK command: needs three arguments\n"
843 "(network id, variable name, and value)\n");
844 return -1;
845 }
846
847 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
848 argv[0], argv[1], argv[2]);
849 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
850 printf("Too long SET_NETWORK command.\n");
851 return -1;
852 }
853 return wpa_ctrl_command(ctrl, cmd);
854 }
855
856
wpa_cli_cmd_get_network(struct wpa_ctrl * ctrl,int argc,char * argv[])857 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
858 char *argv[])
859 {
860 char cmd[256];
861 int res;
862
863 if (argc == 0) {
864 wpa_cli_show_network_variables();
865 return 0;
866 }
867
868 if (argc != 2) {
869 printf("Invalid GET_NETWORK command: needs two arguments\n"
870 "(network id and variable name)\n");
871 return -1;
872 }
873
874 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
875 argv[0], argv[1]);
876 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
877 printf("Too long GET_NETWORK command.\n");
878 return -1;
879 }
880 return wpa_ctrl_command(ctrl, cmd);
881 }
882
883
wpa_cli_cmd_disconnect(struct wpa_ctrl * ctrl,int argc,char * argv[])884 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
885 char *argv[])
886 {
887 return wpa_ctrl_command(ctrl, "DISCONNECT");
888 }
889
890
wpa_cli_cmd_reconnect(struct wpa_ctrl * ctrl,int argc,char * argv[])891 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
892 char *argv[])
893 {
894 return wpa_ctrl_command(ctrl, "RECONNECT");
895 }
896
897
wpa_cli_cmd_save_config(struct wpa_ctrl * ctrl,int argc,char * argv[])898 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
899 char *argv[])
900 {
901 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
902 }
903
904
wpa_cli_cmd_scan(struct wpa_ctrl * ctrl,int argc,char * argv[])905 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
906 {
907 return wpa_ctrl_command(ctrl, "SCAN");
908 }
909
910
wpa_cli_cmd_scan_results(struct wpa_ctrl * ctrl,int argc,char * argv[])911 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
912 char *argv[])
913 {
914 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
915 }
916
917
wpa_cli_cmd_get_capability(struct wpa_ctrl * ctrl,int argc,char * argv[])918 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
919 char *argv[])
920 {
921 char cmd[64];
922
923 if (argc < 1 || argc > 2) {
924 printf("Invalid GET_CAPABILITY command: need either one or "
925 "two arguments\n");
926 return -1;
927 }
928
929 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
930 printf("Invalid GET_CAPABILITY command: second argument, "
931 "if any, must be 'strict'\n");
932 return -1;
933 }
934
935 os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
936 (argc == 2) ? " strict" : "");
937 cmd[sizeof(cmd) - 1] = '\0';
938
939 return wpa_ctrl_command(ctrl, cmd);
940 }
941
942
wpa_cli_list_interfaces(struct wpa_ctrl * ctrl)943 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
944 {
945 printf("Available interfaces:\n");
946 return wpa_ctrl_command(ctrl, "INTERFACES");
947 }
948
949
wpa_cli_cmd_interface(struct wpa_ctrl * ctrl,int argc,char * argv[])950 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
951 {
952 if (argc < 1) {
953 wpa_cli_list_interfaces(ctrl);
954 return 0;
955 }
956
957 wpa_cli_close_connection();
958 os_free(ctrl_ifname);
959 ctrl_ifname = os_strdup(argv[0]);
960
961 if ((ctrl_conn = wpa_cli_open_connection(ctrl_ifname)) != NULL) {
962 printf("Connected to interface '%s.\n", ctrl_ifname);
963 if (wpa_ctrl_attach(monitor_conn) == 0) {
964 wpa_cli_attached = 1;
965 } else {
966 printf("Warning: Failed to attach to "
967 "wpa_supplicant.\n");
968 }
969 } else {
970 printf("Could not connect to interface '%s' - re-trying\n",
971 ctrl_ifname);
972 }
973 return 0;
974 }
975
976
wpa_cli_cmd_reconfigure(struct wpa_ctrl * ctrl,int argc,char * argv[])977 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
978 char *argv[])
979 {
980 return wpa_ctrl_command(ctrl, "RECONFIGURE");
981 }
982
983
wpa_cli_cmd_terminate(struct wpa_ctrl * ctrl,int argc,char * argv[])984 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
985 char *argv[])
986 {
987 return wpa_ctrl_command(ctrl, "TERMINATE");
988 }
989
990
wpa_cli_cmd_interface_add(struct wpa_ctrl * ctrl,int argc,char * argv[])991 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
992 char *argv[])
993 {
994 char cmd[256];
995
996 if (argc < 1) {
997 printf("Invalid INTERFACE_ADD command: needs at least one "
998 "argument (interface name)\n"
999 "All arguments: ifname confname driver ctrl_interface "
1000 "driver_param bridge_name\n");
1001 return -1;
1002 }
1003
1004 /*
1005 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1006 * <driver_param>TAB<bridge_name>
1007 */
1008 os_snprintf(cmd, sizeof(cmd), "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1009 argv[0],
1010 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1011 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1012 argc > 5 ? argv[5] : "");
1013 cmd[sizeof(cmd) - 1] = '\0';
1014 return wpa_ctrl_command(ctrl, cmd);
1015 }
1016
1017
wpa_cli_cmd_interface_remove(struct wpa_ctrl * ctrl,int argc,char * argv[])1018 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1019 char *argv[])
1020 {
1021 char cmd[128];
1022
1023 if (argc != 1) {
1024 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1025 "(interface name)\n");
1026 return -1;
1027 }
1028
1029 os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1030 cmd[sizeof(cmd) - 1] = '\0';
1031 return wpa_ctrl_command(ctrl, cmd);
1032 }
1033
wpa_cli_cmd_driver(struct wpa_ctrl * ctrl,int argc,char * argv[])1034 static int wpa_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc,
1035 char *argv[])
1036 {
1037 char cmd[32];
1038
1039 if (argc < 1) {
1040 printf("Invalid DRIVER command: needs one argument (cmd)\n");
1041 return -1;
1042 }
1043
1044 if (argc > 1)
1045 os_snprintf(cmd, sizeof(cmd), "DRIVER %s %s", argv[0], argv[1]);
1046 else
1047 os_snprintf(cmd, sizeof(cmd), "DRIVER %s", argv[0]);
1048 cmd[sizeof(cmd) - 1] = '\0';
1049
1050 return wpa_ctrl_command(ctrl, cmd);
1051 }
1052
1053 struct wpa_cli_cmd {
1054 const char *cmd;
1055 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1056 };
1057
1058 static struct wpa_cli_cmd wpa_cli_commands[] = {
1059 { "status", wpa_cli_cmd_status },
1060 { "ping", wpa_cli_cmd_ping },
1061 { "mib", wpa_cli_cmd_mib },
1062 { "help", wpa_cli_cmd_help },
1063 { "interface", wpa_cli_cmd_interface },
1064 { "level", wpa_cli_cmd_level },
1065 { "license", wpa_cli_cmd_license },
1066 { "quit", wpa_cli_cmd_quit },
1067 { "set", wpa_cli_cmd_set },
1068 { "logon", wpa_cli_cmd_logon },
1069 { "logoff", wpa_cli_cmd_logoff },
1070 { "pmksa", wpa_cli_cmd_pmksa },
1071 { "reassociate", wpa_cli_cmd_reassociate },
1072 { "preauthenticate", wpa_cli_cmd_preauthenticate },
1073 { "identity", wpa_cli_cmd_identity },
1074 { "password", wpa_cli_cmd_password },
1075 { "new_password", wpa_cli_cmd_new_password },
1076 { "pin", wpa_cli_cmd_pin },
1077 { "otp", wpa_cli_cmd_otp },
1078 { "passphrase", wpa_cli_cmd_passphrase },
1079 { "bssid", wpa_cli_cmd_bssid },
1080 #ifdef ANDROID
1081 { "blacklist", wpa_cli_cmd_blacklist },
1082 #endif
1083 { "list_networks", wpa_cli_cmd_list_networks },
1084 { "select_network", wpa_cli_cmd_select_network },
1085 { "enable_network", wpa_cli_cmd_enable_network },
1086 { "disable_network", wpa_cli_cmd_disable_network },
1087 { "add_network", wpa_cli_cmd_add_network },
1088 { "remove_network", wpa_cli_cmd_remove_network },
1089 { "set_network", wpa_cli_cmd_set_network },
1090 { "get_network", wpa_cli_cmd_get_network },
1091 { "save_config", wpa_cli_cmd_save_config },
1092 { "disconnect", wpa_cli_cmd_disconnect },
1093 { "reconnect", wpa_cli_cmd_reconnect },
1094 { "scan", wpa_cli_cmd_scan },
1095 { "scan_results", wpa_cli_cmd_scan_results },
1096 { "get_capability", wpa_cli_cmd_get_capability },
1097 { "reconfigure", wpa_cli_cmd_reconfigure },
1098 { "terminate", wpa_cli_cmd_terminate },
1099 { "interface_add", wpa_cli_cmd_interface_add },
1100 { "interface_remove", wpa_cli_cmd_interface_remove },
1101 { "ap_scan", wpa_cli_cmd_ap_scan },
1102 { "stkstart", wpa_cli_cmd_stkstart },
1103 { "driver", wpa_cli_cmd_driver },
1104 { NULL, NULL }
1105 };
1106
1107
wpa_request(struct wpa_ctrl * ctrl,int argc,char * argv[])1108 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1109 {
1110 struct wpa_cli_cmd *cmd, *match = NULL;
1111 int count;
1112 int ret = 0;
1113
1114 count = 0;
1115 cmd = wpa_cli_commands;
1116 while (cmd->cmd) {
1117 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1118 {
1119 match = cmd;
1120 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1121 /* we have an exact match */
1122 count = 1;
1123 break;
1124 }
1125 count++;
1126 }
1127 cmd++;
1128 }
1129
1130 if (count > 1) {
1131 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1132 cmd = wpa_cli_commands;
1133 while (cmd->cmd) {
1134 if (os_strncasecmp(cmd->cmd, argv[0],
1135 os_strlen(argv[0])) == 0) {
1136 printf(" %s", cmd->cmd);
1137 }
1138 cmd++;
1139 }
1140 printf("\n");
1141 ret = 1;
1142 } else if (count == 0) {
1143 printf("Unknown command '%s'\n", argv[0]);
1144 ret = 1;
1145 } else {
1146 if( os_strncasecmp( "level", argv[0], os_strlen(argv[0]) ) == 0 ) {
1147 ctrl = monitor_conn;
1148 }
1149 ret = match->handler(ctrl, argc - 1, &argv[1]);
1150 }
1151
1152 return ret;
1153 }
1154
1155
str_match(const char * a,const char * b)1156 static int str_match(const char *a, const char *b)
1157 {
1158 return os_strncmp(a, b, os_strlen(b)) == 0;
1159 }
1160
1161
wpa_cli_exec(const char * program,const char * arg1,const char * arg2)1162 static int wpa_cli_exec(const char *program, const char *arg1,
1163 const char *arg2)
1164 {
1165 char *cmd;
1166 size_t len;
1167
1168 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1169 cmd = os_malloc(len);
1170 if (cmd == NULL)
1171 return -1;
1172 os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1173 cmd[len - 1] = '\0';
1174 #ifndef _WIN32_WCE
1175 system(cmd);
1176 #endif /* _WIN32_WCE */
1177 os_free(cmd);
1178
1179 return 0;
1180 }
1181
1182
wpa_cli_action_process(const char * msg)1183 static void wpa_cli_action_process(const char *msg)
1184 {
1185 const char *pos;
1186 char *copy = NULL, *id, *pos2;
1187
1188 pos = msg;
1189 if (*pos == '<') {
1190 /* skip priority */
1191 pos = os_strchr(pos, '>');
1192 if (pos)
1193 pos++;
1194 else
1195 pos = msg;
1196 }
1197
1198 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1199 int new_id = -1;
1200 os_unsetenv("WPA_ID");
1201 os_unsetenv("WPA_ID_STR");
1202 os_unsetenv("WPA_CTRL_DIR");
1203
1204 pos = os_strstr(pos, "[id=");
1205 if (pos)
1206 copy = os_strdup(pos + 4);
1207
1208 if (copy) {
1209 pos2 = id = copy;
1210 while (*pos2 && *pos2 != ' ')
1211 pos2++;
1212 *pos2++ = '\0';
1213 new_id = atoi(id);
1214 os_setenv("WPA_ID", id, 1);
1215 while (*pos2 && *pos2 != '=')
1216 pos2++;
1217 if (*pos2 == '=')
1218 pos2++;
1219 id = pos2;
1220 while (*pos2 && *pos2 != ']')
1221 pos2++;
1222 *pos2 = '\0';
1223 os_setenv("WPA_ID_STR", id, 1);
1224 os_free(copy);
1225 }
1226
1227 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1228
1229 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1230 wpa_cli_connected = 1;
1231 wpa_cli_last_id = new_id;
1232 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1233 }
1234 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1235 if (wpa_cli_connected) {
1236 wpa_cli_connected = 0;
1237 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1238 }
1239 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1240 printf("wpa_supplicant is terminating - stop monitoring\n");
1241 wpa_cli_quit = 1;
1242 }
1243 }
1244
1245
1246 #ifndef CONFIG_ANSI_C_EXTRA
wpa_cli_action_cb(char * msg,size_t len)1247 static void wpa_cli_action_cb(char *msg, size_t len)
1248 {
1249 wpa_cli_action_process(msg);
1250 }
1251 #endif /* CONFIG_ANSI_C_EXTRA */
1252
1253
wpa_cli_reconnect(void)1254 static void wpa_cli_reconnect(void)
1255 {
1256 wpa_cli_close_connection();
1257 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1258 if (ctrl_conn) {
1259 printf("Connection to wpa_supplicant re-established\n");
1260 if (wpa_ctrl_attach(monitor_conn) == 0) {
1261 wpa_cli_attached = 1;
1262 } else {
1263 printf("Warning: Failed to attach to "
1264 "wpa_supplicant.\n");
1265 }
1266 }
1267 }
1268
1269
wpa_cli_recv_pending(struct wpa_ctrl * ctrl,int in_read,int action_monitor)1270 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1271 int action_monitor)
1272 {
1273 int first = 1;
1274 if (ctrl == NULL) {
1275 wpa_cli_reconnect();
1276 return;
1277 }
1278 while (wpa_ctrl_pending(ctrl) > 0) {
1279 char buf[256];
1280 size_t len = sizeof(buf) - 1;
1281 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1282 buf[len] = '\0';
1283 if (action_monitor)
1284 wpa_cli_action_process(buf);
1285 else {
1286 if (in_read && first)
1287 printf("\n");
1288 first = 0;
1289 printf("%s\n", buf);
1290 }
1291 } else {
1292 printf("Could not read pending message.\n");
1293 break;
1294 }
1295 }
1296
1297 if (wpa_ctrl_pending(ctrl) < 0) {
1298 printf("Connection to wpa_supplicant lost - trying to "
1299 "reconnect\n");
1300 wpa_cli_reconnect();
1301 }
1302 }
1303
1304
1305 #ifdef CONFIG_READLINE
wpa_cli_cmd_gen(const char * text,int state)1306 static char * wpa_cli_cmd_gen(const char *text, int state)
1307 {
1308 static int i, len;
1309 const char *cmd;
1310
1311 if (state == 0) {
1312 i = 0;
1313 len = os_strlen(text);
1314 }
1315
1316 while ((cmd = wpa_cli_commands[i].cmd)) {
1317 i++;
1318 if (os_strncasecmp(cmd, text, len) == 0)
1319 return os_strdup(cmd);
1320 }
1321
1322 return NULL;
1323 }
1324
1325
wpa_cli_dummy_gen(const char * text,int state)1326 static char * wpa_cli_dummy_gen(const char *text, int state)
1327 {
1328 return NULL;
1329 }
1330
1331
wpa_cli_completion(const char * text,int start,int end)1332 static char ** wpa_cli_completion(const char *text, int start, int end)
1333 {
1334 return rl_completion_matches(text, start == 0 ?
1335 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1336 }
1337 #endif /* CONFIG_READLINE */
1338
1339
wpa_cli_interactive(void)1340 static void wpa_cli_interactive(void)
1341 {
1342 #define max_args 10
1343 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1344 int argc;
1345 #ifdef CONFIG_READLINE
1346 char *home, *hfile = NULL;
1347 #endif /* CONFIG_READLINE */
1348
1349 printf("\nInteractive mode\n\n");
1350
1351 #ifdef CONFIG_READLINE
1352 rl_attempted_completion_function = wpa_cli_completion;
1353 home = getenv("HOME");
1354 if (home) {
1355 const char *fname = ".wpa_cli_history";
1356 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1357 hfile = os_malloc(hfile_len);
1358 if (hfile) {
1359 os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
1360 hfile[hfile_len - 1] = '\0';
1361 read_history(hfile);
1362 stifle_history(100);
1363 }
1364 }
1365 #endif /* CONFIG_READLINE */
1366
1367 do {
1368 wpa_cli_recv_pending(monitor_conn, 0, 0);
1369 #ifndef CONFIG_NATIVE_WINDOWS
1370 alarm(1);
1371 #endif /* CONFIG_NATIVE_WINDOWS */
1372 #ifdef CONFIG_READLINE
1373 cmd = readline("> ");
1374 if (cmd && *cmd) {
1375 HIST_ENTRY *h;
1376 while (next_history())
1377 ;
1378 h = previous_history();
1379 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1380 add_history(cmd);
1381 next_history();
1382 }
1383 #else /* CONFIG_READLINE */
1384 printf("> ");
1385 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1386 #endif /* CONFIG_READLINE */
1387 #ifndef CONFIG_NATIVE_WINDOWS
1388 alarm(0);
1389 #endif /* CONFIG_NATIVE_WINDOWS */
1390 if (cmd == NULL)
1391 break;
1392 wpa_cli_recv_pending(monitor_conn, 0, 0);
1393 pos = cmd;
1394 while (*pos != '\0') {
1395 if (*pos == '\n') {
1396 *pos = '\0';
1397 break;
1398 }
1399 pos++;
1400 }
1401 argc = 0;
1402 pos = cmd;
1403 for (;;) {
1404 while (*pos == ' ')
1405 pos++;
1406 if (*pos == '\0')
1407 break;
1408 argv[argc] = pos;
1409 argc++;
1410 if (argc == max_args)
1411 break;
1412 if (*pos == '"') {
1413 char *pos2 = os_strrchr(pos, '"');
1414 if (pos2)
1415 pos = pos2 + 1;
1416 }
1417 while (*pos != '\0' && *pos != ' ')
1418 pos++;
1419 if (*pos == ' ')
1420 *pos++ = '\0';
1421 }
1422 if (argc)
1423 wpa_request(ctrl_conn, argc, argv);
1424
1425 if (cmd != cmdbuf)
1426 os_free(cmd);
1427 } while (!wpa_cli_quit);
1428
1429 #ifdef CONFIG_READLINE
1430 if (hfile) {
1431 /* Save command history, excluding lines that may contain
1432 * passwords. */
1433 HIST_ENTRY *h;
1434 history_set_pos(0);
1435 h = next_history();
1436 while (h) {
1437 char *p = h->line;
1438 while (*p == ' ' || *p == '\t')
1439 p++;
1440 if (os_strncasecmp(p, "pa", 2) == 0 ||
1441 os_strncasecmp(p, "o", 1) == 0 ||
1442 os_strncasecmp(p, "n", 1)) {
1443 h = remove_history(where_history());
1444 if (h) {
1445 os_free(h->line);
1446 os_free(h->data);
1447 os_free(h);
1448 }
1449 h = current_history();
1450 } else {
1451 h = next_history();
1452 }
1453 }
1454 write_history(hfile);
1455 os_free(hfile);
1456 }
1457 #endif /* CONFIG_READLINE */
1458 }
1459
1460
wpa_cli_action(struct wpa_ctrl * ctrl)1461 static void wpa_cli_action(struct wpa_ctrl *ctrl)
1462 {
1463 #ifdef CONFIG_ANSI_C_EXTRA
1464 /* TODO: ANSI C version(?) */
1465 printf("Action processing not supported in ANSI C build.\n");
1466 #else /* CONFIG_ANSI_C_EXTRA */
1467 fd_set rfds;
1468 int fd, res;
1469 struct timeval tv;
1470 char buf[256]; /* note: large enough to fit in unsolicited messages */
1471 size_t len;
1472
1473 fd = wpa_ctrl_get_fd(ctrl);
1474
1475 while (!wpa_cli_quit) {
1476 FD_ZERO(&rfds);
1477 FD_SET(fd, &rfds);
1478 tv.tv_sec = 2;
1479 tv.tv_usec = 0;
1480 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1481 if (res < 0 && errno != EINTR) {
1482 perror("select");
1483 break;
1484 }
1485
1486 if (FD_ISSET(fd, &rfds))
1487 wpa_cli_recv_pending(ctrl, 0, 1);
1488 else {
1489 /* verify that connection is still working */
1490 len = sizeof(buf) - 1;
1491 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1492 wpa_cli_action_cb) < 0 ||
1493 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1494 printf("wpa_supplicant did not reply to PING "
1495 "command - exiting\n");
1496 break;
1497 }
1498 }
1499 }
1500 #endif /* CONFIG_ANSI_C_EXTRA */
1501 }
1502
1503
wpa_cli_cleanup(void)1504 static void wpa_cli_cleanup(void)
1505 {
1506 wpa_cli_close_connection();
1507 if (pid_file)
1508 os_daemonize_terminate(pid_file);
1509
1510 os_program_deinit();
1511 }
1512
wpa_cli_terminate(int sig)1513 static void wpa_cli_terminate(int sig)
1514 {
1515 wpa_cli_cleanup();
1516 exit(0);
1517 }
1518
1519
1520 #ifndef CONFIG_NATIVE_WINDOWS
wpa_cli_alarm(int sig)1521 static void wpa_cli_alarm(int sig)
1522 {
1523 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1524 printf("Connection to wpa_supplicant lost - trying to "
1525 "reconnect\n");
1526 wpa_cli_close_connection();
1527 }
1528 if (!monitor_conn)
1529 wpa_cli_reconnect();
1530 if (monitor_conn)
1531 wpa_cli_recv_pending(monitor_conn, 1, 0);
1532 alarm(1);
1533 }
1534 #endif /* CONFIG_NATIVE_WINDOWS */
1535
1536
wpa_cli_get_default_ifname(void)1537 static char * wpa_cli_get_default_ifname(void)
1538 {
1539 char *ifname = NULL;
1540
1541 #ifdef CONFIG_CTRL_IFACE_UNIX
1542 struct dirent *dent;
1543 DIR *dir = opendir(ctrl_iface_dir);
1544 if (!dir) {
1545 #ifdef ANDROID
1546 char ifprop[PROPERTY_VALUE_MAX];
1547 if (property_get("wifi.interface", ifprop, NULL) != 0) {
1548 ifname = os_strdup(ifprop);
1549 printf("Using interface '%s'\n", ifname);
1550 return ifname;
1551 }
1552 #endif
1553 return NULL;
1554 }
1555 while ((dent = readdir(dir))) {
1556 #ifdef _DIRENT_HAVE_D_TYPE
1557 /*
1558 * Skip the file if it is not a socket. Also accept
1559 * DT_UNKNOWN (0) in case the C library or underlying
1560 * file system does not support d_type.
1561 */
1562 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1563 continue;
1564 #endif /* _DIRENT_HAVE_D_TYPE */
1565 if (os_strcmp(dent->d_name, ".") == 0 ||
1566 os_strcmp(dent->d_name, "..") == 0)
1567 continue;
1568 printf("Selected interface '%s'\n", dent->d_name);
1569 ifname = os_strdup(dent->d_name);
1570 break;
1571 }
1572 closedir(dir);
1573 #endif /* CONFIG_CTRL_IFACE_UNIX */
1574
1575 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1576 char buf[4096], *pos;
1577 size_t len;
1578 struct wpa_ctrl *ctrl;
1579 int ret;
1580
1581 ctrl = wpa_ctrl_open(NULL);
1582 if (ctrl == NULL)
1583 return NULL;
1584
1585 len = sizeof(buf) - 1;
1586 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1587 if (ret >= 0) {
1588 buf[len] = '\0';
1589 pos = os_strchr(buf, '\n');
1590 if (pos)
1591 *pos = '\0';
1592 ifname = os_strdup(buf);
1593 }
1594 wpa_ctrl_close(ctrl);
1595 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1596
1597 return ifname;
1598 }
1599
1600
main(int argc,char * argv[])1601 int main(int argc, char *argv[])
1602 {
1603 int interactive;
1604 int warning_displayed = 0;
1605 int c;
1606 int daemonize = 0;
1607 int ret = 0;
1608 const char *global = NULL;
1609
1610 if (os_program_init())
1611 return -1;
1612
1613 for (;;) {
1614 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1615 if (c < 0)
1616 break;
1617 switch (c) {
1618 case 'a':
1619 action_file = optarg;
1620 break;
1621 case 'B':
1622 daemonize = 1;
1623 break;
1624 case 'g':
1625 global = optarg;
1626 break;
1627 case 'h':
1628 usage();
1629 return 0;
1630 case 'v':
1631 printf("%s\n", wpa_cli_version);
1632 return 0;
1633 case 'i':
1634 os_free(ctrl_ifname);
1635 ctrl_ifname = os_strdup(optarg);
1636 break;
1637 case 'p':
1638 ctrl_iface_dir = optarg;
1639 break;
1640 case 'P':
1641 pid_file = optarg;
1642 break;
1643 default:
1644 usage();
1645 return -1;
1646 }
1647 }
1648
1649 interactive = (argc == optind) && (action_file == NULL);
1650
1651 if (interactive)
1652 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1653
1654 if (global) {
1655 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1656 ctrl_conn = wpa_ctrl_open(NULL);
1657 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1658 ctrl_conn = wpa_ctrl_open(global);
1659 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1660 if (ctrl_conn == NULL) {
1661 perror("Failed to connect to wpa_supplicant - "
1662 "wpa_ctrl_open");
1663 return -1;
1664 }
1665 }
1666
1667 for (; !global;) {
1668 if (ctrl_ifname == NULL)
1669 ctrl_ifname = wpa_cli_get_default_ifname();
1670 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1671 if (ctrl_conn) {
1672 if (warning_displayed)
1673 printf("Connection established.\n");
1674 break;
1675 }
1676
1677 if (!interactive) {
1678 perror("Failed to connect to wpa_supplicant - "
1679 "wpa_ctrl_open");
1680 return -1;
1681 }
1682
1683 if (!warning_displayed) {
1684 printf("Could not connect to wpa_supplicant - "
1685 "re-trying\n");
1686 warning_displayed = 1;
1687 }
1688 os_sleep(1, 0);
1689 continue;
1690 }
1691
1692 #ifndef _WIN32_WCE
1693 signal(SIGINT, wpa_cli_terminate);
1694 signal(SIGTERM, wpa_cli_terminate);
1695 #endif /* _WIN32_WCE */
1696 #ifndef CONFIG_NATIVE_WINDOWS
1697 signal(SIGALRM, wpa_cli_alarm);
1698 #endif /* CONFIG_NATIVE_WINDOWS */
1699
1700 if (interactive || action_file) {
1701 if (wpa_ctrl_attach(monitor_conn) == 0) {
1702 wpa_cli_attached = 1;
1703 } else {
1704 printf("Warning: Failed to attach to "
1705 "wpa_supplicant.\n");
1706 if (!interactive)
1707 return -1;
1708 }
1709 }
1710
1711 if (daemonize && os_daemonize(pid_file))
1712 return -1;
1713
1714 if (interactive)
1715 wpa_cli_interactive();
1716 else if (action_file)
1717 wpa_cli_action(ctrl_conn);
1718 else
1719 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1720
1721 os_free(ctrl_ifname);
1722 wpa_cli_cleanup();
1723
1724 return ret;
1725 }
1726
1727 #else /* CONFIG_CTRL_IFACE */
main(int argc,char * argv[])1728 int main(int argc, char *argv[])
1729 {
1730 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1731 return -1;
1732 }
1733 #endif /* CONFIG_CTRL_IFACE */
1734