Home | History | Annotate | Download | only in wpa_supplicant
      1 /*
      2  * WPA Supplicant - command line interface for wpa_supplicant daemon
      3  * Copyright (c) 2004-2008, Jouni Malinen <j (at) 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 (at) 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 
    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 
    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 
    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 
    236 static void wpa_cli_msg_cb(char *msg, size_t len)
    237 {
    238 	printf("%s\n", msg);
    239 }
    240 
    241 
    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 
    270 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
    271 {
    272 	return _wpa_ctrl_command(ctrl, cmd, 1);
    273 }
    274 
    275 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
   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 
   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 
   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 
   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 
   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 
   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
   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 
   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 
   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
   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 
   1326 static char * wpa_cli_dummy_gen(const char *text, int state)
   1327 {
   1328 	return NULL;
   1329 }
   1330 
   1331 
   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 
   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 
   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 
   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 
   1513 static void wpa_cli_terminate(int sig)
   1514 {
   1515 	wpa_cli_cleanup();
   1516 	exit(0);
   1517 }
   1518 
   1519 
   1520 #ifndef CONFIG_NATIVE_WINDOWS
   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 
   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 
   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 */
   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