• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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