Home | History | Annotate | Download | only in hostapd
      1 /*
      2  * hostapd - command line interface for hostapd daemon
      3  * Copyright (c) 2004-2014, Jouni Malinen <j (at) w1.fi>
      4  *
      5  * This software may be distributed under the terms of the BSD license.
      6  * See README for more details.
      7  */
      8 
      9 #include "includes.h"
     10 #include <dirent.h>
     11 
     12 #include "common/wpa_ctrl.h"
     13 #include "utils/common.h"
     14 #include "utils/eloop.h"
     15 #include "utils/edit.h"
     16 #include "common/version.h"
     17 
     18 
     19 static const char *hostapd_cli_version =
     20 "hostapd_cli v" VERSION_STR "\n"
     21 "Copyright (c) 2004-2014, Jouni Malinen <j (at) w1.fi> and contributors";
     22 
     23 
     24 static const char *hostapd_cli_license =
     25 "This software may be distributed under the terms of the BSD license.\n"
     26 "See README for more details.\n";
     27 
     28 static const char *hostapd_cli_full_license =
     29 "This software may be distributed under the terms of the BSD license.\n"
     30 "\n"
     31 "Redistribution and use in source and binary forms, with or without\n"
     32 "modification, are permitted provided that the following conditions are\n"
     33 "met:\n"
     34 "\n"
     35 "1. Redistributions of source code must retain the above copyright\n"
     36 "   notice, this list of conditions and the following disclaimer.\n"
     37 "\n"
     38 "2. Redistributions in binary form must reproduce the above copyright\n"
     39 "   notice, this list of conditions and the following disclaimer in the\n"
     40 "   documentation and/or other materials provided with the distribution.\n"
     41 "\n"
     42 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
     43 "   names of its contributors may be used to endorse or promote products\n"
     44 "   derived from this software without specific prior written permission.\n"
     45 "\n"
     46 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
     47 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
     48 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
     49 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
     50 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
     51 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
     52 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
     53 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
     54 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
     55 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
     56 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
     57 "\n";
     58 
     59 static const char *commands_help =
     60 "Commands:\n"
     61 "   mib                  get MIB variables (dot1x, dot11, radius)\n"
     62 "   sta <addr>           get MIB variables for one station\n"
     63 "   all_sta              get MIB variables for all stations\n"
     64 "   new_sta <addr>       add a new station\n"
     65 "   deauthenticate <addr>  deauthenticate a station\n"
     66 "   disassociate <addr>  disassociate a station\n"
     67 #ifdef CONFIG_IEEE80211W
     68 "   sa_query <addr>      send SA Query to a station\n"
     69 #endif /* CONFIG_IEEE80211W */
     70 #ifdef CONFIG_WPS
     71 "   wps_pin <uuid> <pin> [timeout] [addr]  add WPS Enrollee PIN\n"
     72 "   wps_check_pin <PIN>  verify PIN checksum\n"
     73 "   wps_pbc              indicate button pushed to initiate PBC\n"
     74 "   wps_cancel           cancel the pending WPS operation\n"
     75 #ifdef CONFIG_WPS_NFC
     76 "   wps_nfc_tag_read <hexdump>  report read NFC tag with WPS data\n"
     77 "   wps_nfc_config_token <WPS/NDEF>  build NFC configuration token\n"
     78 "   wps_nfc_token <WPS/NDEF/enable/disable>  manager NFC password token\n"
     79 #endif /* CONFIG_WPS_NFC */
     80 "   wps_ap_pin <cmd> [params..]  enable/disable AP PIN\n"
     81 "   wps_config <SSID> <auth> <encr> <key>  configure AP\n"
     82 "   wps_get_status       show current WPS status\n"
     83 #endif /* CONFIG_WPS */
     84 "   get_config           show current configuration\n"
     85 "   help                 show this usage help\n"
     86 "   interface [ifname]   show interfaces/select interface\n"
     87 "   level <debug level>  change debug level\n"
     88 "   license              show full hostapd_cli license\n"
     89 "   quit                 exit hostapd_cli\n";
     90 
     91 static struct wpa_ctrl *ctrl_conn;
     92 static int hostapd_cli_quit = 0;
     93 static int hostapd_cli_attached = 0;
     94 
     95 #ifndef CONFIG_CTRL_IFACE_DIR
     96 #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
     97 #endif /* CONFIG_CTRL_IFACE_DIR */
     98 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
     99 
    100 static char *ctrl_ifname = NULL;
    101 static const char *pid_file = NULL;
    102 static const char *action_file = NULL;
    103 static int ping_interval = 5;
    104 static int interactive = 0;
    105 
    106 
    107 static void usage(void)
    108 {
    109 	fprintf(stderr, "%s\n", hostapd_cli_version);
    110 	fprintf(stderr,
    111 		"\n"
    112 		"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
    113 		"[-a<path>] \\\n"
    114 		"                   [-G<ping interval>] [command..]\n"
    115 		"\n"
    116 		"Options:\n"
    117 		"   -h           help (show this usage text)\n"
    118 		"   -v           shown version information\n"
    119 		"   -p<path>     path to find control sockets (default: "
    120 		"/var/run/hostapd)\n"
    121 		"   -a<file>     run in daemon mode executing the action file "
    122 		"based on events\n"
    123 		"                from hostapd\n"
    124 		"   -B           run a daemon in the background\n"
    125 		"   -i<ifname>   Interface to listen on (default: first "
    126 		"interface found in the\n"
    127 		"                socket path)\n\n"
    128 		"%s",
    129 		commands_help);
    130 }
    131 
    132 
    133 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
    134 {
    135 	char *cfile;
    136 	int flen;
    137 
    138 	if (ifname == NULL)
    139 		return NULL;
    140 
    141 	flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
    142 	cfile = malloc(flen);
    143 	if (cfile == NULL)
    144 		return NULL;
    145 	snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
    146 
    147 	ctrl_conn = wpa_ctrl_open(cfile);
    148 	free(cfile);
    149 	return ctrl_conn;
    150 }
    151 
    152 
    153 static void hostapd_cli_close_connection(void)
    154 {
    155 	if (ctrl_conn == NULL)
    156 		return;
    157 
    158 	if (hostapd_cli_attached) {
    159 		wpa_ctrl_detach(ctrl_conn);
    160 		hostapd_cli_attached = 0;
    161 	}
    162 	wpa_ctrl_close(ctrl_conn);
    163 	ctrl_conn = NULL;
    164 }
    165 
    166 
    167 static void hostapd_cli_msg_cb(char *msg, size_t len)
    168 {
    169 	printf("%s\n", msg);
    170 }
    171 
    172 
    173 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
    174 {
    175 	char buf[4096];
    176 	size_t len;
    177 	int ret;
    178 
    179 	if (ctrl_conn == NULL) {
    180 		printf("Not connected to hostapd - command dropped.\n");
    181 		return -1;
    182 	}
    183 	len = sizeof(buf) - 1;
    184 	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
    185 			       hostapd_cli_msg_cb);
    186 	if (ret == -2) {
    187 		printf("'%s' command timed out.\n", cmd);
    188 		return -2;
    189 	} else if (ret < 0) {
    190 		printf("'%s' command failed.\n", cmd);
    191 		return -1;
    192 	}
    193 	if (print) {
    194 		buf[len] = '\0';
    195 		printf("%s", buf);
    196 	}
    197 	return 0;
    198 }
    199 
    200 
    201 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
    202 {
    203 	return _wpa_ctrl_command(ctrl, cmd, 1);
    204 }
    205 
    206 
    207 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
    208 {
    209 	return wpa_ctrl_command(ctrl, "PING");
    210 }
    211 
    212 
    213 static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
    214 {
    215 	return wpa_ctrl_command(ctrl, "RELOG");
    216 }
    217 
    218 
    219 static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
    220 {
    221 	if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
    222 		return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
    223 	return wpa_ctrl_command(ctrl, "STATUS");
    224 }
    225 
    226 
    227 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
    228 {
    229 	if (argc > 0) {
    230 		char buf[100];
    231 		os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
    232 		return wpa_ctrl_command(ctrl, buf);
    233 	}
    234 	return wpa_ctrl_command(ctrl, "MIB");
    235 }
    236 
    237 
    238 static int hostapd_cli_exec(const char *program, const char *arg1,
    239 			    const char *arg2)
    240 {
    241 	char *arg;
    242 	size_t len;
    243 	int res;
    244 
    245 	len = os_strlen(arg1) + os_strlen(arg2) + 2;
    246 	arg = os_malloc(len);
    247 	if (arg == NULL)
    248 		return -1;
    249 	os_snprintf(arg, len, "%s %s", arg1, arg2);
    250 	res = os_exec(program, arg, 1);
    251 	os_free(arg);
    252 
    253 	return res;
    254 }
    255 
    256 
    257 static void hostapd_cli_action_process(char *msg, size_t len)
    258 {
    259 	const char *pos;
    260 
    261 	pos = msg;
    262 	if (*pos == '<') {
    263 		pos = os_strchr(pos, '>');
    264 		if (pos)
    265 			pos++;
    266 		else
    267 			pos = msg;
    268 	}
    269 
    270 	hostapd_cli_exec(action_file, ctrl_ifname, pos);
    271 }
    272 
    273 
    274 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
    275 {
    276 	char buf[64];
    277 	if (argc < 1) {
    278 		printf("Invalid 'sta' command - at least one argument, STA "
    279 		       "address, is required.\n");
    280 		return -1;
    281 	}
    282 	if (argc > 1)
    283 		snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
    284 	else
    285 		snprintf(buf, sizeof(buf), "STA %s", argv[0]);
    286 	return wpa_ctrl_command(ctrl, buf);
    287 }
    288 
    289 
    290 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
    291 				   char *argv[])
    292 {
    293 	char buf[64];
    294 	if (argc != 1) {
    295 		printf("Invalid 'new_sta' command - exactly one argument, STA "
    296 		       "address, is required.\n");
    297 		return -1;
    298 	}
    299 	snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
    300 	return wpa_ctrl_command(ctrl, buf);
    301 }
    302 
    303 
    304 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
    305 					  char *argv[])
    306 {
    307 	char buf[64];
    308 	if (argc < 1) {
    309 		printf("Invalid 'deauthenticate' command - exactly one "
    310 		       "argument, STA address, is required.\n");
    311 		return -1;
    312 	}
    313 	if (argc > 1)
    314 		os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
    315 			    argv[0], argv[1]);
    316 	else
    317 		os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
    318 	return wpa_ctrl_command(ctrl, buf);
    319 }
    320 
    321 
    322 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
    323 					char *argv[])
    324 {
    325 	char buf[64];
    326 	if (argc < 1) {
    327 		printf("Invalid 'disassociate' command - exactly one "
    328 		       "argument, STA address, is required.\n");
    329 		return -1;
    330 	}
    331 	if (argc > 1)
    332 		os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
    333 			    argv[0], argv[1]);
    334 	else
    335 		os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
    336 	return wpa_ctrl_command(ctrl, buf);
    337 }
    338 
    339 
    340 #ifdef CONFIG_IEEE80211W
    341 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
    342 				    char *argv[])
    343 {
    344 	char buf[64];
    345 	if (argc != 1) {
    346 		printf("Invalid 'sa_query' command - exactly one argument, "
    347 		       "STA address, is required.\n");
    348 		return -1;
    349 	}
    350 	snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
    351 	return wpa_ctrl_command(ctrl, buf);
    352 }
    353 #endif /* CONFIG_IEEE80211W */
    354 
    355 
    356 #ifdef CONFIG_WPS
    357 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
    358 				   char *argv[])
    359 {
    360 	char buf[256];
    361 	if (argc < 2) {
    362 		printf("Invalid 'wps_pin' command - at least two arguments, "
    363 		       "UUID and PIN, are required.\n");
    364 		return -1;
    365 	}
    366 	if (argc > 3)
    367 		snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
    368 			 argv[0], argv[1], argv[2], argv[3]);
    369 	else if (argc > 2)
    370 		snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
    371 			 argv[0], argv[1], argv[2]);
    372 	else
    373 		snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
    374 	return wpa_ctrl_command(ctrl, buf);
    375 }
    376 
    377 
    378 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
    379 					 char *argv[])
    380 {
    381 	char cmd[256];
    382 	int res;
    383 
    384 	if (argc != 1 && argc != 2) {
    385 		printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
    386 		       "- PIN to be verified\n");
    387 		return -1;
    388 	}
    389 
    390 	if (argc == 2)
    391 		res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
    392 				  argv[0], argv[1]);
    393 	else
    394 		res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
    395 				  argv[0]);
    396 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
    397 		printf("Too long WPS_CHECK_PIN command.\n");
    398 		return -1;
    399 	}
    400 	return wpa_ctrl_command(ctrl, cmd);
    401 }
    402 
    403 
    404 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
    405 				   char *argv[])
    406 {
    407 	return wpa_ctrl_command(ctrl, "WPS_PBC");
    408 }
    409 
    410 
    411 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
    412 				      char *argv[])
    413 {
    414 	return wpa_ctrl_command(ctrl, "WPS_CANCEL");
    415 }
    416 
    417 
    418 #ifdef CONFIG_WPS_NFC
    419 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
    420 					    char *argv[])
    421 {
    422 	int ret;
    423 	char *buf;
    424 	size_t buflen;
    425 
    426 	if (argc != 1) {
    427 		printf("Invalid 'wps_nfc_tag_read' command - one argument "
    428 		       "is required.\n");
    429 		return -1;
    430 	}
    431 
    432 	buflen = 18 + os_strlen(argv[0]);
    433 	buf = os_malloc(buflen);
    434 	if (buf == NULL)
    435 		return -1;
    436 	os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
    437 
    438 	ret = wpa_ctrl_command(ctrl, buf);
    439 	os_free(buf);
    440 
    441 	return ret;
    442 }
    443 
    444 
    445 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
    446 						int argc, char *argv[])
    447 {
    448 	char cmd[64];
    449 	int res;
    450 
    451 	if (argc != 1) {
    452 		printf("Invalid 'wps_nfc_config_token' command - one argument "
    453 		       "is required.\n");
    454 		return -1;
    455 	}
    456 
    457 	res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
    458 			  argv[0]);
    459 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
    460 		printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
    461 		return -1;
    462 	}
    463 	return wpa_ctrl_command(ctrl, cmd);
    464 }
    465 
    466 
    467 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
    468 					 int argc, char *argv[])
    469 {
    470 	char cmd[64];
    471 	int res;
    472 
    473 	if (argc != 1) {
    474 		printf("Invalid 'wps_nfc_token' command - one argument is "
    475 		       "required.\n");
    476 		return -1;
    477 	}
    478 
    479 	res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
    480 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
    481 		printf("Too long WPS_NFC_TOKEN command.\n");
    482 		return -1;
    483 	}
    484 	return wpa_ctrl_command(ctrl, cmd);
    485 }
    486 
    487 
    488 static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
    489 						int argc, char *argv[])
    490 {
    491 	char cmd[64];
    492 	int res;
    493 
    494 	if (argc != 2) {
    495 		printf("Invalid 'nfc_get_handover_sel' command - two arguments "
    496 		       "are required.\n");
    497 		return -1;
    498 	}
    499 
    500 	res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
    501 			  argv[0], argv[1]);
    502 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
    503 		printf("Too long NFC_GET_HANDOVER_SEL command.\n");
    504 		return -1;
    505 	}
    506 	return wpa_ctrl_command(ctrl, cmd);
    507 }
    508 
    509 #endif /* CONFIG_WPS_NFC */
    510 
    511 
    512 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
    513 				      char *argv[])
    514 {
    515 	char buf[64];
    516 	if (argc < 1) {
    517 		printf("Invalid 'wps_ap_pin' command - at least one argument "
    518 		       "is required.\n");
    519 		return -1;
    520 	}
    521 	if (argc > 2)
    522 		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
    523 			 argv[0], argv[1], argv[2]);
    524 	else if (argc > 1)
    525 		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
    526 			 argv[0], argv[1]);
    527 	else
    528 		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
    529 	return wpa_ctrl_command(ctrl, buf);
    530 }
    531 
    532 
    533 static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
    534 					  char *argv[])
    535 {
    536 	return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
    537 }
    538 
    539 
    540 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
    541 				      char *argv[])
    542 {
    543 	char buf[256];
    544 	char ssid_hex[2 * 32 + 1];
    545 	char key_hex[2 * 64 + 1];
    546 	int i;
    547 
    548 	if (argc < 1) {
    549 		printf("Invalid 'wps_config' command - at least two arguments "
    550 		       "are required.\n");
    551 		return -1;
    552 	}
    553 
    554 	ssid_hex[0] = '\0';
    555 	for (i = 0; i < 32; i++) {
    556 		if (argv[0][i] == '\0')
    557 			break;
    558 		os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
    559 	}
    560 
    561 	key_hex[0] = '\0';
    562 	if (argc > 3) {
    563 		for (i = 0; i < 64; i++) {
    564 			if (argv[3][i] == '\0')
    565 				break;
    566 			os_snprintf(&key_hex[i * 2], 3, "%02x",
    567 				    argv[3][i]);
    568 		}
    569 	}
    570 
    571 	if (argc > 3)
    572 		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
    573 			 ssid_hex, argv[1], argv[2], key_hex);
    574 	else if (argc > 2)
    575 		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
    576 			 ssid_hex, argv[1], argv[2]);
    577 	else
    578 		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
    579 			 ssid_hex, argv[1]);
    580 	return wpa_ctrl_command(ctrl, buf);
    581 }
    582 #endif /* CONFIG_WPS */
    583 
    584 
    585 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
    586 					     char *argv[])
    587 {
    588 	char buf[300];
    589 	int res;
    590 
    591 	if (argc < 2) {
    592 		printf("Invalid 'disassoc_imminent' command - two arguments "
    593 		       "(STA addr and Disassociation Timer) are needed\n");
    594 		return -1;
    595 	}
    596 
    597 	res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
    598 			  argv[0], argv[1]);
    599 	if (res < 0 || res >= (int) sizeof(buf))
    600 		return -1;
    601 	return wpa_ctrl_command(ctrl, buf);
    602 }
    603 
    604 
    605 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
    606 					char *argv[])
    607 {
    608 	char buf[300];
    609 	int res;
    610 
    611 	if (argc < 3) {
    612 		printf("Invalid 'ess_disassoc' command - three arguments (STA "
    613 		       "addr, disassoc timer, and URL) are needed\n");
    614 		return -1;
    615 	}
    616 
    617 	res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
    618 			  argv[0], argv[1], argv[2]);
    619 	if (res < 0 || res >= (int) sizeof(buf))
    620 		return -1;
    621 	return wpa_ctrl_command(ctrl, buf);
    622 }
    623 
    624 
    625 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
    626 				      char *argv[])
    627 {
    628 	return wpa_ctrl_command(ctrl, "GET_CONFIG");
    629 }
    630 
    631 
    632 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
    633 				char *addr, size_t addr_len)
    634 {
    635 	char buf[4096], *pos;
    636 	size_t len;
    637 	int ret;
    638 
    639 	if (ctrl_conn == NULL) {
    640 		printf("Not connected to hostapd - command dropped.\n");
    641 		return -1;
    642 	}
    643 	len = sizeof(buf) - 1;
    644 	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
    645 			       hostapd_cli_msg_cb);
    646 	if (ret == -2) {
    647 		printf("'%s' command timed out.\n", cmd);
    648 		return -2;
    649 	} else if (ret < 0) {
    650 		printf("'%s' command failed.\n", cmd);
    651 		return -1;
    652 	}
    653 
    654 	buf[len] = '\0';
    655 	if (memcmp(buf, "FAIL", 4) == 0)
    656 		return -1;
    657 	printf("%s", buf);
    658 
    659 	pos = buf;
    660 	while (*pos != '\0' && *pos != '\n')
    661 		pos++;
    662 	*pos = '\0';
    663 	os_strlcpy(addr, buf, addr_len);
    664 	return 0;
    665 }
    666 
    667 
    668 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
    669 				   char *argv[])
    670 {
    671 	char addr[32], cmd[64];
    672 
    673 	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
    674 		return 0;
    675 	do {
    676 		snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
    677 	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
    678 
    679 	return -1;
    680 }
    681 
    682 
    683 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
    684 {
    685 	printf("%s", commands_help);
    686 	return 0;
    687 }
    688 
    689 
    690 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
    691 				   char *argv[])
    692 {
    693 	printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
    694 	return 0;
    695 }
    696 
    697 
    698 static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
    699 					   int argc, char *argv[])
    700 {
    701 	char buf[200];
    702 	int res;
    703 
    704 	if (argc != 1) {
    705 		printf("Invalid 'set_qos_map_set' command - "
    706 		       "one argument (comma delimited QoS map set) "
    707 		       "is needed\n");
    708 		return -1;
    709 	}
    710 
    711 	res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
    712 	if (res < 0 || res >= (int) sizeof(buf))
    713 		return -1;
    714 	return wpa_ctrl_command(ctrl, buf);
    715 }
    716 
    717 
    718 static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
    719 					     int argc, char *argv[])
    720 {
    721 	char buf[50];
    722 	int res;
    723 
    724 	if (argc != 1) {
    725 		printf("Invalid 'send_qos_map_conf' command - "
    726 		       "one argument (STA addr) is needed\n");
    727 		return -1;
    728 	}
    729 
    730 	res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
    731 	if (res < 0 || res >= (int) sizeof(buf))
    732 		return -1;
    733 	return wpa_ctrl_command(ctrl, buf);
    734 }
    735 
    736 
    737 static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
    738 					  char *argv[])
    739 {
    740 	char buf[300];
    741 	int res;
    742 
    743 	if (argc < 2) {
    744 		printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
    745 		       "addr and URL) are needed\n");
    746 		return -1;
    747 	}
    748 
    749 	res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
    750 			  argv[0], argv[1]);
    751 	if (res < 0 || res >= (int) sizeof(buf))
    752 		return -1;
    753 	return wpa_ctrl_command(ctrl, buf);
    754 }
    755 
    756 
    757 static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
    758 					   char *argv[])
    759 {
    760 	char buf[300];
    761 	int res;
    762 
    763 	if (argc < 3) {
    764 		printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
    765 		return -1;
    766 	}
    767 
    768 	if (argc > 3)
    769 		res = os_snprintf(buf, sizeof(buf),
    770 				  "HS20_DEAUTH_REQ %s %s %s %s",
    771 				  argv[0], argv[1], argv[2], argv[3]);
    772 	else
    773 		res = os_snprintf(buf, sizeof(buf),
    774 				  "HS20_DEAUTH_REQ %s %s %s",
    775 				  argv[0], argv[1], argv[2]);
    776 	if (res < 0 || res >= (int) sizeof(buf))
    777 		return -1;
    778 	return wpa_ctrl_command(ctrl, buf);
    779 }
    780 
    781 
    782 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
    783 {
    784 	hostapd_cli_quit = 1;
    785 	if (interactive)
    786 		eloop_terminate();
    787 	return 0;
    788 }
    789 
    790 
    791 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
    792 {
    793 	char cmd[256];
    794 	if (argc != 1) {
    795 		printf("Invalid LEVEL command: needs one argument (debug "
    796 		       "level)\n");
    797 		return 0;
    798 	}
    799 	snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
    800 	return wpa_ctrl_command(ctrl, cmd);
    801 }
    802 
    803 
    804 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
    805 {
    806 	struct dirent *dent;
    807 	DIR *dir;
    808 
    809 	dir = opendir(ctrl_iface_dir);
    810 	if (dir == NULL) {
    811 		printf("Control interface directory '%s' could not be "
    812 		       "openned.\n", ctrl_iface_dir);
    813 		return;
    814 	}
    815 
    816 	printf("Available interfaces:\n");
    817 	while ((dent = readdir(dir))) {
    818 		if (strcmp(dent->d_name, ".") == 0 ||
    819 		    strcmp(dent->d_name, "..") == 0)
    820 			continue;
    821 		printf("%s\n", dent->d_name);
    822 	}
    823 	closedir(dir);
    824 }
    825 
    826 
    827 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
    828 				     char *argv[])
    829 {
    830 	if (argc < 1) {
    831 		hostapd_cli_list_interfaces(ctrl);
    832 		return 0;
    833 	}
    834 
    835 	hostapd_cli_close_connection();
    836 	os_free(ctrl_ifname);
    837 	ctrl_ifname = os_strdup(argv[0]);
    838 	if (ctrl_ifname == NULL)
    839 		return -1;
    840 
    841 	if (hostapd_cli_open_connection(ctrl_ifname)) {
    842 		printf("Connected to interface '%s.\n", ctrl_ifname);
    843 		if (wpa_ctrl_attach(ctrl_conn) == 0) {
    844 			hostapd_cli_attached = 1;
    845 		} else {
    846 			printf("Warning: Failed to attach to "
    847 			       "hostapd.\n");
    848 		}
    849 	} else {
    850 		printf("Could not connect to interface '%s' - re-trying\n",
    851 			ctrl_ifname);
    852 	}
    853 	return 0;
    854 }
    855 
    856 
    857 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
    858 {
    859 	char cmd[256];
    860 	int res;
    861 
    862 	if (argc != 2) {
    863 		printf("Invalid SET command: needs two arguments (variable "
    864 		       "name and value)\n");
    865 		return -1;
    866 	}
    867 
    868 	res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
    869 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
    870 		printf("Too long SET command.\n");
    871 		return -1;
    872 	}
    873 	return wpa_ctrl_command(ctrl, cmd);
    874 }
    875 
    876 
    877 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
    878 {
    879 	char cmd[256];
    880 	int res;
    881 
    882 	if (argc != 1) {
    883 		printf("Invalid GET command: needs one argument (variable "
    884 		       "name)\n");
    885 		return -1;
    886 	}
    887 
    888 	res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
    889 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
    890 		printf("Too long GET command.\n");
    891 		return -1;
    892 	}
    893 	return wpa_ctrl_command(ctrl, cmd);
    894 }
    895 
    896 
    897 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
    898 				       int argc, char *argv[])
    899 {
    900 	char cmd[256];
    901 	int res;
    902 	int i;
    903 	char *tmp;
    904 	int total;
    905 
    906 	if (argc < 2) {
    907 		printf("Invalid chan_switch command: needs at least two "
    908 		       "arguments (count and freq)\n"
    909 		       "usage: <cs_count> <freq> [sec_channel_offset=] "
    910 		       "[center_freq1=] [center_freq2=] [bandwidth=] "
    911 		       "[blocktx] [ht|vht]\n");
    912 		return -1;
    913 	}
    914 
    915 	res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
    916 			  argv[0], argv[1]);
    917 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
    918 		printf("Too long CHAN_SWITCH command.\n");
    919 		return -1;
    920 	}
    921 
    922 	total = res;
    923 	for (i = 2; i < argc; i++) {
    924 		tmp = cmd + total;
    925 		res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
    926 		if (res < 0 || (size_t) res >= sizeof(cmd) - total - 1) {
    927 			printf("Too long CHAN_SWITCH command.\n");
    928 			return -1;
    929 		}
    930 		total += res;
    931 	}
    932 	return wpa_ctrl_command(ctrl, cmd);
    933 }
    934 
    935 
    936 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
    937 {
    938 	char cmd[256];
    939 	int res;
    940 
    941 	if (argc < 2 || argc > 3) {
    942 		printf("Invalid vendor command\n"
    943 		       "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
    944 		return -1;
    945 	}
    946 
    947 	res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
    948 			  argc == 3 ? argv[2] : "");
    949 	if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
    950 		printf("Too long VENDOR command.\n");
    951 		return -1;
    952 	}
    953 	return wpa_ctrl_command(ctrl, cmd);
    954 }
    955 
    956 
    957 struct hostapd_cli_cmd {
    958 	const char *cmd;
    959 	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
    960 };
    961 
    962 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
    963 	{ "ping", hostapd_cli_cmd_ping },
    964 	{ "mib", hostapd_cli_cmd_mib },
    965 	{ "relog", hostapd_cli_cmd_relog },
    966 	{ "status", hostapd_cli_cmd_status },
    967 	{ "sta", hostapd_cli_cmd_sta },
    968 	{ "all_sta", hostapd_cli_cmd_all_sta },
    969 	{ "new_sta", hostapd_cli_cmd_new_sta },
    970 	{ "deauthenticate", hostapd_cli_cmd_deauthenticate },
    971 	{ "disassociate", hostapd_cli_cmd_disassociate },
    972 #ifdef CONFIG_IEEE80211W
    973 	{ "sa_query", hostapd_cli_cmd_sa_query },
    974 #endif /* CONFIG_IEEE80211W */
    975 #ifdef CONFIG_WPS
    976 	{ "wps_pin", hostapd_cli_cmd_wps_pin },
    977 	{ "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
    978 	{ "wps_pbc", hostapd_cli_cmd_wps_pbc },
    979 	{ "wps_cancel", hostapd_cli_cmd_wps_cancel },
    980 #ifdef CONFIG_WPS_NFC
    981 	{ "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
    982 	{ "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
    983 	{ "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
    984 	{ "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
    985 #endif /* CONFIG_WPS_NFC */
    986 	{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
    987 	{ "wps_config", hostapd_cli_cmd_wps_config },
    988 	{ "wps_get_status", hostapd_cli_cmd_wps_get_status },
    989 #endif /* CONFIG_WPS */
    990 	{ "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
    991 	{ "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
    992 	{ "get_config", hostapd_cli_cmd_get_config },
    993 	{ "help", hostapd_cli_cmd_help },
    994 	{ "interface", hostapd_cli_cmd_interface },
    995 	{ "level", hostapd_cli_cmd_level },
    996 	{ "license", hostapd_cli_cmd_license },
    997 	{ "quit", hostapd_cli_cmd_quit },
    998 	{ "set", hostapd_cli_cmd_set },
    999 	{ "get", hostapd_cli_cmd_get },
   1000 	{ "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
   1001 	{ "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
   1002 	{ "chan_switch", hostapd_cli_cmd_chan_switch },
   1003 	{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
   1004 	{ "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
   1005 	{ "vendor", hostapd_cli_cmd_vendor },
   1006 	{ NULL, NULL }
   1007 };
   1008 
   1009 
   1010 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
   1011 {
   1012 	struct hostapd_cli_cmd *cmd, *match = NULL;
   1013 	int count;
   1014 
   1015 	count = 0;
   1016 	cmd = hostapd_cli_commands;
   1017 	while (cmd->cmd) {
   1018 		if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
   1019 			match = cmd;
   1020 			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
   1021 				/* we have an exact match */
   1022 				count = 1;
   1023 				break;
   1024 			}
   1025 			count++;
   1026 		}
   1027 		cmd++;
   1028 	}
   1029 
   1030 	if (count > 1) {
   1031 		printf("Ambiguous command '%s'; possible commands:", argv[0]);
   1032 		cmd = hostapd_cli_commands;
   1033 		while (cmd->cmd) {
   1034 			if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
   1035 			    0) {
   1036 				printf(" %s", cmd->cmd);
   1037 			}
   1038 			cmd++;
   1039 		}
   1040 		printf("\n");
   1041 	} else if (count == 0) {
   1042 		printf("Unknown command '%s'\n", argv[0]);
   1043 	} else {
   1044 		match->handler(ctrl, argc - 1, &argv[1]);
   1045 	}
   1046 }
   1047 
   1048 
   1049 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
   1050 				     int action_monitor)
   1051 {
   1052 	int first = 1;
   1053 	if (ctrl_conn == NULL)
   1054 		return;
   1055 	while (wpa_ctrl_pending(ctrl)) {
   1056 		char buf[256];
   1057 		size_t len = sizeof(buf) - 1;
   1058 		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
   1059 			buf[len] = '\0';
   1060 			if (action_monitor)
   1061 				hostapd_cli_action_process(buf, len);
   1062 			else {
   1063 				if (in_read && first)
   1064 					printf("\n");
   1065 				first = 0;
   1066 				printf("%s\n", buf);
   1067 			}
   1068 		} else {
   1069 			printf("Could not read pending message.\n");
   1070 			break;
   1071 		}
   1072 	}
   1073 }
   1074 
   1075 
   1076 #define max_args 10
   1077 
   1078 static int tokenize_cmd(char *cmd, char *argv[])
   1079 {
   1080 	char *pos;
   1081 	int argc = 0;
   1082 
   1083 	pos = cmd;
   1084 	for (;;) {
   1085 		while (*pos == ' ')
   1086 			pos++;
   1087 		if (*pos == '\0')
   1088 			break;
   1089 		argv[argc] = pos;
   1090 		argc++;
   1091 		if (argc == max_args)
   1092 			break;
   1093 		if (*pos == '"') {
   1094 			char *pos2 = os_strrchr(pos, '"');
   1095 			if (pos2)
   1096 				pos = pos2 + 1;
   1097 		}
   1098 		while (*pos != '\0' && *pos != ' ')
   1099 			pos++;
   1100 		if (*pos == ' ')
   1101 			*pos++ = '\0';
   1102 	}
   1103 
   1104 	return argc;
   1105 }
   1106 
   1107 
   1108 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
   1109 {
   1110 	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
   1111 		printf("Connection to hostapd lost - trying to reconnect\n");
   1112 		hostapd_cli_close_connection();
   1113 	}
   1114 	if (!ctrl_conn) {
   1115 		ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
   1116 		if (ctrl_conn) {
   1117 			printf("Connection to hostapd re-established\n");
   1118 			if (wpa_ctrl_attach(ctrl_conn) == 0) {
   1119 				hostapd_cli_attached = 1;
   1120 			} else {
   1121 				printf("Warning: Failed to attach to "
   1122 				       "hostapd.\n");
   1123 			}
   1124 		}
   1125 	}
   1126 	if (ctrl_conn)
   1127 		hostapd_cli_recv_pending(ctrl_conn, 1, 0);
   1128 	eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
   1129 }
   1130 
   1131 
   1132 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
   1133 {
   1134 	eloop_terminate();
   1135 }
   1136 
   1137 
   1138 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
   1139 {
   1140 	char *argv[max_args];
   1141 	int argc;
   1142 	argc = tokenize_cmd(cmd, argv);
   1143 	if (argc)
   1144 		wpa_request(ctrl_conn, argc, argv);
   1145 }
   1146 
   1147 
   1148 static void hostapd_cli_edit_eof_cb(void *ctx)
   1149 {
   1150 	eloop_terminate();
   1151 }
   1152 
   1153 
   1154 static void hostapd_cli_interactive(void)
   1155 {
   1156 	printf("\nInteractive mode\n\n");
   1157 
   1158 	eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
   1159 	edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
   1160 		  NULL, NULL, NULL, NULL);
   1161 	eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
   1162 
   1163 	eloop_run();
   1164 
   1165 	edit_deinit(NULL, NULL);
   1166 	eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
   1167 }
   1168 
   1169 
   1170 static void hostapd_cli_cleanup(void)
   1171 {
   1172 	hostapd_cli_close_connection();
   1173 	if (pid_file)
   1174 		os_daemonize_terminate(pid_file);
   1175 
   1176 	os_program_deinit();
   1177 }
   1178 
   1179 
   1180 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
   1181 {
   1182 	fd_set rfds;
   1183 	int fd, res;
   1184 	struct timeval tv;
   1185 	char buf[256];
   1186 	size_t len;
   1187 
   1188 	fd = wpa_ctrl_get_fd(ctrl);
   1189 
   1190 	while (!hostapd_cli_quit) {
   1191 		FD_ZERO(&rfds);
   1192 		FD_SET(fd, &rfds);
   1193 		tv.tv_sec = ping_interval;
   1194 		tv.tv_usec = 0;
   1195 		res = select(fd + 1, &rfds, NULL, NULL, &tv);
   1196 		if (res < 0 && errno != EINTR) {
   1197 			perror("select");
   1198 			break;
   1199 		}
   1200 
   1201 		if (FD_ISSET(fd, &rfds))
   1202 			hostapd_cli_recv_pending(ctrl, 0, 1);
   1203 		else {
   1204 			len = sizeof(buf) - 1;
   1205 			if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
   1206 					     hostapd_cli_action_process) < 0 ||
   1207 			    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
   1208 				printf("hostapd did not reply to PING "
   1209 				       "command - exiting\n");
   1210 				break;
   1211 			}
   1212 		}
   1213 	}
   1214 }
   1215 
   1216 
   1217 int main(int argc, char *argv[])
   1218 {
   1219 	int warning_displayed = 0;
   1220 	int c;
   1221 	int daemonize = 0;
   1222 
   1223 	if (os_program_init())
   1224 		return -1;
   1225 
   1226 	for (;;) {
   1227 		c = getopt(argc, argv, "a:BhG:i:p:v");
   1228 		if (c < 0)
   1229 			break;
   1230 		switch (c) {
   1231 		case 'a':
   1232 			action_file = optarg;
   1233 			break;
   1234 		case 'B':
   1235 			daemonize = 1;
   1236 			break;
   1237 		case 'G':
   1238 			ping_interval = atoi(optarg);
   1239 			break;
   1240 		case 'h':
   1241 			usage();
   1242 			return 0;
   1243 		case 'v':
   1244 			printf("%s\n", hostapd_cli_version);
   1245 			return 0;
   1246 		case 'i':
   1247 			os_free(ctrl_ifname);
   1248 			ctrl_ifname = os_strdup(optarg);
   1249 			break;
   1250 		case 'p':
   1251 			ctrl_iface_dir = optarg;
   1252 			break;
   1253 		default:
   1254 			usage();
   1255 			return -1;
   1256 		}
   1257 	}
   1258 
   1259 	interactive = (argc == optind) && (action_file == NULL);
   1260 
   1261 	if (interactive) {
   1262 		printf("%s\n\n%s\n\n", hostapd_cli_version,
   1263 		       hostapd_cli_license);
   1264 	}
   1265 
   1266 	if (eloop_init())
   1267 		return -1;
   1268 
   1269 	for (;;) {
   1270 		if (ctrl_ifname == NULL) {
   1271 			struct dirent *dent;
   1272 			DIR *dir = opendir(ctrl_iface_dir);
   1273 			if (dir) {
   1274 				while ((dent = readdir(dir))) {
   1275 					if (os_strcmp(dent->d_name, ".") == 0
   1276 					    ||
   1277 					    os_strcmp(dent->d_name, "..") == 0)
   1278 						continue;
   1279 					printf("Selected interface '%s'\n",
   1280 					       dent->d_name);
   1281 					ctrl_ifname = os_strdup(dent->d_name);
   1282 					break;
   1283 				}
   1284 				closedir(dir);
   1285 			}
   1286 		}
   1287 		ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
   1288 		if (ctrl_conn) {
   1289 			if (warning_displayed)
   1290 				printf("Connection established.\n");
   1291 			break;
   1292 		}
   1293 
   1294 		if (!interactive) {
   1295 			perror("Failed to connect to hostapd - "
   1296 			       "wpa_ctrl_open");
   1297 			return -1;
   1298 		}
   1299 
   1300 		if (!warning_displayed) {
   1301 			printf("Could not connect to hostapd - re-trying\n");
   1302 			warning_displayed = 1;
   1303 		}
   1304 		os_sleep(1, 0);
   1305 		continue;
   1306 	}
   1307 
   1308 	if (interactive || action_file) {
   1309 		if (wpa_ctrl_attach(ctrl_conn) == 0) {
   1310 			hostapd_cli_attached = 1;
   1311 		} else {
   1312 			printf("Warning: Failed to attach to hostapd.\n");
   1313 			if (action_file)
   1314 				return -1;
   1315 		}
   1316 	}
   1317 
   1318 	if (daemonize && os_daemonize(pid_file))
   1319 		return -1;
   1320 
   1321 	if (interactive)
   1322 		hostapd_cli_interactive();
   1323 	else if (action_file)
   1324 		hostapd_cli_action(ctrl_conn);
   1325 	else
   1326 		wpa_request(ctrl_conn, argc - optind, &argv[optind]);
   1327 
   1328 	os_free(ctrl_ifname);
   1329 	eloop_destroy();
   1330 	hostapd_cli_cleanup();
   1331 	return 0;
   1332 }
   1333