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