Home | History | Annotate | Line # | Download | only in hostapd
      1   1.1  christos /*
      2   1.1  christos  * hostapd - command line interface for hostapd daemon
      3  1.12  christos  * Copyright (c) 2004-2022, Jouni Malinen <j (at) w1.fi>
      4   1.1  christos  *
      5   1.5  christos  * This software may be distributed under the terms of the BSD license.
      6   1.5  christos  * See README for more details.
      7   1.1  christos  */
      8   1.1  christos 
      9   1.1  christos #include "includes.h"
     10   1.1  christos #include <dirent.h>
     11   1.1  christos 
     12   1.1  christos #include "common/wpa_ctrl.h"
     13   1.9  christos #include "common/ieee802_11_defs.h"
     14   1.4  christos #include "utils/common.h"
     15   1.4  christos #include "utils/eloop.h"
     16   1.4  christos #include "utils/edit.h"
     17   1.1  christos #include "common/version.h"
     18   1.9  christos #include "common/cli.h"
     19   1.1  christos 
     20   1.9  christos #ifndef CONFIG_NO_CTRL_IFACE
     21   1.1  christos 
     22   1.9  christos static const char *const hostapd_cli_version =
     23   1.1  christos "hostapd_cli v" VERSION_STR "\n"
     24  1.12  christos "Copyright (c) 2004-2024, Jouni Malinen <j (at) w1.fi> and contributors";
     25   1.1  christos 
     26   1.1  christos static struct wpa_ctrl *ctrl_conn;
     27   1.1  christos static int hostapd_cli_quit = 0;
     28   1.1  christos static int hostapd_cli_attached = 0;
     29   1.6  christos 
     30   1.6  christos #ifndef CONFIG_CTRL_IFACE_DIR
     31   1.6  christos #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
     32   1.6  christos #endif /* CONFIG_CTRL_IFACE_DIR */
     33   1.6  christos static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
     34   1.9  christos static const char *client_socket_dir = NULL;
     35   1.6  christos 
     36   1.1  christos static char *ctrl_ifname = NULL;
     37   1.1  christos static const char *pid_file = NULL;
     38   1.1  christos static const char *action_file = NULL;
     39   1.1  christos static int ping_interval = 5;
     40   1.4  christos static int interactive = 0;
     41   1.9  christos static int event_handler_registered = 0;
     42   1.9  christos 
     43   1.9  christos static DEFINE_DL_LIST(stations); /* struct cli_txt_entry */
     44   1.9  christos 
     45   1.9  christos static void print_help(FILE *stream, const char *cmd);
     46   1.9  christos static char ** list_cmd_list(void);
     47   1.9  christos static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx);
     48  1.10  christos static void update_stations(struct wpa_ctrl *ctrl);
     49  1.10  christos static void cli_event(const char *str);
     50   1.1  christos 
     51   1.1  christos 
     52   1.1  christos static void usage(void)
     53   1.1  christos {
     54   1.1  christos 	fprintf(stderr, "%s\n", hostapd_cli_version);
     55   1.1  christos 	fprintf(stderr,
     56   1.1  christos 		"\n"
     57  1.12  christos 		"usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvBr] "
     58   1.1  christos 		"[-a<path>] \\\n"
     59   1.9  christos 		"                   [-P<pid file>] [-G<ping interval>] [command..]\n"
     60   1.1  christos 		"\n"
     61   1.1  christos 		"Options:\n"
     62   1.1  christos 		"   -h           help (show this usage text)\n"
     63   1.1  christos 		"   -v           shown version information\n"
     64   1.1  christos 		"   -p<path>     path to find control sockets (default: "
     65   1.1  christos 		"/var/run/hostapd)\n"
     66   1.9  christos 		"   -s<dir_path> dir path to open client sockets (default: "
     67   1.9  christos 		CONFIG_CTRL_IFACE_DIR ")\n"
     68   1.1  christos 		"   -a<file>     run in daemon mode executing the action file "
     69   1.1  christos 		"based on events\n"
     70   1.1  christos 		"                from hostapd\n"
     71  1.12  christos 		"   -r           try to reconnect when client socket is "
     72  1.12  christos 		"disconnected.\n"
     73  1.12  christos 		"                This is useful only when used with -a.\n"
     74   1.1  christos 		"   -B           run a daemon in the background\n"
     75   1.1  christos 		"   -i<ifname>   Interface to listen on (default: first "
     76   1.1  christos 		"interface found in the\n"
     77   1.9  christos 		"                socket path)\n\n");
     78   1.9  christos 	print_help(stderr, NULL);
     79   1.9  christos }
     80   1.9  christos 
     81   1.9  christos 
     82   1.9  christos static void register_event_handler(struct wpa_ctrl *ctrl)
     83   1.9  christos {
     84   1.9  christos 	if (!ctrl_conn)
     85   1.9  christos 		return;
     86   1.9  christos 	if (interactive) {
     87   1.9  christos 		event_handler_registered =
     88   1.9  christos 			!eloop_register_read_sock(wpa_ctrl_get_fd(ctrl),
     89   1.9  christos 						  hostapd_cli_receive,
     90   1.9  christos 						  NULL, NULL);
     91   1.9  christos 	}
     92   1.9  christos }
     93   1.9  christos 
     94   1.9  christos 
     95   1.9  christos static void unregister_event_handler(struct wpa_ctrl *ctrl)
     96   1.9  christos {
     97   1.9  christos 	if (!ctrl_conn)
     98   1.9  christos 		return;
     99   1.9  christos 	if (interactive && event_handler_registered) {
    100   1.9  christos 		eloop_unregister_read_sock(wpa_ctrl_get_fd(ctrl));
    101   1.9  christos 		event_handler_registered = 0;
    102   1.9  christos 	}
    103   1.1  christos }
    104   1.1  christos 
    105   1.1  christos 
    106   1.1  christos static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
    107   1.1  christos {
    108   1.9  christos #ifndef CONFIG_CTRL_IFACE_UDP
    109   1.1  christos 	char *cfile;
    110   1.1  christos 	int flen;
    111   1.9  christos #endif /* !CONFIG_CTRL_IFACE_UDP */
    112   1.1  christos 
    113   1.1  christos 	if (ifname == NULL)
    114   1.1  christos 		return NULL;
    115   1.1  christos 
    116   1.9  christos #ifdef CONFIG_CTRL_IFACE_UDP
    117   1.9  christos 	ctrl_conn = wpa_ctrl_open(ifname);
    118   1.9  christos 	return ctrl_conn;
    119   1.9  christos #else /* CONFIG_CTRL_IFACE_UDP */
    120   1.1  christos 	flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
    121   1.1  christos 	cfile = malloc(flen);
    122   1.1  christos 	if (cfile == NULL)
    123   1.1  christos 		return NULL;
    124   1.1  christos 	snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
    125   1.1  christos 
    126   1.9  christos 	if (client_socket_dir && client_socket_dir[0] &&
    127   1.9  christos 	    access(client_socket_dir, F_OK) < 0) {
    128   1.9  christos 		perror(client_socket_dir);
    129   1.9  christos 		free(cfile);
    130   1.9  christos 		return NULL;
    131   1.9  christos 	}
    132   1.9  christos 
    133   1.9  christos 	ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir);
    134   1.1  christos 	free(cfile);
    135   1.1  christos 	return ctrl_conn;
    136   1.9  christos #endif /* CONFIG_CTRL_IFACE_UDP */
    137   1.1  christos }
    138   1.1  christos 
    139   1.1  christos 
    140   1.1  christos static void hostapd_cli_close_connection(void)
    141   1.1  christos {
    142   1.1  christos 	if (ctrl_conn == NULL)
    143   1.1  christos 		return;
    144   1.1  christos 
    145   1.9  christos 	unregister_event_handler(ctrl_conn);
    146   1.1  christos 	if (hostapd_cli_attached) {
    147   1.1  christos 		wpa_ctrl_detach(ctrl_conn);
    148   1.1  christos 		hostapd_cli_attached = 0;
    149   1.1  christos 	}
    150   1.1  christos 	wpa_ctrl_close(ctrl_conn);
    151   1.1  christos 	ctrl_conn = NULL;
    152   1.1  christos }
    153   1.1  christos 
    154   1.1  christos 
    155  1.10  christos static int hostapd_cli_reconnect(const char *ifname)
    156  1.10  christos {
    157  1.10  christos 	char *next_ctrl_ifname;
    158  1.10  christos 
    159  1.10  christos 	hostapd_cli_close_connection();
    160  1.10  christos 
    161  1.10  christos 	if (!ifname)
    162  1.10  christos 		return -1;
    163  1.10  christos 
    164  1.10  christos 	next_ctrl_ifname = os_strdup(ifname);
    165  1.10  christos 	os_free(ctrl_ifname);
    166  1.10  christos 	ctrl_ifname = next_ctrl_ifname;
    167  1.10  christos 	if (!ctrl_ifname)
    168  1.10  christos 		return -1;
    169  1.10  christos 
    170  1.10  christos 	ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
    171  1.10  christos 	if (!ctrl_conn)
    172  1.10  christos 		return -1;
    173  1.10  christos 	if (!interactive && !action_file)
    174  1.10  christos 		return 0;
    175  1.10  christos 	if (wpa_ctrl_attach(ctrl_conn) == 0) {
    176  1.10  christos 		hostapd_cli_attached = 1;
    177  1.10  christos 		register_event_handler(ctrl_conn);
    178  1.10  christos 		update_stations(ctrl_conn);
    179  1.10  christos 	} else {
    180  1.10  christos 		printf("Warning: Failed to attach to hostapd.\n");
    181  1.10  christos 	}
    182  1.10  christos 	return 0;
    183  1.10  christos }
    184  1.10  christos 
    185  1.10  christos 
    186   1.1  christos static void hostapd_cli_msg_cb(char *msg, size_t len)
    187   1.1  christos {
    188  1.10  christos 	cli_event(msg);
    189   1.1  christos 	printf("%s\n", msg);
    190   1.1  christos }
    191   1.1  christos 
    192   1.1  christos 
    193  1.10  christos static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print)
    194   1.1  christos {
    195   1.1  christos 	char buf[4096];
    196   1.1  christos 	size_t len;
    197   1.1  christos 	int ret;
    198   1.1  christos 
    199   1.1  christos 	if (ctrl_conn == NULL) {
    200   1.1  christos 		printf("Not connected to hostapd - command dropped.\n");
    201   1.1  christos 		return -1;
    202   1.1  christos 	}
    203   1.1  christos 	len = sizeof(buf) - 1;
    204   1.1  christos 	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
    205   1.1  christos 			       hostapd_cli_msg_cb);
    206   1.1  christos 	if (ret == -2) {
    207   1.1  christos 		printf("'%s' command timed out.\n", cmd);
    208   1.1  christos 		return -2;
    209   1.1  christos 	} else if (ret < 0) {
    210   1.1  christos 		printf("'%s' command failed.\n", cmd);
    211   1.1  christos 		return -1;
    212   1.1  christos 	}
    213   1.1  christos 	if (print) {
    214   1.1  christos 		buf[len] = '\0';
    215   1.1  christos 		printf("%s", buf);
    216   1.1  christos 	}
    217   1.1  christos 	return 0;
    218   1.1  christos }
    219   1.1  christos 
    220   1.1  christos 
    221  1.10  christos static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd)
    222   1.1  christos {
    223   1.1  christos 	return _wpa_ctrl_command(ctrl, cmd, 1);
    224   1.1  christos }
    225   1.1  christos 
    226   1.1  christos 
    227   1.9  christos static int hostapd_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd,
    228   1.9  christos 			   int min_args, int argc, char *argv[])
    229   1.9  christos {
    230   1.9  christos 	char buf[4096];
    231   1.9  christos 
    232   1.9  christos 	if (argc < min_args) {
    233   1.9  christos 		printf("Invalid %s command - at least %d argument%s required.\n",
    234   1.9  christos 		       cmd, min_args, min_args > 1 ? "s are" : " is");
    235   1.9  christos 		return -1;
    236   1.9  christos 	}
    237   1.9  christos 	if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0)
    238   1.9  christos 		return -1;
    239   1.9  christos 	return wpa_ctrl_command(ctrl, buf);
    240   1.9  christos }
    241   1.9  christos 
    242   1.9  christos 
    243   1.1  christos static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
    244   1.1  christos {
    245   1.1  christos 	return wpa_ctrl_command(ctrl, "PING");
    246   1.1  christos }
    247   1.1  christos 
    248   1.1  christos 
    249   1.4  christos static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
    250   1.4  christos {
    251   1.4  christos 	return wpa_ctrl_command(ctrl, "RELOG");
    252   1.4  christos }
    253   1.4  christos 
    254   1.4  christos 
    255  1.12  christos static int hostapd_cli_cmd_close_log(struct wpa_ctrl *ctrl, int argc,
    256  1.12  christos 				     char *argv[])
    257  1.12  christos {
    258  1.12  christos 	return wpa_ctrl_command(ctrl, "CLOSE_LOG");
    259  1.12  christos }
    260  1.12  christos 
    261  1.12  christos 
    262   1.6  christos static int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
    263   1.6  christos {
    264   1.6  christos 	if (argc > 0 && os_strcmp(argv[0], "driver") == 0)
    265   1.6  christos 		return wpa_ctrl_command(ctrl, "STATUS-DRIVER");
    266   1.6  christos 	return wpa_ctrl_command(ctrl, "STATUS");
    267   1.6  christos }
    268   1.6  christos 
    269   1.6  christos 
    270   1.1  christos static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
    271   1.1  christos {
    272   1.6  christos 	if (argc > 0) {
    273   1.6  christos 		char buf[100];
    274   1.6  christos 		os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]);
    275   1.6  christos 		return wpa_ctrl_command(ctrl, buf);
    276   1.6  christos 	}
    277   1.1  christos 	return wpa_ctrl_command(ctrl, "MIB");
    278   1.1  christos }
    279   1.1  christos 
    280   1.1  christos 
    281   1.1  christos static int hostapd_cli_exec(const char *program, const char *arg1,
    282   1.1  christos 			    const char *arg2)
    283   1.1  christos {
    284   1.6  christos 	char *arg;
    285   1.1  christos 	size_t len;
    286   1.1  christos 	int res;
    287   1.1  christos 
    288   1.6  christos 	len = os_strlen(arg1) + os_strlen(arg2) + 2;
    289   1.6  christos 	arg = os_malloc(len);
    290   1.6  christos 	if (arg == NULL)
    291   1.6  christos 		return -1;
    292   1.6  christos 	os_snprintf(arg, len, "%s %s", arg1, arg2);
    293   1.6  christos 	res = os_exec(program, arg, 1);
    294   1.6  christos 	os_free(arg);
    295   1.1  christos 
    296   1.6  christos 	return res;
    297   1.1  christos }
    298   1.1  christos 
    299   1.1  christos 
    300   1.1  christos static void hostapd_cli_action_process(char *msg, size_t len)
    301   1.1  christos {
    302   1.1  christos 	const char *pos;
    303   1.1  christos 
    304   1.1  christos 	pos = msg;
    305   1.1  christos 	if (*pos == '<') {
    306   1.1  christos 		pos = os_strchr(pos, '>');
    307   1.1  christos 		if (pos)
    308   1.1  christos 			pos++;
    309   1.1  christos 		else
    310   1.1  christos 			pos = msg;
    311   1.1  christos 	}
    312   1.1  christos 
    313   1.1  christos 	hostapd_cli_exec(action_file, ctrl_ifname, pos);
    314   1.1  christos }
    315   1.1  christos 
    316   1.1  christos 
    317  1.12  christos static void hostapd_cli_action_cb(char *msg, size_t len)
    318  1.12  christos {
    319  1.12  christos 	hostapd_cli_action_process(msg, len);
    320  1.12  christos }
    321  1.12  christos 
    322  1.12  christos 
    323   1.1  christos static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
    324   1.1  christos {
    325   1.1  christos 	char buf[64];
    326   1.6  christos 	if (argc < 1) {
    327   1.6  christos 		printf("Invalid 'sta' command - at least one argument, STA "
    328   1.1  christos 		       "address, is required.\n");
    329   1.1  christos 		return -1;
    330   1.1  christos 	}
    331   1.6  christos 	if (argc > 1)
    332   1.6  christos 		snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]);
    333   1.6  christos 	else
    334   1.6  christos 		snprintf(buf, sizeof(buf), "STA %s", argv[0]);
    335   1.1  christos 	return wpa_ctrl_command(ctrl, buf);
    336   1.1  christos }
    337   1.1  christos 
    338   1.1  christos 
    339  1.10  christos static char ** hostapd_complete_stations(const char *str, int pos)
    340  1.10  christos {
    341  1.10  christos 	int arg = get_cmd_arg_num(str, pos);
    342  1.10  christos 	char **res = NULL;
    343  1.10  christos 
    344  1.10  christos 	switch (arg) {
    345  1.10  christos 	case 1:
    346  1.10  christos 		res = cli_txt_list_array(&stations);
    347  1.10  christos 		break;
    348  1.10  christos 	}
    349  1.10  christos 
    350  1.10  christos 	return res;
    351  1.10  christos }
    352  1.10  christos 
    353  1.10  christos 
    354   1.1  christos static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
    355   1.1  christos 				   char *argv[])
    356   1.1  christos {
    357   1.1  christos 	char buf[64];
    358   1.1  christos 	if (argc != 1) {
    359   1.1  christos 		printf("Invalid 'new_sta' command - exactly one argument, STA "
    360   1.1  christos 		       "address, is required.\n");
    361   1.1  christos 		return -1;
    362   1.1  christos 	}
    363   1.1  christos 	snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
    364   1.1  christos 	return wpa_ctrl_command(ctrl, buf);
    365   1.1  christos }
    366   1.1  christos 
    367   1.1  christos 
    368   1.1  christos static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
    369   1.1  christos 					  char *argv[])
    370   1.1  christos {
    371   1.1  christos 	char buf[64];
    372   1.1  christos 	if (argc < 1) {
    373   1.1  christos 		printf("Invalid 'deauthenticate' command - exactly one "
    374   1.1  christos 		       "argument, STA address, is required.\n");
    375   1.1  christos 		return -1;
    376   1.1  christos 	}
    377   1.1  christos 	if (argc > 1)
    378   1.1  christos 		os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
    379   1.1  christos 			    argv[0], argv[1]);
    380   1.1  christos 	else
    381   1.1  christos 		os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
    382   1.1  christos 	return wpa_ctrl_command(ctrl, buf);
    383   1.1  christos }
    384   1.1  christos 
    385   1.1  christos 
    386   1.1  christos static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
    387   1.1  christos 					char *argv[])
    388   1.1  christos {
    389   1.1  christos 	char buf[64];
    390   1.1  christos 	if (argc < 1) {
    391   1.1  christos 		printf("Invalid 'disassociate' command - exactly one "
    392   1.1  christos 		       "argument, STA address, is required.\n");
    393   1.1  christos 		return -1;
    394   1.1  christos 	}
    395   1.1  christos 	if (argc > 1)
    396   1.1  christos 		os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
    397   1.1  christos 			    argv[0], argv[1]);
    398   1.1  christos 	else
    399   1.1  christos 		os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
    400   1.1  christos 	return wpa_ctrl_command(ctrl, buf);
    401   1.1  christos }
    402   1.1  christos 
    403   1.1  christos 
    404   1.9  christos #ifdef CONFIG_TAXONOMY
    405   1.9  christos static int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc,
    406   1.9  christos 				     char *argv[])
    407   1.9  christos {
    408   1.9  christos 	char buf[64];
    409   1.9  christos 
    410   1.9  christos 	if (argc != 1) {
    411   1.9  christos 		printf("Invalid 'signature' command - exactly one argument, STA address, is required.\n");
    412   1.9  christos 		return -1;
    413   1.9  christos 	}
    414   1.9  christos 	os_snprintf(buf, sizeof(buf), "SIGNATURE %s", argv[0]);
    415   1.9  christos 	return wpa_ctrl_command(ctrl, buf);
    416   1.9  christos }
    417   1.9  christos #endif /* CONFIG_TAXONOMY */
    418   1.9  christos 
    419   1.9  christos 
    420   1.1  christos static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
    421   1.1  christos 				    char *argv[])
    422   1.1  christos {
    423   1.1  christos 	char buf[64];
    424   1.1  christos 	if (argc != 1) {
    425   1.1  christos 		printf("Invalid 'sa_query' command - exactly one argument, "
    426   1.1  christos 		       "STA address, is required.\n");
    427   1.1  christos 		return -1;
    428   1.1  christos 	}
    429   1.1  christos 	snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
    430   1.1  christos 	return wpa_ctrl_command(ctrl, buf);
    431   1.1  christos }
    432   1.1  christos 
    433   1.1  christos 
    434   1.1  christos #ifdef CONFIG_WPS
    435   1.1  christos static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
    436   1.1  christos 				   char *argv[])
    437   1.1  christos {
    438   1.4  christos 	char buf[256];
    439   1.1  christos 	if (argc < 2) {
    440   1.1  christos 		printf("Invalid 'wps_pin' command - at least two arguments, "
    441   1.1  christos 		       "UUID and PIN, are required.\n");
    442   1.1  christos 		return -1;
    443   1.1  christos 	}
    444   1.4  christos 	if (argc > 3)
    445   1.4  christos 		snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
    446   1.4  christos 			 argv[0], argv[1], argv[2], argv[3]);
    447   1.4  christos 	else if (argc > 2)
    448   1.1  christos 		snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
    449   1.1  christos 			 argv[0], argv[1], argv[2]);
    450   1.1  christos 	else
    451   1.1  christos 		snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
    452   1.1  christos 	return wpa_ctrl_command(ctrl, buf);
    453   1.1  christos }
    454   1.1  christos 
    455   1.1  christos 
    456   1.4  christos static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
    457   1.4  christos 					 char *argv[])
    458   1.4  christos {
    459   1.4  christos 	char cmd[256];
    460   1.4  christos 	int res;
    461   1.4  christos 
    462   1.4  christos 	if (argc != 1 && argc != 2) {
    463   1.4  christos 		printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
    464   1.4  christos 		       "- PIN to be verified\n");
    465   1.4  christos 		return -1;
    466   1.4  christos 	}
    467   1.4  christos 
    468   1.4  christos 	if (argc == 2)
    469   1.4  christos 		res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
    470   1.4  christos 				  argv[0], argv[1]);
    471   1.4  christos 	else
    472   1.4  christos 		res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
    473   1.4  christos 				  argv[0]);
    474   1.7  christos 	if (os_snprintf_error(sizeof(cmd), res)) {
    475   1.4  christos 		printf("Too long WPS_CHECK_PIN command.\n");
    476   1.4  christos 		return -1;
    477   1.4  christos 	}
    478   1.4  christos 	return wpa_ctrl_command(ctrl, cmd);
    479   1.4  christos }
    480   1.4  christos 
    481   1.4  christos 
    482   1.1  christos static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
    483   1.1  christos 				   char *argv[])
    484   1.1  christos {
    485   1.1  christos 	return wpa_ctrl_command(ctrl, "WPS_PBC");
    486   1.1  christos }
    487   1.1  christos 
    488   1.1  christos 
    489   1.5  christos static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
    490   1.5  christos 				      char *argv[])
    491   1.5  christos {
    492   1.5  christos 	return wpa_ctrl_command(ctrl, "WPS_CANCEL");
    493   1.5  christos }
    494   1.5  christos 
    495   1.5  christos 
    496   1.5  christos #ifdef CONFIG_WPS_NFC
    497   1.5  christos static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
    498   1.5  christos 					    char *argv[])
    499   1.5  christos {
    500   1.5  christos 	int ret;
    501   1.5  christos 	char *buf;
    502   1.5  christos 	size_t buflen;
    503   1.5  christos 
    504   1.5  christos 	if (argc != 1) {
    505   1.5  christos 		printf("Invalid 'wps_nfc_tag_read' command - one argument "
    506   1.5  christos 		       "is required.\n");
    507   1.5  christos 		return -1;
    508   1.5  christos 	}
    509   1.5  christos 
    510   1.5  christos 	buflen = 18 + os_strlen(argv[0]);
    511   1.5  christos 	buf = os_malloc(buflen);
    512   1.5  christos 	if (buf == NULL)
    513   1.5  christos 		return -1;
    514   1.5  christos 	os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
    515   1.5  christos 
    516   1.5  christos 	ret = wpa_ctrl_command(ctrl, buf);
    517   1.5  christos 	os_free(buf);
    518   1.5  christos 
    519   1.5  christos 	return ret;
    520   1.5  christos }
    521   1.5  christos 
    522   1.5  christos 
    523   1.5  christos static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
    524   1.5  christos 						int argc, char *argv[])
    525   1.5  christos {
    526   1.5  christos 	char cmd[64];
    527   1.5  christos 	int res;
    528   1.5  christos 
    529   1.5  christos 	if (argc != 1) {
    530   1.5  christos 		printf("Invalid 'wps_nfc_config_token' command - one argument "
    531   1.5  christos 		       "is required.\n");
    532   1.5  christos 		return -1;
    533   1.5  christos 	}
    534   1.5  christos 
    535   1.5  christos 	res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
    536   1.5  christos 			  argv[0]);
    537   1.7  christos 	if (os_snprintf_error(sizeof(cmd), res)) {
    538   1.5  christos 		printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
    539   1.5  christos 		return -1;
    540   1.5  christos 	}
    541   1.5  christos 	return wpa_ctrl_command(ctrl, cmd);
    542   1.5  christos }
    543   1.5  christos 
    544   1.5  christos 
    545   1.5  christos static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
    546   1.5  christos 					 int argc, char *argv[])
    547   1.1  christos {
    548   1.5  christos 	char cmd[64];
    549   1.1  christos 	int res;
    550   1.1  christos 
    551   1.5  christos 	if (argc != 1) {
    552   1.5  christos 		printf("Invalid 'wps_nfc_token' command - one argument is "
    553   1.5  christos 		       "required.\n");
    554   1.1  christos 		return -1;
    555   1.1  christos 	}
    556   1.1  christos 
    557   1.5  christos 	res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
    558   1.7  christos 	if (os_snprintf_error(sizeof(cmd), res)) {
    559   1.5  christos 		printf("Too long WPS_NFC_TOKEN command.\n");
    560   1.1  christos 		return -1;
    561   1.1  christos 	}
    562   1.1  christos 	return wpa_ctrl_command(ctrl, cmd);
    563   1.1  christos }
    564   1.6  christos 
    565   1.6  christos 
    566   1.6  christos static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
    567   1.6  christos 						int argc, char *argv[])
    568   1.6  christos {
    569   1.6  christos 	char cmd[64];
    570   1.6  christos 	int res;
    571   1.6  christos 
    572   1.6  christos 	if (argc != 2) {
    573   1.6  christos 		printf("Invalid 'nfc_get_handover_sel' command - two arguments "
    574   1.6  christos 		       "are required.\n");
    575   1.6  christos 		return -1;
    576   1.6  christos 	}
    577   1.6  christos 
    578   1.6  christos 	res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
    579   1.6  christos 			  argv[0], argv[1]);
    580   1.7  christos 	if (os_snprintf_error(sizeof(cmd), res)) {
    581   1.6  christos 		printf("Too long NFC_GET_HANDOVER_SEL command.\n");
    582   1.6  christos 		return -1;
    583   1.6  christos 	}
    584   1.6  christos 	return wpa_ctrl_command(ctrl, cmd);
    585   1.6  christos }
    586   1.6  christos 
    587   1.5  christos #endif /* CONFIG_WPS_NFC */
    588   1.3  christos 
    589   1.3  christos 
    590   1.3  christos static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
    591   1.3  christos 				      char *argv[])
    592   1.3  christos {
    593   1.3  christos 	char buf[64];
    594   1.3  christos 	if (argc < 1) {
    595   1.3  christos 		printf("Invalid 'wps_ap_pin' command - at least one argument "
    596   1.3  christos 		       "is required.\n");
    597   1.3  christos 		return -1;
    598   1.3  christos 	}
    599   1.3  christos 	if (argc > 2)
    600   1.3  christos 		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
    601   1.3  christos 			 argv[0], argv[1], argv[2]);
    602   1.3  christos 	else if (argc > 1)
    603   1.3  christos 		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
    604   1.3  christos 			 argv[0], argv[1]);
    605   1.3  christos 	else
    606   1.3  christos 		snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
    607   1.3  christos 	return wpa_ctrl_command(ctrl, buf);
    608   1.3  christos }
    609   1.4  christos 
    610   1.4  christos 
    611   1.6  christos static int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc,
    612   1.6  christos 					  char *argv[])
    613   1.6  christos {
    614   1.6  christos 	return wpa_ctrl_command(ctrl, "WPS_GET_STATUS");
    615   1.6  christos }
    616   1.6  christos 
    617   1.6  christos 
    618   1.4  christos static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
    619   1.4  christos 				      char *argv[])
    620   1.4  christos {
    621   1.4  christos 	char buf[256];
    622   1.9  christos 	char ssid_hex[2 * SSID_MAX_LEN + 1];
    623   1.4  christos 	char key_hex[2 * 64 + 1];
    624   1.4  christos 	int i;
    625   1.4  christos 
    626   1.4  christos 	if (argc < 1) {
    627   1.4  christos 		printf("Invalid 'wps_config' command - at least two arguments "
    628   1.4  christos 		       "are required.\n");
    629   1.4  christos 		return -1;
    630   1.4  christos 	}
    631   1.4  christos 
    632   1.4  christos 	ssid_hex[0] = '\0';
    633   1.9  christos 	for (i = 0; i < SSID_MAX_LEN; i++) {
    634   1.4  christos 		if (argv[0][i] == '\0')
    635   1.4  christos 			break;
    636   1.4  christos 		os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
    637   1.4  christos 	}
    638   1.4  christos 
    639   1.4  christos 	key_hex[0] = '\0';
    640   1.4  christos 	if (argc > 3) {
    641   1.4  christos 		for (i = 0; i < 64; i++) {
    642   1.4  christos 			if (argv[3][i] == '\0')
    643   1.4  christos 				break;
    644   1.4  christos 			os_snprintf(&key_hex[i * 2], 3, "%02x",
    645   1.4  christos 				    argv[3][i]);
    646   1.4  christos 		}
    647   1.4  christos 	}
    648   1.4  christos 
    649   1.4  christos 	if (argc > 3)
    650   1.4  christos 		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
    651   1.4  christos 			 ssid_hex, argv[1], argv[2], key_hex);
    652   1.4  christos 	else if (argc > 2)
    653   1.4  christos 		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
    654   1.4  christos 			 ssid_hex, argv[1], argv[2]);
    655   1.4  christos 	else
    656   1.4  christos 		snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
    657   1.4  christos 			 ssid_hex, argv[1]);
    658   1.4  christos 	return wpa_ctrl_command(ctrl, buf);
    659   1.4  christos }
    660   1.1  christos #endif /* CONFIG_WPS */
    661   1.1  christos 
    662   1.1  christos 
    663   1.5  christos static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
    664   1.5  christos 					     char *argv[])
    665   1.5  christos {
    666   1.5  christos 	char buf[300];
    667   1.5  christos 	int res;
    668   1.5  christos 
    669   1.5  christos 	if (argc < 2) {
    670   1.5  christos 		printf("Invalid 'disassoc_imminent' command - two arguments "
    671   1.5  christos 		       "(STA addr and Disassociation Timer) are needed\n");
    672   1.5  christos 		return -1;
    673   1.5  christos 	}
    674   1.5  christos 
    675   1.5  christos 	res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
    676   1.5  christos 			  argv[0], argv[1]);
    677   1.7  christos 	if (os_snprintf_error(sizeof(buf), res))
    678   1.5  christos 		return -1;
    679   1.5  christos 	return wpa_ctrl_command(ctrl, buf);
    680   1.5  christos }
    681   1.5  christos 
    682   1.5  christos 
    683   1.4  christos static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
    684   1.4  christos 					char *argv[])
    685   1.4  christos {
    686   1.4  christos 	char buf[300];
    687   1.4  christos 	int res;
    688   1.4  christos 
    689   1.6  christos 	if (argc < 3) {
    690   1.6  christos 		printf("Invalid 'ess_disassoc' command - three arguments (STA "
    691   1.6  christos 		       "addr, disassoc timer, and URL) are needed\n");
    692   1.4  christos 		return -1;
    693   1.4  christos 	}
    694   1.4  christos 
    695   1.6  christos 	res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s",
    696   1.6  christos 			  argv[0], argv[1], argv[2]);
    697   1.7  christos 	if (os_snprintf_error(sizeof(buf), res))
    698   1.4  christos 		return -1;
    699   1.4  christos 	return wpa_ctrl_command(ctrl, buf);
    700   1.4  christos }
    701   1.4  christos 
    702   1.4  christos 
    703   1.7  christos static int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc,
    704   1.7  christos 				      char *argv[])
    705   1.7  christos {
    706   1.7  christos 	char buf[2000], *tmp;
    707   1.7  christos 	int res, i, total;
    708   1.7  christos 
    709   1.7  christos 	if (argc < 1) {
    710   1.7  christos 		printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n");
    711   1.7  christos 		return -1;
    712   1.7  christos 	}
    713   1.7  christos 
    714   1.7  christos 	res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]);
    715   1.7  christos 	if (os_snprintf_error(sizeof(buf), res))
    716   1.7  christos 		return -1;
    717   1.7  christos 
    718   1.7  christos 	total = res;
    719   1.7  christos 	for (i = 1; i < argc; i++) {
    720   1.7  christos 		tmp = &buf[total];
    721   1.7  christos 		res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]);
    722   1.7  christos 		if (os_snprintf_error(sizeof(buf) - total, res))
    723   1.7  christos 			return -1;
    724   1.7  christos 		total += res;
    725   1.7  christos 	}
    726   1.7  christos 	return wpa_ctrl_command(ctrl, buf);
    727   1.7  christos }
    728   1.7  christos 
    729   1.7  christos 
    730   1.4  christos static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
    731   1.4  christos 				      char *argv[])
    732   1.4  christos {
    733   1.4  christos 	return wpa_ctrl_command(ctrl, "GET_CONFIG");
    734   1.4  christos }
    735   1.4  christos 
    736   1.4  christos 
    737  1.10  christos static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, const char *cmd,
    738  1.10  christos 				char *addr, size_t addr_len, int print)
    739   1.1  christos {
    740   1.1  christos 	char buf[4096], *pos;
    741   1.1  christos 	size_t len;
    742   1.1  christos 	int ret;
    743   1.1  christos 
    744   1.1  christos 	if (ctrl_conn == NULL) {
    745   1.1  christos 		printf("Not connected to hostapd - command dropped.\n");
    746   1.1  christos 		return -1;
    747   1.1  christos 	}
    748   1.1  christos 	len = sizeof(buf) - 1;
    749   1.1  christos 	ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
    750   1.1  christos 			       hostapd_cli_msg_cb);
    751   1.1  christos 	if (ret == -2) {
    752   1.1  christos 		printf("'%s' command timed out.\n", cmd);
    753   1.1  christos 		return -2;
    754   1.1  christos 	} else if (ret < 0) {
    755   1.1  christos 		printf("'%s' command failed.\n", cmd);
    756   1.1  christos 		return -1;
    757   1.1  christos 	}
    758   1.1  christos 
    759   1.1  christos 	buf[len] = '\0';
    760   1.1  christos 	if (memcmp(buf, "FAIL", 4) == 0)
    761   1.1  christos 		return -1;
    762  1.10  christos 	if (print)
    763  1.10  christos 		printf("%s", buf);
    764   1.1  christos 
    765   1.1  christos 	pos = buf;
    766   1.1  christos 	while (*pos != '\0' && *pos != '\n')
    767   1.1  christos 		pos++;
    768   1.1  christos 	*pos = '\0';
    769   1.1  christos 	os_strlcpy(addr, buf, addr_len);
    770   1.1  christos 	return 0;
    771   1.1  christos }
    772   1.1  christos 
    773   1.1  christos 
    774   1.1  christos static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
    775   1.1  christos 				   char *argv[])
    776   1.1  christos {
    777   1.1  christos 	char addr[32], cmd[64];
    778   1.1  christos 
    779  1.10  christos 	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 1))
    780   1.1  christos 		return 0;
    781   1.1  christos 	do {
    782   1.1  christos 		snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
    783  1.10  christos 	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 1) == 0);
    784   1.1  christos 
    785   1.1  christos 	return -1;
    786   1.1  christos }
    787   1.1  christos 
    788   1.1  christos 
    789  1.10  christos static int hostapd_cli_cmd_list_sta(struct wpa_ctrl *ctrl, int argc,
    790  1.10  christos 				    char *argv[])
    791  1.10  christos {
    792  1.10  christos 	char addr[32], cmd[64];
    793  1.10  christos 
    794  1.10  christos 	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 0))
    795  1.10  christos 		return 0;
    796  1.10  christos 	do {
    797  1.10  christos 		if (os_strcmp(addr, "") != 0)
    798  1.10  christos 			printf("%s\n", addr);
    799  1.10  christos 		os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
    800  1.10  christos 	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 0) == 0);
    801  1.10  christos 
    802  1.10  christos 	return 0;
    803  1.10  christos }
    804  1.10  christos 
    805  1.10  christos 
    806   1.1  christos static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
    807   1.1  christos {
    808   1.9  christos 	print_help(stdout, argc > 0 ? argv[0] : NULL);
    809   1.1  christos 	return 0;
    810   1.1  christos }
    811   1.1  christos 
    812   1.1  christos 
    813   1.9  christos static char ** hostapd_cli_complete_help(const char *str, int pos)
    814   1.9  christos {
    815   1.9  christos 	int arg = get_cmd_arg_num(str, pos);
    816   1.9  christos 	char **res = NULL;
    817   1.9  christos 
    818   1.9  christos 	switch (arg) {
    819   1.9  christos 	case 1:
    820   1.9  christos 		res = list_cmd_list();
    821   1.9  christos 		break;
    822   1.9  christos 	}
    823   1.9  christos 
    824   1.9  christos 	return res;
    825   1.9  christos }
    826   1.9  christos 
    827   1.9  christos 
    828   1.1  christos static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
    829   1.1  christos 				   char *argv[])
    830   1.1  christos {
    831   1.9  christos 	printf("%s\n\n%s\n", hostapd_cli_version, cli_full_license);
    832   1.1  christos 	return 0;
    833   1.1  christos }
    834   1.1  christos 
    835   1.1  christos 
    836   1.6  christos static int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl,
    837   1.6  christos 					   int argc, char *argv[])
    838   1.6  christos {
    839   1.6  christos 	char buf[200];
    840   1.6  christos 	int res;
    841   1.6  christos 
    842   1.6  christos 	if (argc != 1) {
    843   1.6  christos 		printf("Invalid 'set_qos_map_set' command - "
    844   1.6  christos 		       "one argument (comma delimited QoS map set) "
    845   1.6  christos 		       "is needed\n");
    846   1.6  christos 		return -1;
    847   1.6  christos 	}
    848   1.6  christos 
    849   1.6  christos 	res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]);
    850   1.7  christos 	if (os_snprintf_error(sizeof(buf), res))
    851   1.6  christos 		return -1;
    852   1.6  christos 	return wpa_ctrl_command(ctrl, buf);
    853   1.6  christos }
    854   1.6  christos 
    855   1.6  christos 
    856   1.6  christos static int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl,
    857   1.6  christos 					     int argc, char *argv[])
    858   1.6  christos {
    859   1.6  christos 	char buf[50];
    860   1.6  christos 	int res;
    861   1.6  christos 
    862   1.6  christos 	if (argc != 1) {
    863   1.6  christos 		printf("Invalid 'send_qos_map_conf' command - "
    864   1.6  christos 		       "one argument (STA addr) is needed\n");
    865   1.6  christos 		return -1;
    866   1.6  christos 	}
    867   1.6  christos 
    868   1.6  christos 	res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]);
    869   1.7  christos 	if (os_snprintf_error(sizeof(buf), res))
    870   1.6  christos 		return -1;
    871   1.6  christos 	return wpa_ctrl_command(ctrl, buf);
    872   1.6  christos }
    873   1.6  christos 
    874   1.6  christos 
    875   1.6  christos static int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc,
    876   1.6  christos 					  char *argv[])
    877   1.6  christos {
    878   1.6  christos 	char buf[300];
    879   1.6  christos 	int res;
    880   1.6  christos 
    881   1.6  christos 	if (argc < 2) {
    882   1.6  christos 		printf("Invalid 'hs20_wnm_notif' command - two arguments (STA "
    883   1.6  christos 		       "addr and URL) are needed\n");
    884   1.6  christos 		return -1;
    885   1.6  christos 	}
    886   1.6  christos 
    887   1.6  christos 	res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s",
    888   1.6  christos 			  argv[0], argv[1]);
    889   1.7  christos 	if (os_snprintf_error(sizeof(buf), res))
    890   1.6  christos 		return -1;
    891   1.6  christos 	return wpa_ctrl_command(ctrl, buf);
    892   1.6  christos }
    893   1.6  christos 
    894   1.6  christos 
    895   1.6  christos static int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc,
    896   1.6  christos 					   char *argv[])
    897   1.6  christos {
    898   1.6  christos 	char buf[300];
    899   1.6  christos 	int res;
    900   1.6  christos 
    901   1.6  christos 	if (argc < 3) {
    902   1.6  christos 		printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n");
    903   1.6  christos 		return -1;
    904   1.6  christos 	}
    905   1.6  christos 
    906   1.6  christos 	if (argc > 3)
    907   1.6  christos 		res = os_snprintf(buf, sizeof(buf),
    908   1.6  christos 				  "HS20_DEAUTH_REQ %s %s %s %s",
    909   1.6  christos 				  argv[0], argv[1], argv[2], argv[3]);
    910   1.6  christos 	else
    911   1.6  christos 		res = os_snprintf(buf, sizeof(buf),
    912   1.6  christos 				  "HS20_DEAUTH_REQ %s %s %s",
    913   1.6  christos 				  argv[0], argv[1], argv[2]);
    914   1.7  christos 	if (os_snprintf_error(sizeof(buf), res))
    915   1.6  christos 		return -1;
    916   1.6  christos 	return wpa_ctrl_command(ctrl, buf);
    917   1.6  christos }
    918   1.6  christos 
    919   1.6  christos 
    920   1.1  christos static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
    921   1.1  christos {
    922   1.1  christos 	hostapd_cli_quit = 1;
    923   1.4  christos 	if (interactive)
    924   1.4  christos 		eloop_terminate();
    925   1.1  christos 	return 0;
    926   1.1  christos }
    927   1.1  christos 
    928   1.1  christos 
    929   1.1  christos static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
    930   1.1  christos {
    931   1.1  christos 	char cmd[256];
    932   1.1  christos 	if (argc != 1) {
    933   1.1  christos 		printf("Invalid LEVEL command: needs one argument (debug "
    934   1.1  christos 		       "level)\n");
    935   1.1  christos 		return 0;
    936   1.1  christos 	}
    937   1.1  christos 	snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
    938   1.1  christos 	return wpa_ctrl_command(ctrl, cmd);
    939   1.1  christos }
    940   1.1  christos 
    941   1.1  christos 
    942  1.10  christos static void update_stations(struct wpa_ctrl *ctrl)
    943  1.10  christos {
    944  1.10  christos 	char addr[32], cmd[64];
    945  1.10  christos 
    946  1.10  christos 	if (!ctrl || !interactive)
    947  1.10  christos 		return;
    948  1.10  christos 
    949  1.10  christos 	cli_txt_list_flush(&stations);
    950  1.10  christos 
    951  1.10  christos 	if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 0))
    952  1.10  christos 		return;
    953  1.10  christos 	do {
    954  1.10  christos 		if (os_strcmp(addr, "") != 0)
    955  1.10  christos 			cli_txt_list_add(&stations, addr);
    956  1.10  christos 		os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
    957  1.10  christos 	} while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 0) == 0);
    958  1.10  christos }
    959  1.10  christos 
    960  1.10  christos 
    961   1.9  christos static void hostapd_cli_get_interfaces(struct wpa_ctrl *ctrl,
    962   1.9  christos 				       struct dl_list *interfaces)
    963   1.9  christos {
    964   1.9  christos 	struct dirent *dent;
    965   1.9  christos 	DIR *dir;
    966   1.9  christos 
    967   1.9  christos 	if (!ctrl || !interfaces)
    968   1.9  christos 		return;
    969   1.9  christos 	dir = opendir(ctrl_iface_dir);
    970   1.9  christos 	if (dir == NULL)
    971   1.9  christos 		return;
    972   1.9  christos 
    973   1.9  christos 	while ((dent = readdir(dir))) {
    974   1.9  christos 		if (strcmp(dent->d_name, ".") == 0 ||
    975   1.9  christos 		    strcmp(dent->d_name, "..") == 0)
    976   1.9  christos 			continue;
    977   1.9  christos 		cli_txt_list_add(interfaces, dent->d_name);
    978   1.9  christos 	}
    979   1.9  christos 	closedir(dir);
    980   1.9  christos }
    981   1.9  christos 
    982   1.9  christos 
    983   1.1  christos static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
    984   1.1  christos {
    985   1.1  christos 	struct dirent *dent;
    986   1.1  christos 	DIR *dir;
    987   1.1  christos 
    988   1.1  christos 	dir = opendir(ctrl_iface_dir);
    989   1.1  christos 	if (dir == NULL) {
    990   1.1  christos 		printf("Control interface directory '%s' could not be "
    991  1.12  christos 		       "opened.\n", ctrl_iface_dir);
    992   1.1  christos 		return;
    993   1.1  christos 	}
    994   1.1  christos 
    995   1.1  christos 	printf("Available interfaces:\n");
    996   1.1  christos 	while ((dent = readdir(dir))) {
    997   1.1  christos 		if (strcmp(dent->d_name, ".") == 0 ||
    998   1.1  christos 		    strcmp(dent->d_name, "..") == 0)
    999   1.1  christos 			continue;
   1000   1.1  christos 		printf("%s\n", dent->d_name);
   1001   1.1  christos 	}
   1002   1.1  christos 	closedir(dir);
   1003   1.1  christos }
   1004   1.1  christos 
   1005   1.1  christos 
   1006   1.1  christos static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
   1007   1.1  christos 				     char *argv[])
   1008   1.1  christos {
   1009   1.1  christos 	if (argc < 1) {
   1010   1.1  christos 		hostapd_cli_list_interfaces(ctrl);
   1011   1.1  christos 		return 0;
   1012   1.1  christos 	}
   1013  1.10  christos 	if (hostapd_cli_reconnect(argv[0]) != 0) {
   1014   1.1  christos 		printf("Could not connect to interface '%s' - re-trying\n",
   1015   1.1  christos 			ctrl_ifname);
   1016   1.1  christos 	}
   1017   1.1  christos 	return 0;
   1018   1.1  christos }
   1019   1.1  christos 
   1020   1.1  christos 
   1021   1.9  christos static char ** hostapd_complete_interface(const char *str, int pos)
   1022   1.9  christos {
   1023   1.9  christos 	int arg = get_cmd_arg_num(str, pos);
   1024   1.9  christos 	char **res = NULL;
   1025   1.9  christos 	DEFINE_DL_LIST(interfaces);
   1026   1.9  christos 
   1027   1.9  christos 	switch (arg) {
   1028   1.9  christos 	case 1:
   1029   1.9  christos 		hostapd_cli_get_interfaces(ctrl_conn, &interfaces);
   1030   1.9  christos 		res = cli_txt_list_array(&interfaces);
   1031   1.9  christos 		cli_txt_list_flush(&interfaces);
   1032   1.9  christos 		break;
   1033   1.9  christos 	}
   1034   1.9  christos 
   1035   1.9  christos 	return res;
   1036   1.9  christos }
   1037   1.9  christos 
   1038   1.9  christos 
   1039   1.4  christos static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
   1040   1.4  christos {
   1041  1.10  christos 	char cmd[2048];
   1042   1.4  christos 	int res;
   1043   1.4  christos 
   1044   1.4  christos 	if (argc != 2) {
   1045   1.4  christos 		printf("Invalid SET command: needs two arguments (variable "
   1046   1.4  christos 		       "name and value)\n");
   1047   1.4  christos 		return -1;
   1048   1.4  christos 	}
   1049   1.4  christos 
   1050   1.4  christos 	res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
   1051   1.7  christos 	if (os_snprintf_error(sizeof(cmd), res)) {
   1052   1.4  christos 		printf("Too long SET command.\n");
   1053   1.4  christos 		return -1;
   1054   1.4  christos 	}
   1055   1.4  christos 	return wpa_ctrl_command(ctrl, cmd);
   1056   1.4  christos }
   1057   1.4  christos 
   1058   1.4  christos 
   1059  1.10  christos static char ** hostapd_complete_set(const char *str, int pos)
   1060  1.10  christos {
   1061  1.10  christos 	int arg = get_cmd_arg_num(str, pos);
   1062  1.10  christos 	const char *fields[] = {
   1063  1.10  christos #ifdef CONFIG_WPS_TESTING
   1064  1.12  christos 		"wps_version_number", "wps_testing_stub_cred",
   1065  1.10  christos 		"wps_corrupt_pkhash",
   1066  1.10  christos #endif /* CONFIG_WPS_TESTING */
   1067  1.10  christos #ifdef CONFIG_INTERWORKING
   1068  1.10  christos 		"gas_frag_limit",
   1069  1.10  christos #endif /* CONFIG_INTERWORKING */
   1070  1.10  christos #ifdef CONFIG_TESTING_OPTIONS
   1071  1.10  christos 		"ext_mgmt_frame_handling", "ext_eapol_frame_io",
   1072  1.10  christos #endif /* CONFIG_TESTING_OPTIONS */
   1073  1.10  christos #ifdef CONFIG_MBO
   1074  1.10  christos 		"mbo_assoc_disallow",
   1075  1.10  christos #endif /* CONFIG_MBO */
   1076  1.10  christos 		"deny_mac_file", "accept_mac_file",
   1077  1.10  christos 	};
   1078  1.10  christos 	int i, num_fields = ARRAY_SIZE(fields);
   1079  1.10  christos 
   1080  1.10  christos 	if (arg == 1) {
   1081  1.10  christos 		char **res;
   1082  1.10  christos 
   1083  1.10  christos 		res = os_calloc(num_fields + 1, sizeof(char *));
   1084  1.10  christos 		if (!res)
   1085  1.10  christos 			return NULL;
   1086  1.10  christos 		for (i = 0; i < num_fields; i++) {
   1087  1.10  christos 			res[i] = os_strdup(fields[i]);
   1088  1.10  christos 			if (!res[i])
   1089  1.10  christos 				return res;
   1090  1.10  christos 		}
   1091  1.10  christos 		return res;
   1092  1.10  christos 	}
   1093  1.10  christos 	return NULL;
   1094  1.10  christos }
   1095  1.10  christos 
   1096  1.10  christos 
   1097   1.4  christos static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
   1098   1.4  christos {
   1099   1.4  christos 	char cmd[256];
   1100   1.4  christos 	int res;
   1101   1.4  christos 
   1102   1.4  christos 	if (argc != 1) {
   1103   1.4  christos 		printf("Invalid GET command: needs one argument (variable "
   1104   1.4  christos 		       "name)\n");
   1105   1.4  christos 		return -1;
   1106   1.4  christos 	}
   1107   1.4  christos 
   1108   1.4  christos 	res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
   1109   1.7  christos 	if (os_snprintf_error(sizeof(cmd), res)) {
   1110   1.4  christos 		printf("Too long GET command.\n");
   1111   1.4  christos 		return -1;
   1112   1.4  christos 	}
   1113   1.4  christos 	return wpa_ctrl_command(ctrl, cmd);
   1114   1.4  christos }
   1115   1.4  christos 
   1116   1.4  christos 
   1117  1.10  christos static char ** hostapd_complete_get(const char *str, int pos)
   1118  1.10  christos {
   1119  1.10  christos 	int arg = get_cmd_arg_num(str, pos);
   1120  1.10  christos 	const char *fields[] = {
   1121  1.10  christos 		"version", "tls_library",
   1122  1.10  christos 	};
   1123  1.10  christos 	int i, num_fields = ARRAY_SIZE(fields);
   1124  1.10  christos 
   1125  1.10  christos 	if (arg == 1) {
   1126  1.10  christos 		char **res;
   1127  1.10  christos 
   1128  1.10  christos 		res = os_calloc(num_fields + 1, sizeof(char *));
   1129  1.10  christos 		if (!res)
   1130  1.10  christos 			return NULL;
   1131  1.10  christos 		for (i = 0; i < num_fields; i++) {
   1132  1.10  christos 			res[i] = os_strdup(fields[i]);
   1133  1.10  christos 			if (!res[i])
   1134  1.10  christos 				return res;
   1135  1.10  christos 		}
   1136  1.10  christos 		return res;
   1137  1.10  christos 	}
   1138  1.10  christos 	return NULL;
   1139  1.10  christos }
   1140  1.10  christos 
   1141  1.10  christos 
   1142   1.9  christos #ifdef CONFIG_FST
   1143   1.9  christos static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
   1144   1.9  christos {
   1145   1.9  christos 	char cmd[256];
   1146   1.9  christos 	int res;
   1147   1.9  christos 	int i;
   1148   1.9  christos 	int total;
   1149   1.9  christos 
   1150   1.9  christos 	if (argc <= 0) {
   1151   1.9  christos 		printf("FST command: parameters are required.\n");
   1152   1.9  christos 		return -1;
   1153   1.9  christos 	}
   1154   1.9  christos 
   1155   1.9  christos 	total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
   1156   1.9  christos 
   1157   1.9  christos 	for (i = 0; i < argc; i++) {
   1158   1.9  christos 		res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
   1159   1.9  christos 				  argv[i]);
   1160   1.9  christos 		if (os_snprintf_error(sizeof(cmd) - total, res)) {
   1161   1.9  christos 			printf("Too long fst command.\n");
   1162   1.9  christos 			return -1;
   1163   1.9  christos 		}
   1164   1.9  christos 		total += res;
   1165   1.9  christos 	}
   1166   1.9  christos 	return wpa_ctrl_command(ctrl, cmd);
   1167   1.9  christos }
   1168   1.9  christos #endif /* CONFIG_FST */
   1169   1.9  christos 
   1170   1.9  christos 
   1171  1.12  christos #ifdef CONFIG_IEEE80211AX
   1172  1.12  christos static int hostapd_cli_cmd_color_change(struct wpa_ctrl *ctrl,
   1173  1.12  christos 					int argc, char *argv[])
   1174  1.12  christos {
   1175  1.12  christos 	return hostapd_cli_cmd(ctrl, "COLOR_CHANGE", 1, argc, argv);
   1176  1.12  christos }
   1177  1.12  christos #endif /* CONFIG_IEEE80211AX */
   1178  1.12  christos 
   1179  1.12  christos 
   1180   1.6  christos static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
   1181   1.6  christos 				       int argc, char *argv[])
   1182   1.6  christos {
   1183   1.6  christos 	char cmd[256];
   1184   1.6  christos 	int res;
   1185   1.6  christos 	int i;
   1186   1.6  christos 	char *tmp;
   1187   1.6  christos 	int total;
   1188   1.6  christos 
   1189   1.6  christos 	if (argc < 2) {
   1190   1.6  christos 		printf("Invalid chan_switch command: needs at least two "
   1191   1.6  christos 		       "arguments (count and freq)\n"
   1192   1.6  christos 		       "usage: <cs_count> <freq> [sec_channel_offset=] "
   1193   1.6  christos 		       "[center_freq1=] [center_freq2=] [bandwidth=] "
   1194  1.12  christos 		       "[blocktx] [ht|vht|he|eht]\n");
   1195   1.6  christos 		return -1;
   1196   1.6  christos 	}
   1197   1.6  christos 
   1198   1.6  christos 	res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
   1199   1.6  christos 			  argv[0], argv[1]);
   1200   1.7  christos 	if (os_snprintf_error(sizeof(cmd), res)) {
   1201   1.6  christos 		printf("Too long CHAN_SWITCH command.\n");
   1202   1.6  christos 		return -1;
   1203   1.6  christos 	}
   1204   1.6  christos 
   1205   1.6  christos 	total = res;
   1206   1.6  christos 	for (i = 2; i < argc; i++) {
   1207   1.6  christos 		tmp = cmd + total;
   1208   1.6  christos 		res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
   1209   1.7  christos 		if (os_snprintf_error(sizeof(cmd) - total, res)) {
   1210   1.6  christos 			printf("Too long CHAN_SWITCH command.\n");
   1211   1.6  christos 			return -1;
   1212   1.6  christos 		}
   1213   1.6  christos 		total += res;
   1214   1.6  christos 	}
   1215   1.6  christos 	return wpa_ctrl_command(ctrl, cmd);
   1216   1.6  christos }
   1217   1.6  christos 
   1218   1.6  christos 
   1219  1.12  christos static int hostapd_cli_cmd_notify_cw_change(struct wpa_ctrl *ctrl,
   1220  1.12  christos 					    int argc, char *argv[])
   1221  1.12  christos {
   1222  1.12  christos 	return hostapd_cli_cmd(ctrl, "NOTIFY_CW_CHANGE", 1, argc, argv);
   1223  1.12  christos }
   1224  1.12  christos 
   1225  1.12  christos 
   1226   1.7  christos static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
   1227  1.12  christos 				  char *argv[])
   1228   1.7  christos {
   1229   1.7  christos 	return wpa_ctrl_command(ctrl, "ENABLE");
   1230   1.7  christos }
   1231   1.7  christos 
   1232   1.7  christos 
   1233   1.7  christos static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
   1234  1.12  christos 				  char *argv[])
   1235  1.12  christos {
   1236  1.12  christos 	return wpa_ctrl_command(ctrl, "RELOAD");
   1237  1.12  christos }
   1238  1.12  christos 
   1239  1.12  christos 
   1240  1.12  christos static int hostapd_cli_cmd_reload_bss(struct wpa_ctrl *ctrl, int argc,
   1241   1.7  christos 				      char *argv[])
   1242   1.7  christos {
   1243  1.12  christos 	return wpa_ctrl_command(ctrl, "RELOAD_BSS");
   1244  1.12  christos }
   1245  1.12  christos 
   1246  1.12  christos 
   1247  1.12  christos static int hostapd_cli_cmd_reload_config(struct wpa_ctrl *ctrl, int argc,
   1248  1.12  christos 					 char *argv[])
   1249  1.12  christos {
   1250  1.12  christos 	return wpa_ctrl_command(ctrl, "RELOAD_CONFIG");
   1251   1.7  christos }
   1252   1.7  christos 
   1253   1.7  christos 
   1254   1.7  christos static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
   1255  1.12  christos 				   char *argv[])
   1256  1.12  christos {
   1257  1.12  christos 	return wpa_ctrl_command(ctrl, "DISABLE");
   1258  1.12  christos }
   1259  1.12  christos 
   1260  1.12  christos 
   1261  1.12  christos static int hostapd_cli_cmd_enable_mld(struct wpa_ctrl *ctrl, int argc,
   1262   1.7  christos 				      char *argv[])
   1263   1.7  christos {
   1264  1.12  christos 	return wpa_ctrl_command(ctrl, "ENABLE_MLD");
   1265  1.12  christos }
   1266  1.12  christos 
   1267  1.12  christos 
   1268  1.12  christos static int hostapd_cli_cmd_disable_mld(struct wpa_ctrl *ctrl, int argc,
   1269  1.12  christos 				       char *argv[])
   1270  1.12  christos {
   1271  1.12  christos 	return wpa_ctrl_command(ctrl, "DISABLE_MLD");
   1272   1.7  christos }
   1273   1.7  christos 
   1274   1.7  christos 
   1275  1.11  christos static int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc,
   1276  1.12  christos 					 char *argv[])
   1277  1.11  christos {
   1278  1.11  christos 	return wpa_ctrl_command(ctrl, "UPDATE_BEACON");
   1279  1.11  christos }
   1280  1.11  christos 
   1281  1.11  christos 
   1282  1.12  christos static int hostapd_cli_cmd_stop_ap(struct wpa_ctrl *ctrl, int argc,
   1283  1.12  christos 				   char *argv[])
   1284  1.12  christos {
   1285  1.12  christos 	return wpa_ctrl_command(ctrl, "STOP_AP");
   1286  1.12  christos }
   1287  1.12  christos 
   1288  1.12  christos 
   1289   1.6  christos static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
   1290   1.6  christos {
   1291   1.6  christos 	char cmd[256];
   1292   1.6  christos 	int res;
   1293   1.6  christos 
   1294  1.12  christos 	if (argc < 2 || argc > 4) {
   1295   1.6  christos 		printf("Invalid vendor command\n"
   1296  1.12  christos 		       "usage: <vendor id> <command id> [<hex formatted command argument>] [nested=<0|1>]\n");
   1297   1.6  christos 		return -1;
   1298   1.6  christos 	}
   1299   1.6  christos 
   1300  1.12  christos 	res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s%s%s", argv[0],
   1301  1.12  christos 			  argv[1], argc >= 3 ? argv[2] : "",
   1302  1.12  christos 			  argc == 4 ? " " : "", argc == 4 ? argv[3] : "");
   1303   1.7  christos 	if (os_snprintf_error(sizeof(cmd), res)) {
   1304   1.6  christos 		printf("Too long VENDOR command.\n");
   1305   1.6  christos 		return -1;
   1306   1.6  christos 	}
   1307   1.6  christos 	return wpa_ctrl_command(ctrl, cmd);
   1308   1.6  christos }
   1309   1.6  christos 
   1310   1.6  christos 
   1311   1.7  christos static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
   1312   1.7  christos 				     char *argv[])
   1313   1.7  christos {
   1314   1.7  christos 	return wpa_ctrl_command(ctrl, "ERP_FLUSH");
   1315   1.7  christos }
   1316   1.7  christos 
   1317   1.7  christos 
   1318   1.9  christos static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
   1319   1.9  christos 				     char *argv[])
   1320   1.9  christos {
   1321   1.9  christos 	char cmd[256];
   1322   1.9  christos 	int res;
   1323   1.9  christos 
   1324   1.9  christos 	res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
   1325   1.9  christos 			  argc >= 1 ? " " : "",
   1326   1.9  christos 			  argc >= 1 ? argv[0] : "",
   1327   1.9  christos 			  argc == 2 ? " " : "",
   1328   1.9  christos 			  argc == 2 ? argv[1] : "");
   1329   1.9  christos 	if (os_snprintf_error(sizeof(cmd), res)) {
   1330   1.9  christos 		printf("Too long option\n");
   1331   1.9  christos 		return -1;
   1332   1.9  christos 	}
   1333   1.9  christos 	return wpa_ctrl_command(ctrl, cmd);
   1334   1.9  christos }
   1335   1.9  christos 
   1336   1.9  christos 
   1337   1.9  christos static int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
   1338   1.9  christos {
   1339   1.9  christos 	if (argc == 0)
   1340   1.9  christos 		return -1;
   1341   1.9  christos 	return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
   1342   1.9  christos }
   1343   1.9  christos 
   1344   1.9  christos 
   1345   1.9  christos static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
   1346   1.9  christos {
   1347   1.9  christos 	return wpa_ctrl_command(ctrl, "PMKSA");
   1348   1.9  christos }
   1349   1.9  christos 
   1350   1.9  christos 
   1351   1.9  christos static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
   1352   1.9  christos 				       char *argv[])
   1353   1.9  christos {
   1354   1.9  christos 	return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
   1355   1.9  christos }
   1356   1.9  christos 
   1357   1.9  christos 
   1358   1.9  christos static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
   1359   1.9  christos 					char *argv[])
   1360   1.9  christos {
   1361   1.9  christos 	char cmd[2048];
   1362   1.9  christos 	int res;
   1363   1.9  christos 
   1364  1.10  christos 	if (argc < 3 || argc > 6) {
   1365  1.10  christos 		printf("Invalid set_neighbor command: needs 3-6 arguments\n");
   1366   1.9  christos 		return -1;
   1367   1.9  christos 	}
   1368   1.9  christos 
   1369  1.10  christos 	res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s %s",
   1370   1.9  christos 			  argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "",
   1371  1.10  christos 			  argc >= 5 ? argv[4] : "", argc == 6 ? argv[5] : "");
   1372   1.9  christos 	if (os_snprintf_error(sizeof(cmd), res)) {
   1373   1.9  christos 		printf("Too long SET_NEIGHBOR command.\n");
   1374   1.9  christos 		return -1;
   1375   1.9  christos 	}
   1376   1.9  christos 	return wpa_ctrl_command(ctrl, cmd);
   1377   1.9  christos }
   1378   1.9  christos 
   1379   1.9  christos 
   1380  1.12  christos static int hostapd_cli_cmd_show_neighbor(struct wpa_ctrl *ctrl, int argc,
   1381  1.12  christos 					 char *argv[])
   1382  1.12  christos {
   1383  1.12  christos 	return wpa_ctrl_command(ctrl, "SHOW_NEIGHBOR");
   1384  1.12  christos }
   1385  1.12  christos 
   1386  1.12  christos 
   1387   1.9  christos static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
   1388   1.9  christos 					   char *argv[])
   1389   1.9  christos {
   1390  1.12  christos 	return hostapd_cli_cmd(ctrl, "REMOVE_NEIGHBOR", 1, argc, argv);
   1391   1.9  christos }
   1392   1.9  christos 
   1393   1.9  christos 
   1394   1.9  christos static int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc,
   1395   1.9  christos 				   char *argv[])
   1396   1.9  christos {
   1397   1.9  christos 	char cmd[256];
   1398   1.9  christos 	int res;
   1399   1.9  christos 
   1400   1.9  christos 	if (argc != 1) {
   1401   1.9  christos 		printf("Invalid req_lci command - requires destination address\n");
   1402   1.9  christos 		return -1;
   1403   1.9  christos 	}
   1404   1.9  christos 
   1405   1.9  christos 	res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]);
   1406   1.9  christos 	if (os_snprintf_error(sizeof(cmd), res)) {
   1407   1.9  christos 		printf("Too long REQ_LCI command.\n");
   1408   1.9  christos 		return -1;
   1409   1.9  christos 	}
   1410   1.9  christos 	return wpa_ctrl_command(ctrl, cmd);
   1411   1.9  christos }
   1412   1.9  christos 
   1413   1.9  christos 
   1414   1.9  christos static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc,
   1415   1.9  christos 				     char *argv[])
   1416   1.9  christos {
   1417   1.9  christos 	if (argc < 4) {
   1418   1.9  christos 		printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n");
   1419   1.9  christos 		return -1;
   1420   1.9  christos 	}
   1421   1.9  christos 
   1422   1.9  christos 	return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv);
   1423   1.9  christos }
   1424   1.9  christos 
   1425   1.9  christos 
   1426   1.9  christos static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
   1427   1.9  christos 					char *argv[])
   1428   1.9  christos {
   1429   1.9  christos 	return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
   1430   1.9  christos }
   1431   1.9  christos 
   1432   1.9  christos 
   1433  1.12  christos static int hostapd_cli_cmd_driver_flags2(struct wpa_ctrl *ctrl, int argc,
   1434  1.12  christos 					 char *argv[])
   1435  1.12  christos {
   1436  1.12  christos 	return wpa_ctrl_command(ctrl, "DRIVER_FLAGS2");
   1437  1.12  christos }
   1438  1.12  christos 
   1439  1.12  christos 
   1440  1.10  christos #ifdef CONFIG_DPP
   1441  1.10  christos 
   1442  1.10  christos static int hostapd_cli_cmd_dpp_qr_code(struct wpa_ctrl *ctrl, int argc,
   1443  1.10  christos 				       char *argv[])
   1444  1.10  christos {
   1445  1.10  christos 	return hostapd_cli_cmd(ctrl, "DPP_QR_CODE", 1, argc, argv);
   1446  1.10  christos }
   1447  1.10  christos 
   1448  1.10  christos 
   1449  1.10  christos static int hostapd_cli_cmd_dpp_bootstrap_gen(struct wpa_ctrl *ctrl, int argc,
   1450  1.10  christos 					     char *argv[])
   1451  1.10  christos {
   1452  1.10  christos 	return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_GEN", 1, argc, argv);
   1453  1.10  christos }
   1454  1.10  christos 
   1455  1.10  christos 
   1456  1.10  christos static int hostapd_cli_cmd_dpp_bootstrap_remove(struct wpa_ctrl *ctrl, int argc,
   1457  1.10  christos 						char *argv[])
   1458  1.10  christos {
   1459  1.10  christos 	return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_REMOVE", 1, argc, argv);
   1460  1.10  christos }
   1461  1.10  christos 
   1462  1.10  christos 
   1463  1.10  christos static int hostapd_cli_cmd_dpp_bootstrap_get_uri(struct wpa_ctrl *ctrl,
   1464  1.10  christos 						 int argc, char *argv[])
   1465  1.10  christos {
   1466  1.10  christos 	return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_GET_URI", 1, argc, argv);
   1467  1.10  christos }
   1468  1.10  christos 
   1469  1.10  christos 
   1470  1.10  christos static int hostapd_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc,
   1471  1.10  christos 					      char *argv[])
   1472  1.10  christos {
   1473  1.10  christos 	return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_INFO", 1, argc, argv);
   1474  1.10  christos }
   1475  1.10  christos 
   1476  1.10  christos 
   1477  1.12  christos static int hostapd_cli_cmd_dpp_bootstrap_set(struct wpa_ctrl *ctrl, int argc,
   1478  1.12  christos 					     char *argv[])
   1479  1.12  christos {
   1480  1.12  christos 	return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_SET", 1, argc, argv);
   1481  1.12  christos }
   1482  1.12  christos 
   1483  1.12  christos 
   1484  1.10  christos static int hostapd_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc,
   1485  1.10  christos 					 char *argv[])
   1486  1.10  christos {
   1487  1.10  christos 	return hostapd_cli_cmd(ctrl, "DPP_AUTH_INIT", 1, argc, argv);
   1488  1.10  christos }
   1489  1.10  christos 
   1490  1.10  christos 
   1491  1.10  christos static int hostapd_cli_cmd_dpp_listen(struct wpa_ctrl *ctrl, int argc,
   1492  1.10  christos 				      char *argv[])
   1493  1.10  christos {
   1494  1.10  christos 	return hostapd_cli_cmd(ctrl, "DPP_LISTEN", 1, argc, argv);
   1495  1.10  christos }
   1496  1.10  christos 
   1497  1.10  christos 
   1498  1.10  christos static int hostapd_cli_cmd_dpp_stop_listen(struct wpa_ctrl *ctrl, int argc,
   1499  1.10  christos 				       char *argv[])
   1500  1.10  christos {
   1501  1.10  christos 	return wpa_ctrl_command(ctrl, "DPP_STOP_LISTEN");
   1502  1.10  christos }
   1503  1.10  christos 
   1504  1.10  christos 
   1505  1.10  christos static int hostapd_cli_cmd_dpp_configurator_add(struct wpa_ctrl *ctrl, int argc,
   1506  1.10  christos 						char *argv[])
   1507  1.10  christos {
   1508  1.10  christos 	return hostapd_cli_cmd(ctrl, "DPP_CONFIGURATOR_ADD", 0, argc, argv);
   1509  1.10  christos }
   1510  1.10  christos 
   1511  1.10  christos 
   1512  1.10  christos static int hostapd_cli_cmd_dpp_configurator_remove(struct wpa_ctrl *ctrl,
   1513  1.10  christos 						   int argc, char *argv[])
   1514  1.10  christos {
   1515  1.10  christos 	return hostapd_cli_cmd(ctrl, "DPP_CONFIGURATOR_REMOVE", 1, argc, argv);
   1516  1.10  christos }
   1517  1.10  christos 
   1518  1.10  christos 
   1519  1.10  christos static int hostapd_cli_cmd_dpp_configurator_get_key(struct wpa_ctrl *ctrl,
   1520  1.10  christos 						    int argc, char *argv[])
   1521  1.10  christos {
   1522  1.10  christos 	return hostapd_cli_cmd(ctrl, "DPP_CONFIGURATOR_GET_KEY", 1, argc, argv);
   1523  1.10  christos }
   1524  1.10  christos 
   1525  1.10  christos 
   1526  1.11  christos static int hostapd_cli_cmd_dpp_configurator_sign(struct wpa_ctrl *ctrl,
   1527  1.11  christos 						 int argc, char *argv[])
   1528  1.11  christos {
   1529  1.11  christos        return hostapd_cli_cmd(ctrl, "DPP_CONFIGURATOR_SIGN", 1, argc, argv);
   1530  1.11  christos }
   1531  1.11  christos 
   1532  1.11  christos 
   1533  1.10  christos static int hostapd_cli_cmd_dpp_pkex_add(struct wpa_ctrl *ctrl, int argc,
   1534  1.10  christos 					char *argv[])
   1535  1.10  christos {
   1536  1.10  christos 	return hostapd_cli_cmd(ctrl, "DPP_PKEX_ADD", 1, argc, argv);
   1537  1.10  christos }
   1538  1.10  christos 
   1539  1.10  christos 
   1540  1.10  christos static int hostapd_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc,
   1541  1.10  christos 					   char *argv[])
   1542  1.10  christos {
   1543  1.10  christos 	return hostapd_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv);
   1544  1.10  christos }
   1545  1.10  christos 
   1546  1.12  christos 
   1547  1.12  christos #ifdef CONFIG_DPP2
   1548  1.12  christos 
   1549  1.12  christos static int hostapd_cli_cmd_dpp_controller_start(struct wpa_ctrl *ctrl, int argc,
   1550  1.12  christos 						char *argv[])
   1551  1.12  christos {
   1552  1.12  christos 	return hostapd_cli_cmd(ctrl, "DPP_CONTROLLER_START", 0, argc, argv);
   1553  1.12  christos }
   1554  1.12  christos 
   1555  1.12  christos 
   1556  1.12  christos static int hostapd_cli_cmd_dpp_controller_stop(struct wpa_ctrl *ctrl, int argc,
   1557  1.12  christos 					       char *argv[])
   1558  1.12  christos {
   1559  1.12  christos 	return wpa_ctrl_command(ctrl, "DPP_CONTROLLER_STOP");
   1560  1.12  christos }
   1561  1.12  christos 
   1562  1.12  christos 
   1563  1.12  christos static int hostapd_cli_cmd_dpp_chirp(struct wpa_ctrl *ctrl, int argc,
   1564  1.12  christos 				     char *argv[])
   1565  1.12  christos {
   1566  1.12  christos 	return hostapd_cli_cmd(ctrl, "DPP_CHIRP", 1, argc, argv);
   1567  1.12  christos }
   1568  1.12  christos 
   1569  1.12  christos 
   1570  1.12  christos static int hostapd_cli_cmd_dpp_stop_chirp(struct wpa_ctrl *ctrl, int argc,
   1571  1.12  christos 					  char *argv[])
   1572  1.12  christos {
   1573  1.12  christos 	return wpa_ctrl_command(ctrl, "DPP_STOP_CHIRP");
   1574  1.12  christos }
   1575  1.12  christos 
   1576  1.12  christos #endif /* CONFIG_DPP2 */
   1577  1.12  christos 
   1578  1.12  christos 
   1579  1.12  christos #ifdef CONFIG_DPP3
   1580  1.12  christos static int hostapd_cli_cmd_dpp_push_button(struct wpa_ctrl *ctrl, int argc,
   1581  1.12  christos 					   char *argv[])
   1582  1.12  christos {
   1583  1.12  christos 	return hostapd_cli_cmd(ctrl, "DPP_PUSH_BUTTON", 0, argc, argv);
   1584  1.12  christos }
   1585  1.12  christos #endif /* CONFIG_DPP3 */
   1586  1.10  christos #endif /* CONFIG_DPP */
   1587  1.10  christos 
   1588  1.10  christos 
   1589  1.10  christos static int hostapd_cli_cmd_accept_macacl(struct wpa_ctrl *ctrl, int argc,
   1590  1.10  christos 					 char *argv[])
   1591  1.10  christos {
   1592  1.10  christos 	return hostapd_cli_cmd(ctrl, "ACCEPT_ACL", 1, argc, argv);
   1593  1.10  christos }
   1594  1.10  christos 
   1595  1.10  christos 
   1596  1.10  christos static int hostapd_cli_cmd_deny_macacl(struct wpa_ctrl *ctrl, int argc,
   1597  1.10  christos 				       char *argv[])
   1598  1.10  christos {
   1599  1.10  christos 	return hostapd_cli_cmd(ctrl, "DENY_ACL", 1, argc, argv);
   1600  1.10  christos }
   1601  1.10  christos 
   1602  1.10  christos 
   1603  1.10  christos static int hostapd_cli_cmd_poll_sta(struct wpa_ctrl *ctrl, int argc,
   1604  1.10  christos 				    char *argv[])
   1605  1.10  christos {
   1606  1.10  christos 	return hostapd_cli_cmd(ctrl, "POLL_STA", 1, argc, argv);
   1607  1.10  christos }
   1608  1.10  christos 
   1609  1.10  christos 
   1610  1.11  christos static int hostapd_cli_cmd_req_beacon(struct wpa_ctrl *ctrl, int argc,
   1611  1.11  christos 				      char *argv[])
   1612  1.11  christos {
   1613  1.11  christos 	return hostapd_cli_cmd(ctrl, "REQ_BEACON", 2, argc, argv);
   1614  1.11  christos }
   1615  1.11  christos 
   1616  1.11  christos 
   1617  1.12  christos static int hostapd_cli_cmd_req_link_measurement(struct wpa_ctrl *ctrl, int argc,
   1618  1.12  christos 						char *argv[])
   1619  1.12  christos {
   1620  1.12  christos 	return hostapd_cli_cmd(ctrl, "REQ_LINK_MEASUREMENT", 1, argc, argv);
   1621  1.12  christos }
   1622  1.12  christos 
   1623  1.12  christos 
   1624  1.11  christos static int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc,
   1625  1.11  christos 					  char *argv[])
   1626  1.11  christos {
   1627  1.11  christos 	return wpa_ctrl_command(ctrl, "RELOAD_WPA_PSK");
   1628  1.11  christos }
   1629  1.11  christos 
   1630  1.11  christos 
   1631  1.12  christos #ifdef CONFIG_IEEE80211R_AP
   1632  1.12  christos 
   1633  1.12  christos static int hostapd_cli_cmd_get_rxkhs(struct wpa_ctrl *ctrl, int argc,
   1634  1.12  christos 				     char *argv[])
   1635  1.12  christos {
   1636  1.12  christos 	return wpa_ctrl_command(ctrl, "GET_RXKHS");
   1637  1.12  christos }
   1638  1.12  christos 
   1639  1.12  christos 
   1640  1.12  christos static int hostapd_cli_cmd_reload_rxkhs(struct wpa_ctrl *ctrl, int argc,
   1641  1.12  christos 					char *argv[])
   1642  1.12  christos {
   1643  1.12  christos 	return wpa_ctrl_command(ctrl, "RELOAD_RXKHS");
   1644  1.12  christos }
   1645  1.12  christos 
   1646  1.12  christos #endif /* CONFIG_IEEE80211R_AP */
   1647  1.12  christos 
   1648  1.12  christos 
   1649  1.12  christos #ifdef ANDROID
   1650  1.12  christos static int hostapd_cli_cmd_driver(struct wpa_ctrl *ctrl, int argc, char *argv[])
   1651  1.12  christos {
   1652  1.12  christos 	return hostapd_cli_cmd(ctrl, "DRIVER", 1, argc, argv);
   1653  1.12  christos }
   1654  1.12  christos #endif /* ANDROID */
   1655  1.12  christos 
   1656  1.12  christos 
   1657   1.1  christos struct hostapd_cli_cmd {
   1658   1.1  christos 	const char *cmd;
   1659   1.1  christos 	int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
   1660   1.9  christos 	char ** (*completion)(const char *str, int pos);
   1661   1.9  christos 	const char *usage;
   1662   1.1  christos };
   1663   1.1  christos 
   1664   1.9  christos static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
   1665   1.9  christos 	{ "ping", hostapd_cli_cmd_ping, NULL,
   1666   1.9  christos 	  "= pings hostapd" },
   1667   1.9  christos 	{ "mib", hostapd_cli_cmd_mib, NULL,
   1668   1.9  christos 	  "= get MIB variables (dot1x, dot11, radius)" },
   1669  1.10  christos 	{ "relog", hostapd_cli_cmd_relog, NULL,
   1670  1.10  christos 	  "= reload/truncate debug log output file" },
   1671  1.12  christos 	{ "close_log", hostapd_cli_cmd_close_log, NULL,
   1672  1.12  christos 	  "= disable debug log output file" },
   1673  1.10  christos 	{ "status", hostapd_cli_cmd_status, NULL,
   1674  1.10  christos 	  "= show interface status info" },
   1675  1.10  christos 	{ "sta", hostapd_cli_cmd_sta, hostapd_complete_stations,
   1676   1.9  christos 	  "<addr> = get MIB variables for one station" },
   1677   1.9  christos 	{ "all_sta", hostapd_cli_cmd_all_sta, NULL,
   1678   1.9  christos 	   "= get MIB variables for all stations" },
   1679  1.10  christos 	{ "list_sta", hostapd_cli_cmd_list_sta, NULL,
   1680  1.10  christos 	   "= list all stations" },
   1681   1.9  christos 	{ "new_sta", hostapd_cli_cmd_new_sta, NULL,
   1682   1.9  christos 	  "<addr> = add a new station" },
   1683   1.9  christos 	{ "deauthenticate", hostapd_cli_cmd_deauthenticate,
   1684  1.10  christos 	  hostapd_complete_stations,
   1685   1.9  christos 	  "<addr> = deauthenticate a station" },
   1686   1.9  christos 	{ "disassociate", hostapd_cli_cmd_disassociate,
   1687  1.10  christos 	  hostapd_complete_stations,
   1688   1.9  christos 	  "<addr> = disassociate a station" },
   1689   1.9  christos #ifdef CONFIG_TAXONOMY
   1690  1.10  christos 	{ "signature", hostapd_cli_cmd_signature, hostapd_complete_stations,
   1691   1.9  christos 	  "<addr> = get taxonomy signature for a station" },
   1692   1.9  christos #endif /* CONFIG_TAXONOMY */
   1693  1.10  christos 	{ "sa_query", hostapd_cli_cmd_sa_query, hostapd_complete_stations,
   1694   1.9  christos 	  "<addr> = send SA Query to a station" },
   1695   1.1  christos #ifdef CONFIG_WPS
   1696   1.9  christos 	{ "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
   1697   1.9  christos 	  "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
   1698   1.9  christos 	{ "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
   1699   1.9  christos 	  "<PIN> = verify PIN checksum" },
   1700   1.9  christos 	{ "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL,
   1701   1.9  christos 	  "= indicate button pushed to initiate PBC" },
   1702   1.9  christos 	{ "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL,
   1703   1.9  christos 	  "= cancel the pending WPS operation" },
   1704   1.5  christos #ifdef CONFIG_WPS_NFC
   1705   1.9  christos 	{ "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL,
   1706   1.9  christos 	  "<hexdump> = report read NFC tag with WPS data" },
   1707   1.9  christos 	{ "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL,
   1708   1.9  christos 	  "<WPS/NDEF> = build NFC configuration token" },
   1709   1.9  christos 	{ "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL,
   1710   1.9  christos 	  "<WPS/NDEF/enable/disable> = manager NFC password token" },
   1711   1.9  christos 	{ "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL,
   1712   1.9  christos 	  NULL },
   1713   1.5  christos #endif /* CONFIG_WPS_NFC */
   1714   1.9  christos 	{ "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL,
   1715   1.9  christos 	  "<cmd> [params..] = enable/disable AP PIN" },
   1716   1.9  christos 	{ "wps_config", hostapd_cli_cmd_wps_config, NULL,
   1717   1.9  christos 	  "<SSID> <auth> <encr> <key> = configure AP" },
   1718   1.9  christos 	{ "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
   1719   1.9  christos 	  "= show current WPS status" },
   1720   1.1  christos #endif /* CONFIG_WPS */
   1721  1.10  christos 	{ "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL,
   1722  1.10  christos 	  "= send Disassociation Imminent notification" },
   1723  1.10  christos 	{ "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL,
   1724  1.10  christos 	  "= send ESS Dissassociation Imminent notification" },
   1725  1.10  christos 	{ "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL,
   1726  1.10  christos 	  "= send BSS Transition Management Request" },
   1727   1.9  christos 	{ "get_config", hostapd_cli_cmd_get_config, NULL,
   1728   1.9  christos 	  "= show current configuration" },
   1729   1.9  christos 	{ "help", hostapd_cli_cmd_help, hostapd_cli_complete_help,
   1730   1.9  christos 	  "= show this usage help" },
   1731   1.9  christos 	{ "interface", hostapd_cli_cmd_interface, hostapd_complete_interface,
   1732   1.9  christos 	  "[ifname] = show interfaces/select interface" },
   1733   1.9  christos #ifdef CONFIG_FST
   1734  1.10  christos 	{ "fst", hostapd_cli_cmd_fst, NULL,
   1735  1.10  christos 	  "<params...> = send FST-MANAGER control interface command" },
   1736   1.9  christos #endif /* CONFIG_FST */
   1737  1.10  christos 	{ "raw", hostapd_cli_cmd_raw, NULL,
   1738  1.10  christos 	  "<params..> = send unprocessed command" },
   1739   1.9  christos 	{ "level", hostapd_cli_cmd_level, NULL,
   1740   1.9  christos 	  "<debug level> = change debug level" },
   1741   1.9  christos 	{ "license", hostapd_cli_cmd_license, NULL,
   1742   1.9  christos 	  "= show full hostapd_cli license" },
   1743   1.9  christos 	{ "quit", hostapd_cli_cmd_quit, NULL,
   1744   1.9  christos 	  "= exit hostapd_cli" },
   1745  1.10  christos 	{ "set", hostapd_cli_cmd_set, hostapd_complete_set,
   1746  1.10  christos 	  "<name> <value> = set runtime variables" },
   1747  1.10  christos 	{ "get", hostapd_cli_cmd_get, hostapd_complete_get,
   1748  1.10  christos 	  "<name> = get runtime info" },
   1749  1.10  christos 	{ "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL,
   1750  1.10  christos 	  "<arg,arg,...> = set QoS Map set element" },
   1751  1.10  christos 	{ "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf,
   1752  1.10  christos 	  hostapd_complete_stations,
   1753  1.10  christos 	  "<addr> = send QoS Map Configure frame" },
   1754  1.10  christos 	{ "chan_switch", hostapd_cli_cmd_chan_switch, NULL,
   1755  1.10  christos 	  "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]\n"
   1756  1.10  christos 	  "  [center_freq2=] [bandwidth=] [blocktx] [ht|vht]\n"
   1757  1.10  christos 	  "  = initiate channel switch announcement" },
   1758  1.12  christos #ifdef CONFIG_IEEE80211AX
   1759  1.12  christos 	{ "color_change", hostapd_cli_cmd_color_change, NULL,
   1760  1.12  christos 	  "<color> = initiate BSS color change to set the specified color\n"
   1761  1.12  christos 	  "Value 0 will disable the color.\n"},
   1762  1.12  christos #endif /* CONFIG_IEEE80211AX */
   1763  1.12  christos 	{ "notify_cw_change", hostapd_cli_cmd_notify_cw_change, NULL,
   1764  1.12  christos 	  "<channel_width> = 0 - 20 MHz, 1 - 40 MHz, 2 - 80 MHz, 3 - 160 MHz" },
   1765  1.10  christos 	{ "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL,
   1766  1.10  christos 	  "<addr> <url>\n"
   1767  1.10  christos 	  "  = send WNM-Notification Subscription Remediation Request" },
   1768  1.10  christos 	{ "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL,
   1769  1.10  christos 	  "<addr> <code (0/1)> <Re-auth-Delay(sec)> [url]\n"
   1770  1.10  christos 	  "  = send WNM-Notification imminent deauthentication indication" },
   1771  1.10  christos 	{ "vendor", hostapd_cli_cmd_vendor, NULL,
   1772  1.10  christos 	  "<vendor id> <sub command id> [<hex formatted data>]\n"
   1773  1.10  christos 	  "  = send vendor driver command" },
   1774  1.10  christos 	{ "enable", hostapd_cli_cmd_enable, NULL,
   1775  1.10  christos 	  "= enable hostapd on current interface" },
   1776  1.10  christos 	{ "reload", hostapd_cli_cmd_reload, NULL,
   1777  1.10  christos 	  "= reload configuration for current interface" },
   1778  1.12  christos 	{ "reload_bss", hostapd_cli_cmd_reload_bss, NULL,
   1779  1.12  christos 	  "= reload configuration for current BSS" },
   1780  1.12  christos 	{ "reload_config", hostapd_cli_cmd_reload_config, NULL,
   1781  1.12  christos 	  "= reload configuration for current interface" },
   1782  1.10  christos 	{ "disable", hostapd_cli_cmd_disable, NULL,
   1783  1.10  christos 	  "= disable hostapd on current interface" },
   1784  1.12  christos 	{ "enable_mld", hostapd_cli_cmd_enable_mld, NULL,
   1785  1.12  christos 	  "= enable AP MLD to which the interface is affiliated" },
   1786  1.12  christos 	{ "disable_mld", hostapd_cli_cmd_disable_mld, NULL,
   1787  1.12  christos 	  "= disable AP MLD to which the interface is affiliated" },
   1788  1.11  christos 	{ "update_beacon", hostapd_cli_cmd_update_beacon, NULL,
   1789  1.11  christos 	  "= update Beacon frame contents\n"},
   1790  1.12  christos 	{ "stop_ap", hostapd_cli_cmd_stop_ap, NULL,
   1791  1.12  christos 	  "= stop AP\n"},
   1792  1.10  christos 	{ "erp_flush", hostapd_cli_cmd_erp_flush, NULL,
   1793  1.10  christos 	  "= drop all ERP keys"},
   1794  1.10  christos 	{ "log_level", hostapd_cli_cmd_log_level, NULL,
   1795  1.10  christos 	  "[level] = show/change log verbosity level" },
   1796  1.10  christos 	{ "pmksa", hostapd_cli_cmd_pmksa, NULL,
   1797  1.10  christos 	  " = show PMKSA cache entries" },
   1798  1.10  christos 	{ "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL,
   1799  1.10  christos 	  " = flush PMKSA cache" },
   1800  1.10  christos 	{ "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL,
   1801  1.10  christos 	  "<addr> <ssid=> <nr=> [lci=] [civic=] [stat]\n"
   1802  1.10  christos 	  "  = add AP to neighbor database" },
   1803  1.12  christos 	{ "show_neighbor", hostapd_cli_cmd_show_neighbor, NULL,
   1804  1.12  christos 	  "  = show neighbor database entries" },
   1805  1.10  christos 	{ "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL,
   1806  1.12  christos 	  "<addr> [ssid=<hex>] = remove AP from neighbor database" },
   1807  1.10  christos 	{ "req_lci", hostapd_cli_cmd_req_lci, hostapd_complete_stations,
   1808  1.10  christos 	  "<addr> = send LCI request to a station"},
   1809  1.10  christos 	{ "req_range", hostapd_cli_cmd_req_range, NULL,
   1810  1.10  christos 	  " = send FTM range request"},
   1811  1.10  christos 	{ "driver_flags", hostapd_cli_cmd_driver_flags, NULL,
   1812  1.10  christos 	  " = show supported driver flags"},
   1813  1.12  christos 	{ "driver_flags2", hostapd_cli_cmd_driver_flags2, NULL,
   1814  1.12  christos 	  " = show supported driver flags2"},
   1815  1.10  christos #ifdef CONFIG_DPP
   1816  1.10  christos 	{ "dpp_qr_code", hostapd_cli_cmd_dpp_qr_code, NULL,
   1817  1.10  christos 	  "report a scanned DPP URI from a QR Code" },
   1818  1.10  christos 	{ "dpp_bootstrap_gen", hostapd_cli_cmd_dpp_bootstrap_gen, NULL,
   1819  1.10  christos 	  "type=<qrcode> [chan=..] [mac=..] [info=..] [curve=..] [key=..] = generate DPP bootstrap information" },
   1820  1.10  christos 	{ "dpp_bootstrap_remove", hostapd_cli_cmd_dpp_bootstrap_remove, NULL,
   1821  1.10  christos 	  "*|<id> = remove DPP bootstrap information" },
   1822  1.10  christos 	{ "dpp_bootstrap_get_uri", hostapd_cli_cmd_dpp_bootstrap_get_uri, NULL,
   1823  1.10  christos 	  "<id> = get DPP bootstrap URI" },
   1824  1.10  christos 	{ "dpp_bootstrap_info", hostapd_cli_cmd_dpp_bootstrap_info, NULL,
   1825  1.10  christos 	  "<id> = show DPP bootstrap information" },
   1826  1.12  christos 	{ "dpp_bootstrap_set", hostapd_cli_cmd_dpp_bootstrap_set, NULL,
   1827  1.12  christos 	  "<id> [conf=..] [ssid=<SSID>] [ssid_charset=#] [psk=<PSK>] [pass=<passphrase>] [configurator=<id>] [conn_status=#] [akm_use_selector=<0|1>] [group_id=..] [expiry=#] [csrattrs=..] = set DPP configurator parameters" },
   1828  1.10  christos 	{ "dpp_auth_init", hostapd_cli_cmd_dpp_auth_init, NULL,
   1829  1.10  christos 	  "peer=<id> [own=<id>] = initiate DPP bootstrapping" },
   1830  1.10  christos 	{ "dpp_listen", hostapd_cli_cmd_dpp_listen, NULL,
   1831  1.10  christos 	  "<freq in MHz> = start DPP listen" },
   1832  1.10  christos 	{ "dpp_stop_listen", hostapd_cli_cmd_dpp_stop_listen, NULL,
   1833  1.10  christos 	  "= stop DPP listen" },
   1834  1.10  christos 	{ "dpp_configurator_add", hostapd_cli_cmd_dpp_configurator_add, NULL,
   1835  1.10  christos 	  "[curve=..] [key=..] = add DPP configurator" },
   1836  1.10  christos 	{ "dpp_configurator_remove", hostapd_cli_cmd_dpp_configurator_remove,
   1837  1.10  christos 	  NULL,
   1838  1.10  christos 	  "*|<id> = remove DPP configurator" },
   1839  1.10  christos 	{ "dpp_configurator_get_key", hostapd_cli_cmd_dpp_configurator_get_key,
   1840  1.10  christos 	  NULL,
   1841  1.10  christos 	  "<id> = Get DPP configurator's private key" },
   1842  1.11  christos 	{ "dpp_configurator_sign", hostapd_cli_cmd_dpp_configurator_sign, NULL,
   1843  1.11  christos 	  "conf=<role> configurator=<id> = generate self DPP configuration" },
   1844  1.10  christos 	{ "dpp_pkex_add", hostapd_cli_cmd_dpp_pkex_add, NULL,
   1845  1.10  christos 	  "add PKEX code" },
   1846  1.10  christos 	{ "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL,
   1847  1.10  christos 	  "*|<id> = remove DPP pkex information" },
   1848  1.12  christos #ifdef CONFIG_DPP2
   1849  1.12  christos 	{ "dpp_controller_start", hostapd_cli_cmd_dpp_controller_start, NULL,
   1850  1.12  christos 	  "[tcp_port=<port>] [role=..] = start DPP controller" },
   1851  1.12  christos 	{ "dpp_controller_stop", hostapd_cli_cmd_dpp_controller_stop, NULL,
   1852  1.12  christos 	  "= stop DPP controller" },
   1853  1.12  christos 	{ "dpp_chirp", hostapd_cli_cmd_dpp_chirp, NULL,
   1854  1.12  christos 	  "own=<BI ID> iter=<count> = start DPP chirp" },
   1855  1.12  christos 	{ "dpp_stop_chirp", hostapd_cli_cmd_dpp_stop_chirp, NULL,
   1856  1.12  christos 	  "= stop DPP chirp" },
   1857  1.12  christos #endif /* CONFIG_DPP2 */
   1858  1.12  christos #ifdef CONFIG_DPP3
   1859  1.12  christos 	{ "dpp_push_button", hostapd_cli_cmd_dpp_push_button, NULL,
   1860  1.12  christos 	  "= press DPP push button" },
   1861  1.12  christos #endif /* CONFIG_DPP3 */
   1862  1.10  christos #endif /* CONFIG_DPP */
   1863  1.10  christos 	{ "accept_acl", hostapd_cli_cmd_accept_macacl, NULL,
   1864  1.10  christos 	  "=Add/Delete/Show/Clear accept MAC ACL" },
   1865  1.10  christos 	{ "deny_acl", hostapd_cli_cmd_deny_macacl, NULL,
   1866  1.10  christos 	  "=Add/Delete/Show/Clear deny MAC ACL" },
   1867  1.10  christos 	{ "poll_sta", hostapd_cli_cmd_poll_sta, hostapd_complete_stations,
   1868  1.10  christos 	  "<addr> = poll a STA to check connectivity with a QoS null frame" },
   1869  1.11  christos 	{ "req_beacon", hostapd_cli_cmd_req_beacon, NULL,
   1870  1.11  christos 	  "<addr> [req_mode=] <measurement request hexdump>  = send a Beacon report request to a station" },
   1871  1.12  christos 	{ "req_link_measurement", hostapd_cli_cmd_req_link_measurement, NULL,
   1872  1.12  christos 	  "<addr> = send a link measurement report request to a station"},
   1873  1.11  christos 	{ "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL,
   1874  1.11  christos 	  "= reload wpa_psk_file only" },
   1875  1.12  christos #ifdef CONFIG_IEEE80211R_AP
   1876  1.12  christos 	{ "reload_rxkhs", hostapd_cli_cmd_reload_rxkhs, NULL,
   1877  1.12  christos 	  "= reload R0KHs and R1KHs" },
   1878  1.12  christos 	{ "get_rxkhs", hostapd_cli_cmd_get_rxkhs, NULL,
   1879  1.12  christos 	  "= get R0KHs and R1KHs" },
   1880  1.12  christos #endif /* CONFIG_IEEE80211R_AP */
   1881  1.12  christos #ifdef ANDROID
   1882  1.12  christos 	{ "driver", hostapd_cli_cmd_driver, NULL,
   1883  1.12  christos 	  "<driver sub command> [<hex formatted data>] = send driver command data" },
   1884  1.12  christos #endif /* ANDROID */
   1885   1.9  christos 	{ NULL, NULL, NULL, NULL }
   1886   1.1  christos };
   1887   1.1  christos 
   1888   1.1  christos 
   1889   1.9  christos /*
   1890   1.9  christos  * Prints command usage, lines are padded with the specified string.
   1891   1.9  christos  */
   1892   1.9  christos static void print_cmd_help(FILE *stream, const struct hostapd_cli_cmd *cmd,
   1893   1.9  christos 			   const char *pad)
   1894   1.9  christos {
   1895   1.9  christos 	char c;
   1896   1.9  christos 	size_t n;
   1897   1.9  christos 
   1898   1.9  christos 	if (cmd->usage == NULL)
   1899   1.9  christos 		return;
   1900   1.9  christos 	fprintf(stream, "%s%s ", pad, cmd->cmd);
   1901   1.9  christos 	for (n = 0; (c = cmd->usage[n]); n++) {
   1902   1.9  christos 		fprintf(stream, "%c", c);
   1903   1.9  christos 		if (c == '\n')
   1904   1.9  christos 			fprintf(stream, "%s", pad);
   1905   1.9  christos 	}
   1906   1.9  christos 	fprintf(stream, "\n");
   1907   1.9  christos }
   1908   1.9  christos 
   1909   1.9  christos 
   1910   1.9  christos static void print_help(FILE *stream, const char *cmd)
   1911   1.9  christos {
   1912   1.9  christos 	int n;
   1913   1.9  christos 
   1914   1.9  christos 	fprintf(stream, "commands:\n");
   1915   1.9  christos 	for (n = 0; hostapd_cli_commands[n].cmd; n++) {
   1916   1.9  christos 		if (cmd == NULL || str_starts(hostapd_cli_commands[n].cmd, cmd))
   1917   1.9  christos 			print_cmd_help(stream, &hostapd_cli_commands[n], "  ");
   1918   1.9  christos 	}
   1919   1.9  christos }
   1920   1.9  christos 
   1921   1.9  christos 
   1922   1.1  christos static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
   1923   1.1  christos {
   1924   1.9  christos 	const struct hostapd_cli_cmd *cmd, *match = NULL;
   1925   1.1  christos 	int count;
   1926   1.1  christos 
   1927   1.1  christos 	count = 0;
   1928   1.1  christos 	cmd = hostapd_cli_commands;
   1929   1.1  christos 	while (cmd->cmd) {
   1930   1.1  christos 		if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
   1931   1.1  christos 			match = cmd;
   1932   1.4  christos 			if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
   1933   1.4  christos 				/* we have an exact match */
   1934   1.4  christos 				count = 1;
   1935   1.4  christos 				break;
   1936   1.4  christos 			}
   1937   1.1  christos 			count++;
   1938   1.1  christos 		}
   1939   1.1  christos 		cmd++;
   1940   1.1  christos 	}
   1941   1.1  christos 
   1942   1.1  christos 	if (count > 1) {
   1943   1.1  christos 		printf("Ambiguous command '%s'; possible commands:", argv[0]);
   1944   1.1  christos 		cmd = hostapd_cli_commands;
   1945   1.1  christos 		while (cmd->cmd) {
   1946   1.1  christos 			if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
   1947   1.1  christos 			    0) {
   1948   1.1  christos 				printf(" %s", cmd->cmd);
   1949   1.1  christos 			}
   1950   1.1  christos 			cmd++;
   1951   1.1  christos 		}
   1952   1.1  christos 		printf("\n");
   1953   1.1  christos 	} else if (count == 0) {
   1954   1.1  christos 		printf("Unknown command '%s'\n", argv[0]);
   1955   1.1  christos 	} else {
   1956   1.1  christos 		match->handler(ctrl, argc - 1, &argv[1]);
   1957   1.1  christos 	}
   1958   1.1  christos }
   1959   1.1  christos 
   1960   1.1  christos 
   1961   1.9  christos static void cli_event(const char *str)
   1962   1.9  christos {
   1963   1.9  christos 	const char *start, *s;
   1964   1.9  christos 
   1965   1.9  christos 	start = os_strchr(str, '>');
   1966   1.9  christos 	if (start == NULL)
   1967   1.9  christos 		return;
   1968   1.9  christos 
   1969   1.9  christos 	start++;
   1970   1.9  christos 
   1971   1.9  christos 	if (str_starts(start, AP_STA_CONNECTED)) {
   1972   1.9  christos 		s = os_strchr(start, ' ');
   1973   1.9  christos 		if (s == NULL)
   1974   1.9  christos 			return;
   1975   1.9  christos 		cli_txt_list_add(&stations, s + 1);
   1976   1.9  christos 		return;
   1977   1.9  christos 	}
   1978   1.9  christos 
   1979   1.9  christos 	if (str_starts(start, AP_STA_DISCONNECTED)) {
   1980   1.9  christos 		s = os_strchr(start, ' ');
   1981   1.9  christos 		if (s == NULL)
   1982   1.9  christos 			return;
   1983   1.9  christos 		cli_txt_list_del_addr(&stations, s + 1);
   1984   1.9  christos 		return;
   1985   1.9  christos 	}
   1986   1.9  christos }
   1987   1.9  christos 
   1988   1.9  christos 
   1989   1.1  christos static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
   1990   1.1  christos 				     int action_monitor)
   1991   1.1  christos {
   1992   1.1  christos 	int first = 1;
   1993   1.1  christos 	if (ctrl_conn == NULL)
   1994   1.1  christos 		return;
   1995   1.1  christos 	while (wpa_ctrl_pending(ctrl)) {
   1996  1.10  christos 		char buf[4096];
   1997   1.1  christos 		size_t len = sizeof(buf) - 1;
   1998   1.1  christos 		if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
   1999   1.1  christos 			buf[len] = '\0';
   2000   1.1  christos 			if (action_monitor)
   2001   1.1  christos 				hostapd_cli_action_process(buf, len);
   2002   1.1  christos 			else {
   2003   1.9  christos 				cli_event(buf);
   2004   1.1  christos 				if (in_read && first)
   2005   1.1  christos 					printf("\n");
   2006   1.1  christos 				first = 0;
   2007   1.1  christos 				printf("%s\n", buf);
   2008   1.1  christos 			}
   2009   1.1  christos 		} else {
   2010   1.1  christos 			printf("Could not read pending message.\n");
   2011   1.1  christos 			break;
   2012   1.1  christos 		}
   2013   1.1  christos 	}
   2014   1.1  christos }
   2015   1.1  christos 
   2016   1.1  christos 
   2017   1.9  christos static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx)
   2018   1.1  christos {
   2019   1.9  christos 	hostapd_cli_recv_pending(ctrl_conn, 0, 0);
   2020   1.1  christos }
   2021   1.1  christos 
   2022   1.1  christos 
   2023   1.4  christos static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
   2024   1.1  christos {
   2025   1.1  christos 	if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
   2026   1.1  christos 		printf("Connection to hostapd lost - trying to reconnect\n");
   2027   1.1  christos 		hostapd_cli_close_connection();
   2028   1.1  christos 	}
   2029  1.10  christos 	if (!ctrl_conn && hostapd_cli_reconnect(ctrl_ifname) == 0)
   2030  1.10  christos 		printf("Connection to hostapd re-established\n");
   2031   1.1  christos 	if (ctrl_conn)
   2032   1.1  christos 		hostapd_cli_recv_pending(ctrl_conn, 1, 0);
   2033   1.4  christos 	eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
   2034   1.4  christos }
   2035   1.4  christos 
   2036   1.4  christos 
   2037   1.4  christos static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
   2038   1.4  christos {
   2039   1.4  christos 	eloop_terminate();
   2040   1.4  christos }
   2041   1.4  christos 
   2042   1.4  christos 
   2043   1.4  christos static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
   2044   1.4  christos {
   2045   1.4  christos 	char *argv[max_args];
   2046   1.4  christos 	int argc;
   2047   1.4  christos 	argc = tokenize_cmd(cmd, argv);
   2048   1.4  christos 	if (argc)
   2049   1.4  christos 		wpa_request(ctrl_conn, argc, argv);
   2050   1.4  christos }
   2051   1.4  christos 
   2052   1.4  christos 
   2053   1.4  christos static void hostapd_cli_edit_eof_cb(void *ctx)
   2054   1.4  christos {
   2055   1.4  christos 	eloop_terminate();
   2056   1.4  christos }
   2057   1.4  christos 
   2058   1.4  christos 
   2059   1.9  christos static char ** list_cmd_list(void)
   2060   1.9  christos {
   2061   1.9  christos 	char **res;
   2062   1.9  christos 	int i, count;
   2063   1.9  christos 
   2064   1.9  christos 	count = ARRAY_SIZE(hostapd_cli_commands);
   2065   1.9  christos 	res = os_calloc(count + 1, sizeof(char *));
   2066   1.9  christos 	if (res == NULL)
   2067   1.9  christos 		return NULL;
   2068   1.9  christos 
   2069   1.9  christos 	for (i = 0; hostapd_cli_commands[i].cmd; i++) {
   2070   1.9  christos 		res[i] = os_strdup(hostapd_cli_commands[i].cmd);
   2071   1.9  christos 		if (res[i] == NULL)
   2072   1.9  christos 			break;
   2073   1.9  christos 	}
   2074   1.9  christos 
   2075   1.9  christos 	return res;
   2076   1.9  christos }
   2077   1.9  christos 
   2078   1.9  christos 
   2079   1.9  christos static char ** hostapd_cli_cmd_completion(const char *cmd, const char *str,
   2080   1.9  christos 				      int pos)
   2081   1.9  christos {
   2082   1.9  christos 	int i;
   2083   1.9  christos 
   2084   1.9  christos 	for (i = 0; hostapd_cli_commands[i].cmd; i++) {
   2085   1.9  christos 		if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0)
   2086   1.9  christos 			continue;
   2087   1.9  christos 		if (hostapd_cli_commands[i].completion)
   2088   1.9  christos 			return hostapd_cli_commands[i].completion(str, pos);
   2089   1.9  christos 		if (!hostapd_cli_commands[i].usage)
   2090   1.9  christos 			return NULL;
   2091   1.9  christos 		edit_clear_line();
   2092   1.9  christos 		printf("\r%s\n", hostapd_cli_commands[i].usage);
   2093   1.9  christos 		edit_redraw();
   2094   1.9  christos 		break;
   2095   1.9  christos 	}
   2096   1.9  christos 
   2097   1.9  christos 	return NULL;
   2098   1.9  christos }
   2099   1.9  christos 
   2100   1.9  christos 
   2101   1.9  christos static char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str,
   2102   1.9  christos 					      int pos)
   2103   1.9  christos {
   2104   1.9  christos 	char **res;
   2105   1.9  christos 	const char *end;
   2106   1.9  christos 	char *cmd;
   2107   1.9  christos 
   2108   1.9  christos 	end = os_strchr(str, ' ');
   2109   1.9  christos 	if (end == NULL || str + pos < end)
   2110   1.9  christos 		return list_cmd_list();
   2111   1.9  christos 
   2112   1.9  christos 	cmd = os_malloc(pos + 1);
   2113   1.9  christos 	if (cmd == NULL)
   2114   1.9  christos 		return NULL;
   2115   1.9  christos 	os_memcpy(cmd, str, pos);
   2116   1.9  christos 	cmd[end - str] = '\0';
   2117   1.9  christos 	res = hostapd_cli_cmd_completion(cmd, str, pos);
   2118   1.9  christos 	os_free(cmd);
   2119   1.9  christos 	return res;
   2120   1.9  christos }
   2121   1.9  christos 
   2122   1.9  christos 
   2123   1.4  christos static void hostapd_cli_interactive(void)
   2124   1.4  christos {
   2125  1.10  christos 	char *hfile = NULL;
   2126  1.10  christos 	char *home;
   2127  1.10  christos 
   2128   1.4  christos 	printf("\nInteractive mode\n\n");
   2129   1.4  christos 
   2130  1.10  christos #ifdef CONFIG_HOSTAPD_CLI_HISTORY_DIR
   2131  1.10  christos 	home = CONFIG_HOSTAPD_CLI_HISTORY_DIR;
   2132  1.10  christos #else /* CONFIG_HOSTAPD_CLI_HISTORY_DIR */
   2133  1.10  christos 	home = getenv("HOME");
   2134  1.10  christos #endif /* CONFIG_HOSTAPD_CLI_HISTORY_DIR */
   2135  1.10  christos 	if (home) {
   2136  1.10  christos 		const char *fname = ".hostapd_cli_history";
   2137  1.10  christos 		int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
   2138  1.10  christos 		hfile = os_malloc(hfile_len);
   2139  1.10  christos 		if (hfile)
   2140  1.10  christos 			os_snprintf(hfile, hfile_len, "%s/%s", home, fname);
   2141  1.10  christos 	}
   2142  1.10  christos 
   2143   1.4  christos 	edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
   2144  1.10  christos 		  hostapd_cli_edit_completion_cb, NULL, hfile, NULL);
   2145   1.4  christos 	eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
   2146   1.4  christos 
   2147   1.4  christos 	eloop_run();
   2148   1.4  christos 
   2149   1.9  christos 	cli_txt_list_flush(&stations);
   2150  1.10  christos 	edit_deinit(hfile, NULL);
   2151  1.10  christos 	os_free(hfile);
   2152   1.4  christos 	eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
   2153   1.4  christos }
   2154   1.4  christos 
   2155   1.4  christos 
   2156   1.4  christos static void hostapd_cli_cleanup(void)
   2157   1.4  christos {
   2158   1.4  christos 	hostapd_cli_close_connection();
   2159   1.4  christos 	if (pid_file)
   2160   1.4  christos 		os_daemonize_terminate(pid_file);
   2161   1.4  christos 
   2162   1.4  christos 	os_program_deinit();
   2163   1.1  christos }
   2164   1.1  christos 
   2165   1.1  christos 
   2166  1.12  christos static void hostapd_cli_action_ping(void *eloop_ctx, void *timeout_ctx)
   2167   1.1  christos {
   2168  1.12  christos 	struct wpa_ctrl *ctrl = eloop_ctx;
   2169   1.1  christos 	char buf[256];
   2170   1.1  christos 	size_t len;
   2171   1.1  christos 
   2172  1.12  christos 	/* verify that connection is still working */
   2173  1.12  christos 	len = sizeof(buf) - 1;
   2174  1.12  christos 	if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
   2175  1.12  christos 			     hostapd_cli_action_cb) < 0 ||
   2176  1.12  christos 	    len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
   2177  1.12  christos 		printf("hostapd did not reply to PING command - exiting\n");
   2178  1.12  christos 		eloop_terminate();
   2179  1.12  christos 		return;
   2180  1.12  christos 	}
   2181  1.12  christos 	eloop_register_timeout(ping_interval, 0, hostapd_cli_action_ping,
   2182  1.12  christos 			       ctrl, NULL);
   2183  1.12  christos }
   2184  1.12  christos 
   2185  1.12  christos 
   2186  1.12  christos static void hostapd_cli_action_receive(int sock, void *eloop_ctx,
   2187  1.12  christos 				       void *sock_ctx)
   2188  1.12  christos {
   2189  1.12  christos 	struct wpa_ctrl *ctrl = eloop_ctx;
   2190  1.12  christos 
   2191  1.12  christos 	hostapd_cli_recv_pending(ctrl, 0, 1);
   2192  1.12  christos }
   2193  1.12  christos 
   2194   1.1  christos 
   2195  1.12  christos static void hostapd_cli_action(struct wpa_ctrl *ctrl)
   2196  1.12  christos {
   2197  1.12  christos 	int fd;
   2198   1.1  christos 
   2199  1.12  christos 	fd = wpa_ctrl_get_fd(ctrl);
   2200  1.12  christos 	eloop_register_timeout(ping_interval, 0, hostapd_cli_action_ping,
   2201  1.12  christos 			       ctrl, NULL);
   2202  1.12  christos 	eloop_register_read_sock(fd, hostapd_cli_action_receive, ctrl, NULL);
   2203  1.12  christos 	eloop_run();
   2204  1.12  christos 	eloop_cancel_timeout(hostapd_cli_action_ping, ctrl, NULL);
   2205  1.12  christos 	eloop_unregister_read_sock(fd);
   2206   1.1  christos }
   2207   1.1  christos 
   2208   1.1  christos 
   2209   1.1  christos int main(int argc, char *argv[])
   2210   1.1  christos {
   2211   1.1  christos 	int warning_displayed = 0;
   2212   1.1  christos 	int c;
   2213   1.1  christos 	int daemonize = 0;
   2214  1.12  christos 	int reconnect = 0;
   2215   1.1  christos 
   2216   1.1  christos 	if (os_program_init())
   2217   1.1  christos 		return -1;
   2218   1.1  christos 
   2219   1.1  christos 	for (;;) {
   2220  1.12  christos 		c = getopt(argc, argv, "a:BhG:i:p:P:rs:v");
   2221   1.1  christos 		if (c < 0)
   2222   1.1  christos 			break;
   2223   1.1  christos 		switch (c) {
   2224   1.1  christos 		case 'a':
   2225   1.1  christos 			action_file = optarg;
   2226   1.1  christos 			break;
   2227   1.1  christos 		case 'B':
   2228   1.1  christos 			daemonize = 1;
   2229   1.1  christos 			break;
   2230   1.1  christos 		case 'G':
   2231   1.1  christos 			ping_interval = atoi(optarg);
   2232   1.1  christos 			break;
   2233   1.1  christos 		case 'h':
   2234   1.1  christos 			usage();
   2235   1.1  christos 			return 0;
   2236   1.1  christos 		case 'v':
   2237   1.1  christos 			printf("%s\n", hostapd_cli_version);
   2238   1.1  christos 			return 0;
   2239   1.1  christos 		case 'i':
   2240   1.1  christos 			os_free(ctrl_ifname);
   2241   1.1  christos 			ctrl_ifname = os_strdup(optarg);
   2242   1.1  christos 			break;
   2243   1.1  christos 		case 'p':
   2244   1.1  christos 			ctrl_iface_dir = optarg;
   2245   1.1  christos 			break;
   2246   1.9  christos 		case 'P':
   2247   1.9  christos 			pid_file = optarg;
   2248   1.9  christos 			break;
   2249  1.12  christos 		case 'r':
   2250  1.12  christos 			reconnect = 1;
   2251  1.12  christos 			break;
   2252   1.9  christos 		case 's':
   2253   1.9  christos 			client_socket_dir = optarg;
   2254   1.9  christos 			break;
   2255   1.1  christos 		default:
   2256   1.1  christos 			usage();
   2257   1.1  christos 			return -1;
   2258   1.1  christos 		}
   2259   1.1  christos 	}
   2260   1.1  christos 
   2261   1.1  christos 	interactive = (argc == optind) && (action_file == NULL);
   2262   1.1  christos 
   2263   1.1  christos 	if (interactive) {
   2264   1.9  christos 		printf("%s\n\n%s\n\n", hostapd_cli_version, cli_license);
   2265   1.1  christos 	}
   2266   1.1  christos 
   2267   1.4  christos 	if (eloop_init())
   2268   1.4  christos 		return -1;
   2269   1.4  christos 
   2270   1.1  christos 	for (;;) {
   2271   1.1  christos 		if (ctrl_ifname == NULL) {
   2272   1.1  christos 			struct dirent *dent;
   2273   1.1  christos 			DIR *dir = opendir(ctrl_iface_dir);
   2274   1.1  christos 			if (dir) {
   2275   1.1  christos 				while ((dent = readdir(dir))) {
   2276   1.1  christos 					if (os_strcmp(dent->d_name, ".") == 0
   2277   1.1  christos 					    ||
   2278   1.1  christos 					    os_strcmp(dent->d_name, "..") == 0)
   2279   1.1  christos 						continue;
   2280   1.1  christos 					printf("Selected interface '%s'\n",
   2281   1.1  christos 					       dent->d_name);
   2282   1.1  christos 					ctrl_ifname = os_strdup(dent->d_name);
   2283   1.1  christos 					break;
   2284   1.1  christos 				}
   2285   1.1  christos 				closedir(dir);
   2286   1.1  christos 			}
   2287   1.1  christos 		}
   2288  1.10  christos 		hostapd_cli_reconnect(ctrl_ifname);
   2289   1.1  christos 		if (ctrl_conn) {
   2290   1.1  christos 			if (warning_displayed)
   2291   1.1  christos 				printf("Connection established.\n");
   2292   1.1  christos 			break;
   2293   1.1  christos 		}
   2294  1.12  christos 		if (!interactive && !reconnect) {
   2295   1.1  christos 			perror("Failed to connect to hostapd - "
   2296   1.1  christos 			       "wpa_ctrl_open");
   2297   1.1  christos 			return -1;
   2298   1.1  christos 		}
   2299   1.1  christos 
   2300   1.1  christos 		if (!warning_displayed) {
   2301   1.1  christos 			printf("Could not connect to hostapd - re-trying\n");
   2302   1.1  christos 			warning_displayed = 1;
   2303   1.1  christos 		}
   2304   1.1  christos 		os_sleep(1, 0);
   2305   1.1  christos 		continue;
   2306   1.1  christos 	}
   2307   1.1  christos 
   2308  1.12  christos 	eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
   2309  1.12  christos 
   2310  1.10  christos 	if (action_file && !hostapd_cli_attached)
   2311  1.10  christos 		return -1;
   2312   1.8       roy 	if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
   2313   1.1  christos 		return -1;
   2314  1.12  christos 	if (reconnect && action_file && ctrl_ifname) {
   2315  1.12  christos 		while (!hostapd_cli_quit) {
   2316  1.12  christos 			if (ctrl_conn)
   2317  1.12  christos 				hostapd_cli_action(ctrl_conn);
   2318  1.12  christos 			os_sleep(1, 0);
   2319  1.12  christos 			hostapd_cli_reconnect(ctrl_ifname);
   2320  1.12  christos 		}
   2321  1.12  christos 	} else if (interactive)
   2322   1.1  christos 		hostapd_cli_interactive();
   2323   1.1  christos 	else if (action_file)
   2324   1.1  christos 		hostapd_cli_action(ctrl_conn);
   2325   1.1  christos 	else
   2326   1.1  christos 		wpa_request(ctrl_conn, argc - optind, &argv[optind]);
   2327   1.1  christos 
   2328   1.9  christos 	unregister_event_handler(ctrl_conn);
   2329   1.1  christos 	os_free(ctrl_ifname);
   2330   1.4  christos 	eloop_destroy();
   2331   1.1  christos 	hostapd_cli_cleanup();
   2332   1.1  christos 	return 0;
   2333   1.1  christos }
   2334   1.9  christos 
   2335   1.9  christos #else /* CONFIG_NO_CTRL_IFACE */
   2336   1.9  christos 
   2337   1.9  christos int main(int argc, char *argv[])
   2338   1.9  christos {
   2339   1.9  christos 	return -1;
   2340   1.9  christos }
   2341   1.9  christos 
   2342   1.9  christos #endif /* CONFIG_NO_CTRL_IFACE */
   2343