1214503Srpaulo/* 2214503Srpaulo * hostapd - command line interface for hostapd daemon 3346981Scy * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> 4214503Srpaulo * 5252726Srpaulo * This software may be distributed under the terms of the BSD license. 6252726Srpaulo * See README for more details. 7214503Srpaulo */ 8214503Srpaulo 9214503Srpaulo#include "includes.h" 10214503Srpaulo#include <dirent.h> 11214503Srpaulo 12214503Srpaulo#include "common/wpa_ctrl.h" 13289549Srpaulo#include "common/ieee802_11_defs.h" 14252726Srpaulo#include "utils/common.h" 15252726Srpaulo#include "utils/eloop.h" 16252726Srpaulo#include "utils/edit.h" 17214503Srpaulo#include "common/version.h" 18337817Scy#include "common/cli.h" 19214503Srpaulo 20337817Scy#ifndef CONFIG_NO_CTRL_IFACE 21214503Srpaulo 22289549Srpaulostatic const char *const hostapd_cli_version = 23214503Srpaulo"hostapd_cli v" VERSION_STR "\n" 24346981Scy"Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi> and contributors"; 25214503Srpaulo 26214503Srpaulostatic struct wpa_ctrl *ctrl_conn; 27214503Srpaulostatic int hostapd_cli_quit = 0; 28214503Srpaulostatic int hostapd_cli_attached = 0; 29281806Srpaulo 30281806Srpaulo#ifndef CONFIG_CTRL_IFACE_DIR 31281806Srpaulo#define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd" 32281806Srpaulo#endif /* CONFIG_CTRL_IFACE_DIR */ 33281806Srpaulostatic const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR; 34289549Srpaulostatic const char *client_socket_dir = NULL; 35281806Srpaulo 36214503Srpaulostatic char *ctrl_ifname = NULL; 37214503Srpaulostatic const char *pid_file = NULL; 38214503Srpaulostatic const char *action_file = NULL; 39214503Srpaulostatic int ping_interval = 5; 40252726Srpaulostatic int interactive = 0; 41337817Scystatic int event_handler_registered = 0; 42214503Srpaulo 43337817Scystatic DEFINE_DL_LIST(stations); /* struct cli_txt_entry */ 44214503Srpaulo 45337817Scystatic void print_help(FILE *stream, const char *cmd); 46337817Scystatic char ** list_cmd_list(void); 47337817Scystatic void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx); 48346981Scystatic void update_stations(struct wpa_ctrl *ctrl); 49346981Scystatic void cli_event(const char *str); 50337817Scy 51337817Scy 52214503Srpaulostatic void usage(void) 53214503Srpaulo{ 54214503Srpaulo fprintf(stderr, "%s\n", hostapd_cli_version); 55214503Srpaulo fprintf(stderr, 56214503Srpaulo "\n" 57214503Srpaulo "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] " 58214503Srpaulo "[-a<path>] \\\n" 59289549Srpaulo " [-P<pid file>] [-G<ping interval>] [command..]\n" 60214503Srpaulo "\n" 61214503Srpaulo "Options:\n" 62214503Srpaulo " -h help (show this usage text)\n" 63214503Srpaulo " -v shown version information\n" 64214503Srpaulo " -p<path> path to find control sockets (default: " 65214503Srpaulo "/var/run/hostapd)\n" 66289549Srpaulo " -s<dir_path> dir path to open client sockets (default: " 67289549Srpaulo CONFIG_CTRL_IFACE_DIR ")\n" 68214503Srpaulo " -a<file> run in daemon mode executing the action file " 69214503Srpaulo "based on events\n" 70214503Srpaulo " from hostapd\n" 71214503Srpaulo " -B run a daemon in the background\n" 72214503Srpaulo " -i<ifname> Interface to listen on (default: first " 73214503Srpaulo "interface found in the\n" 74337817Scy " socket path)\n\n"); 75337817Scy print_help(stderr, NULL); 76214503Srpaulo} 77214503Srpaulo 78214503Srpaulo 79337817Scystatic void register_event_handler(struct wpa_ctrl *ctrl) 80337817Scy{ 81337817Scy if (!ctrl_conn) 82337817Scy return; 83337817Scy if (interactive) { 84337817Scy event_handler_registered = 85337817Scy !eloop_register_read_sock(wpa_ctrl_get_fd(ctrl), 86337817Scy hostapd_cli_receive, 87337817Scy NULL, NULL); 88337817Scy } 89337817Scy} 90337817Scy 91337817Scy 92337817Scystatic void unregister_event_handler(struct wpa_ctrl *ctrl) 93337817Scy{ 94337817Scy if (!ctrl_conn) 95337817Scy return; 96337817Scy if (interactive && event_handler_registered) { 97337817Scy eloop_unregister_read_sock(wpa_ctrl_get_fd(ctrl)); 98337817Scy event_handler_registered = 0; 99337817Scy } 100337817Scy} 101337817Scy 102337817Scy 103214503Srpaulostatic struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname) 104214503Srpaulo{ 105337817Scy#ifndef CONFIG_CTRL_IFACE_UDP 106214503Srpaulo char *cfile; 107214503Srpaulo int flen; 108337817Scy#endif /* !CONFIG_CTRL_IFACE_UDP */ 109214503Srpaulo 110214503Srpaulo if (ifname == NULL) 111214503Srpaulo return NULL; 112214503Srpaulo 113337817Scy#ifdef CONFIG_CTRL_IFACE_UDP 114337817Scy ctrl_conn = wpa_ctrl_open(ifname); 115337817Scy return ctrl_conn; 116337817Scy#else /* CONFIG_CTRL_IFACE_UDP */ 117214503Srpaulo flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2; 118214503Srpaulo cfile = malloc(flen); 119214503Srpaulo if (cfile == NULL) 120214503Srpaulo return NULL; 121214503Srpaulo snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname); 122214503Srpaulo 123289549Srpaulo if (client_socket_dir && client_socket_dir[0] && 124289549Srpaulo access(client_socket_dir, F_OK) < 0) { 125289549Srpaulo perror(client_socket_dir); 126289549Srpaulo free(cfile); 127289549Srpaulo return NULL; 128289549Srpaulo } 129289549Srpaulo 130289549Srpaulo ctrl_conn = wpa_ctrl_open2(cfile, client_socket_dir); 131214503Srpaulo free(cfile); 132214503Srpaulo return ctrl_conn; 133337817Scy#endif /* CONFIG_CTRL_IFACE_UDP */ 134214503Srpaulo} 135214503Srpaulo 136214503Srpaulo 137214503Srpaulostatic void hostapd_cli_close_connection(void) 138214503Srpaulo{ 139214503Srpaulo if (ctrl_conn == NULL) 140214503Srpaulo return; 141214503Srpaulo 142337817Scy unregister_event_handler(ctrl_conn); 143214503Srpaulo if (hostapd_cli_attached) { 144214503Srpaulo wpa_ctrl_detach(ctrl_conn); 145214503Srpaulo hostapd_cli_attached = 0; 146214503Srpaulo } 147214503Srpaulo wpa_ctrl_close(ctrl_conn); 148214503Srpaulo ctrl_conn = NULL; 149214503Srpaulo} 150214503Srpaulo 151214503Srpaulo 152346981Scystatic int hostapd_cli_reconnect(const char *ifname) 153346981Scy{ 154346981Scy char *next_ctrl_ifname; 155346981Scy 156346981Scy hostapd_cli_close_connection(); 157346981Scy 158346981Scy if (!ifname) 159346981Scy return -1; 160346981Scy 161346981Scy next_ctrl_ifname = os_strdup(ifname); 162346981Scy os_free(ctrl_ifname); 163346981Scy ctrl_ifname = next_ctrl_ifname; 164346981Scy if (!ctrl_ifname) 165346981Scy return -1; 166346981Scy 167346981Scy ctrl_conn = hostapd_cli_open_connection(ctrl_ifname); 168346981Scy if (!ctrl_conn) 169346981Scy return -1; 170346981Scy if (!interactive && !action_file) 171346981Scy return 0; 172346981Scy if (wpa_ctrl_attach(ctrl_conn) == 0) { 173346981Scy hostapd_cli_attached = 1; 174346981Scy register_event_handler(ctrl_conn); 175346981Scy update_stations(ctrl_conn); 176346981Scy } else { 177346981Scy printf("Warning: Failed to attach to hostapd.\n"); 178346981Scy } 179346981Scy return 0; 180346981Scy} 181346981Scy 182346981Scy 183214503Srpaulostatic void hostapd_cli_msg_cb(char *msg, size_t len) 184214503Srpaulo{ 185346981Scy cli_event(msg); 186214503Srpaulo printf("%s\n", msg); 187214503Srpaulo} 188214503Srpaulo 189214503Srpaulo 190346981Scystatic int _wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd, int print) 191214503Srpaulo{ 192214503Srpaulo char buf[4096]; 193214503Srpaulo size_t len; 194214503Srpaulo int ret; 195214503Srpaulo 196214503Srpaulo if (ctrl_conn == NULL) { 197214503Srpaulo printf("Not connected to hostapd - command dropped.\n"); 198214503Srpaulo return -1; 199214503Srpaulo } 200214503Srpaulo len = sizeof(buf) - 1; 201214503Srpaulo ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, 202214503Srpaulo hostapd_cli_msg_cb); 203214503Srpaulo if (ret == -2) { 204214503Srpaulo printf("'%s' command timed out.\n", cmd); 205214503Srpaulo return -2; 206214503Srpaulo } else if (ret < 0) { 207214503Srpaulo printf("'%s' command failed.\n", cmd); 208214503Srpaulo return -1; 209214503Srpaulo } 210214503Srpaulo if (print) { 211214503Srpaulo buf[len] = '\0'; 212214503Srpaulo printf("%s", buf); 213214503Srpaulo } 214214503Srpaulo return 0; 215214503Srpaulo} 216214503Srpaulo 217214503Srpaulo 218346981Scystatic inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, const char *cmd) 219214503Srpaulo{ 220214503Srpaulo return _wpa_ctrl_command(ctrl, cmd, 1); 221214503Srpaulo} 222214503Srpaulo 223214503Srpaulo 224337817Scystatic int hostapd_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, 225337817Scy int min_args, int argc, char *argv[]) 226337817Scy{ 227337817Scy char buf[4096]; 228337817Scy 229337817Scy if (argc < min_args) { 230337817Scy printf("Invalid %s command - at least %d argument%s required.\n", 231337817Scy cmd, min_args, min_args > 1 ? "s are" : " is"); 232337817Scy return -1; 233337817Scy } 234337817Scy if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0) 235337817Scy return -1; 236337817Scy return wpa_ctrl_command(ctrl, buf); 237337817Scy} 238337817Scy 239337817Scy 240214503Srpaulostatic int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) 241214503Srpaulo{ 242214503Srpaulo return wpa_ctrl_command(ctrl, "PING"); 243214503Srpaulo} 244214503Srpaulo 245214503Srpaulo 246252726Srpaulostatic int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[]) 247252726Srpaulo{ 248252726Srpaulo return wpa_ctrl_command(ctrl, "RELOG"); 249252726Srpaulo} 250252726Srpaulo 251252726Srpaulo 252281806Srpaulostatic int hostapd_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) 253281806Srpaulo{ 254281806Srpaulo if (argc > 0 && os_strcmp(argv[0], "driver") == 0) 255281806Srpaulo return wpa_ctrl_command(ctrl, "STATUS-DRIVER"); 256281806Srpaulo return wpa_ctrl_command(ctrl, "STATUS"); 257281806Srpaulo} 258281806Srpaulo 259281806Srpaulo 260214503Srpaulostatic int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) 261214503Srpaulo{ 262281806Srpaulo if (argc > 0) { 263281806Srpaulo char buf[100]; 264281806Srpaulo os_snprintf(buf, sizeof(buf), "MIB %s", argv[0]); 265281806Srpaulo return wpa_ctrl_command(ctrl, buf); 266281806Srpaulo } 267214503Srpaulo return wpa_ctrl_command(ctrl, "MIB"); 268214503Srpaulo} 269214503Srpaulo 270214503Srpaulo 271214503Srpaulostatic int hostapd_cli_exec(const char *program, const char *arg1, 272214503Srpaulo const char *arg2) 273214503Srpaulo{ 274281806Srpaulo char *arg; 275214503Srpaulo size_t len; 276214503Srpaulo int res; 277214503Srpaulo 278281806Srpaulo len = os_strlen(arg1) + os_strlen(arg2) + 2; 279281806Srpaulo arg = os_malloc(len); 280281806Srpaulo if (arg == NULL) 281214503Srpaulo return -1; 282281806Srpaulo os_snprintf(arg, len, "%s %s", arg1, arg2); 283281806Srpaulo res = os_exec(program, arg, 1); 284281806Srpaulo os_free(arg); 285214503Srpaulo 286281806Srpaulo return res; 287214503Srpaulo} 288214503Srpaulo 289214503Srpaulo 290214503Srpaulostatic void hostapd_cli_action_process(char *msg, size_t len) 291214503Srpaulo{ 292214503Srpaulo const char *pos; 293214503Srpaulo 294214503Srpaulo pos = msg; 295214503Srpaulo if (*pos == '<') { 296214503Srpaulo pos = os_strchr(pos, '>'); 297214503Srpaulo if (pos) 298214503Srpaulo pos++; 299214503Srpaulo else 300214503Srpaulo pos = msg; 301214503Srpaulo } 302214503Srpaulo 303214503Srpaulo hostapd_cli_exec(action_file, ctrl_ifname, pos); 304214503Srpaulo} 305214503Srpaulo 306214503Srpaulo 307214503Srpaulostatic int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) 308214503Srpaulo{ 309214503Srpaulo char buf[64]; 310281806Srpaulo if (argc < 1) { 311281806Srpaulo printf("Invalid 'sta' command - at least one argument, STA " 312214503Srpaulo "address, is required.\n"); 313214503Srpaulo return -1; 314214503Srpaulo } 315281806Srpaulo if (argc > 1) 316281806Srpaulo snprintf(buf, sizeof(buf), "STA %s %s", argv[0], argv[1]); 317281806Srpaulo else 318281806Srpaulo snprintf(buf, sizeof(buf), "STA %s", argv[0]); 319214503Srpaulo return wpa_ctrl_command(ctrl, buf); 320214503Srpaulo} 321214503Srpaulo 322214503Srpaulo 323346981Scystatic char ** hostapd_complete_stations(const char *str, int pos) 324346981Scy{ 325346981Scy int arg = get_cmd_arg_num(str, pos); 326346981Scy char **res = NULL; 327346981Scy 328346981Scy switch (arg) { 329346981Scy case 1: 330346981Scy res = cli_txt_list_array(&stations); 331346981Scy break; 332346981Scy } 333346981Scy 334346981Scy return res; 335346981Scy} 336346981Scy 337346981Scy 338214503Srpaulostatic int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc, 339214503Srpaulo char *argv[]) 340214503Srpaulo{ 341214503Srpaulo char buf[64]; 342214503Srpaulo if (argc != 1) { 343214503Srpaulo printf("Invalid 'new_sta' command - exactly one argument, STA " 344214503Srpaulo "address, is required.\n"); 345214503Srpaulo return -1; 346214503Srpaulo } 347214503Srpaulo snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]); 348214503Srpaulo return wpa_ctrl_command(ctrl, buf); 349214503Srpaulo} 350214503Srpaulo 351214503Srpaulo 352214503Srpaulostatic int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc, 353214503Srpaulo char *argv[]) 354214503Srpaulo{ 355214503Srpaulo char buf[64]; 356214503Srpaulo if (argc < 1) { 357214503Srpaulo printf("Invalid 'deauthenticate' command - exactly one " 358214503Srpaulo "argument, STA address, is required.\n"); 359214503Srpaulo return -1; 360214503Srpaulo } 361214503Srpaulo if (argc > 1) 362214503Srpaulo os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s", 363214503Srpaulo argv[0], argv[1]); 364214503Srpaulo else 365214503Srpaulo os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]); 366214503Srpaulo return wpa_ctrl_command(ctrl, buf); 367214503Srpaulo} 368214503Srpaulo 369214503Srpaulo 370214503Srpaulostatic int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc, 371214503Srpaulo char *argv[]) 372214503Srpaulo{ 373214503Srpaulo char buf[64]; 374214503Srpaulo if (argc < 1) { 375214503Srpaulo printf("Invalid 'disassociate' command - exactly one " 376214503Srpaulo "argument, STA address, is required.\n"); 377214503Srpaulo return -1; 378214503Srpaulo } 379214503Srpaulo if (argc > 1) 380214503Srpaulo os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s", 381214503Srpaulo argv[0], argv[1]); 382214503Srpaulo else 383214503Srpaulo os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]); 384214503Srpaulo return wpa_ctrl_command(ctrl, buf); 385214503Srpaulo} 386214503Srpaulo 387214503Srpaulo 388337817Scy#ifdef CONFIG_TAXONOMY 389337817Scystatic int hostapd_cli_cmd_signature(struct wpa_ctrl *ctrl, int argc, 390337817Scy char *argv[]) 391337817Scy{ 392337817Scy char buf[64]; 393337817Scy 394337817Scy if (argc != 1) { 395337817Scy printf("Invalid 'signature' command - exactly one argument, STA address, is required.\n"); 396337817Scy return -1; 397337817Scy } 398337817Scy os_snprintf(buf, sizeof(buf), "SIGNATURE %s", argv[0]); 399337817Scy return wpa_ctrl_command(ctrl, buf); 400337817Scy} 401337817Scy#endif /* CONFIG_TAXONOMY */ 402337817Scy 403337817Scy 404214503Srpaulo#ifdef CONFIG_IEEE80211W 405214503Srpaulostatic int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc, 406214503Srpaulo char *argv[]) 407214503Srpaulo{ 408214503Srpaulo char buf[64]; 409214503Srpaulo if (argc != 1) { 410214503Srpaulo printf("Invalid 'sa_query' command - exactly one argument, " 411214503Srpaulo "STA address, is required.\n"); 412214503Srpaulo return -1; 413214503Srpaulo } 414214503Srpaulo snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]); 415214503Srpaulo return wpa_ctrl_command(ctrl, buf); 416214503Srpaulo} 417214503Srpaulo#endif /* CONFIG_IEEE80211W */ 418214503Srpaulo 419214503Srpaulo 420214503Srpaulo#ifdef CONFIG_WPS 421214503Srpaulostatic int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, 422214503Srpaulo char *argv[]) 423214503Srpaulo{ 424252726Srpaulo char buf[256]; 425214503Srpaulo if (argc < 2) { 426214503Srpaulo printf("Invalid 'wps_pin' command - at least two arguments, " 427214503Srpaulo "UUID and PIN, are required.\n"); 428214503Srpaulo return -1; 429214503Srpaulo } 430252726Srpaulo if (argc > 3) 431252726Srpaulo snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s", 432252726Srpaulo argv[0], argv[1], argv[2], argv[3]); 433252726Srpaulo else if (argc > 2) 434214503Srpaulo snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s", 435214503Srpaulo argv[0], argv[1], argv[2]); 436214503Srpaulo else 437214503Srpaulo snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]); 438214503Srpaulo return wpa_ctrl_command(ctrl, buf); 439214503Srpaulo} 440214503Srpaulo 441214503Srpaulo 442252726Srpaulostatic int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc, 443252726Srpaulo char *argv[]) 444252726Srpaulo{ 445252726Srpaulo char cmd[256]; 446252726Srpaulo int res; 447252726Srpaulo 448252726Srpaulo if (argc != 1 && argc != 2) { 449252726Srpaulo printf("Invalid WPS_CHECK_PIN command: needs one argument:\n" 450252726Srpaulo "- PIN to be verified\n"); 451252726Srpaulo return -1; 452252726Srpaulo } 453252726Srpaulo 454252726Srpaulo if (argc == 2) 455252726Srpaulo res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s", 456252726Srpaulo argv[0], argv[1]); 457252726Srpaulo else 458252726Srpaulo res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s", 459252726Srpaulo argv[0]); 460281806Srpaulo if (os_snprintf_error(sizeof(cmd), res)) { 461252726Srpaulo printf("Too long WPS_CHECK_PIN command.\n"); 462252726Srpaulo return -1; 463252726Srpaulo } 464252726Srpaulo return wpa_ctrl_command(ctrl, cmd); 465252726Srpaulo} 466252726Srpaulo 467252726Srpaulo 468214503Srpaulostatic int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, 469214503Srpaulo char *argv[]) 470214503Srpaulo{ 471214503Srpaulo return wpa_ctrl_command(ctrl, "WPS_PBC"); 472214503Srpaulo} 473214503Srpaulo 474214503Srpaulo 475252726Srpaulostatic int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc, 476252726Srpaulo char *argv[]) 477214503Srpaulo{ 478252726Srpaulo return wpa_ctrl_command(ctrl, "WPS_CANCEL"); 479252726Srpaulo} 480252726Srpaulo 481252726Srpaulo 482252726Srpaulo#ifdef CONFIG_WPS_NFC 483252726Srpaulostatic int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc, 484252726Srpaulo char *argv[]) 485252726Srpaulo{ 486252726Srpaulo int ret; 487252726Srpaulo char *buf; 488252726Srpaulo size_t buflen; 489252726Srpaulo 490252726Srpaulo if (argc != 1) { 491252726Srpaulo printf("Invalid 'wps_nfc_tag_read' command - one argument " 492252726Srpaulo "is required.\n"); 493252726Srpaulo return -1; 494252726Srpaulo } 495252726Srpaulo 496252726Srpaulo buflen = 18 + os_strlen(argv[0]); 497252726Srpaulo buf = os_malloc(buflen); 498252726Srpaulo if (buf == NULL) 499252726Srpaulo return -1; 500252726Srpaulo os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]); 501252726Srpaulo 502252726Srpaulo ret = wpa_ctrl_command(ctrl, buf); 503252726Srpaulo os_free(buf); 504252726Srpaulo 505252726Srpaulo return ret; 506252726Srpaulo} 507252726Srpaulo 508252726Srpaulo 509252726Srpaulostatic int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl, 510252726Srpaulo int argc, char *argv[]) 511252726Srpaulo{ 512252726Srpaulo char cmd[64]; 513214503Srpaulo int res; 514214503Srpaulo 515252726Srpaulo if (argc != 1) { 516252726Srpaulo printf("Invalid 'wps_nfc_config_token' command - one argument " 517252726Srpaulo "is required.\n"); 518214503Srpaulo return -1; 519214503Srpaulo } 520214503Srpaulo 521252726Srpaulo res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s", 522252726Srpaulo argv[0]); 523281806Srpaulo if (os_snprintf_error(sizeof(cmd), res)) { 524252726Srpaulo printf("Too long WPS_NFC_CONFIG_TOKEN command.\n"); 525214503Srpaulo return -1; 526214503Srpaulo } 527214503Srpaulo return wpa_ctrl_command(ctrl, cmd); 528214503Srpaulo} 529214503Srpaulo 530214503Srpaulo 531252726Srpaulostatic int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, 532252726Srpaulo int argc, char *argv[]) 533252726Srpaulo{ 534252726Srpaulo char cmd[64]; 535252726Srpaulo int res; 536252726Srpaulo 537252726Srpaulo if (argc != 1) { 538252726Srpaulo printf("Invalid 'wps_nfc_token' command - one argument is " 539252726Srpaulo "required.\n"); 540252726Srpaulo return -1; 541252726Srpaulo } 542252726Srpaulo 543252726Srpaulo res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]); 544281806Srpaulo if (os_snprintf_error(sizeof(cmd), res)) { 545252726Srpaulo printf("Too long WPS_NFC_TOKEN command.\n"); 546252726Srpaulo return -1; 547252726Srpaulo } 548252726Srpaulo return wpa_ctrl_command(ctrl, cmd); 549252726Srpaulo} 550281806Srpaulo 551281806Srpaulo 552281806Srpaulostatic int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, 553281806Srpaulo int argc, char *argv[]) 554281806Srpaulo{ 555281806Srpaulo char cmd[64]; 556281806Srpaulo int res; 557281806Srpaulo 558281806Srpaulo if (argc != 2) { 559281806Srpaulo printf("Invalid 'nfc_get_handover_sel' command - two arguments " 560281806Srpaulo "are required.\n"); 561281806Srpaulo return -1; 562281806Srpaulo } 563281806Srpaulo 564281806Srpaulo res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s", 565281806Srpaulo argv[0], argv[1]); 566281806Srpaulo if (os_snprintf_error(sizeof(cmd), res)) { 567281806Srpaulo printf("Too long NFC_GET_HANDOVER_SEL command.\n"); 568281806Srpaulo return -1; 569281806Srpaulo } 570281806Srpaulo return wpa_ctrl_command(ctrl, cmd); 571281806Srpaulo} 572281806Srpaulo 573252726Srpaulo#endif /* CONFIG_WPS_NFC */ 574252726Srpaulo 575252726Srpaulo 576214503Srpaulostatic int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc, 577214503Srpaulo char *argv[]) 578214503Srpaulo{ 579214503Srpaulo char buf[64]; 580214503Srpaulo if (argc < 1) { 581214503Srpaulo printf("Invalid 'wps_ap_pin' command - at least one argument " 582214503Srpaulo "is required.\n"); 583214503Srpaulo return -1; 584214503Srpaulo } 585214503Srpaulo if (argc > 2) 586214503Srpaulo snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s", 587214503Srpaulo argv[0], argv[1], argv[2]); 588214503Srpaulo else if (argc > 1) 589214503Srpaulo snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s", 590214503Srpaulo argv[0], argv[1]); 591214503Srpaulo else 592214503Srpaulo snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]); 593214503Srpaulo return wpa_ctrl_command(ctrl, buf); 594214503Srpaulo} 595252726Srpaulo 596252726Srpaulo 597281806Srpaulostatic int hostapd_cli_cmd_wps_get_status(struct wpa_ctrl *ctrl, int argc, 598281806Srpaulo char *argv[]) 599281806Srpaulo{ 600281806Srpaulo return wpa_ctrl_command(ctrl, "WPS_GET_STATUS"); 601281806Srpaulo} 602281806Srpaulo 603281806Srpaulo 604252726Srpaulostatic int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc, 605252726Srpaulo char *argv[]) 606252726Srpaulo{ 607252726Srpaulo char buf[256]; 608289549Srpaulo char ssid_hex[2 * SSID_MAX_LEN + 1]; 609252726Srpaulo char key_hex[2 * 64 + 1]; 610252726Srpaulo int i; 611252726Srpaulo 612252726Srpaulo if (argc < 1) { 613252726Srpaulo printf("Invalid 'wps_config' command - at least two arguments " 614252726Srpaulo "are required.\n"); 615252726Srpaulo return -1; 616252726Srpaulo } 617252726Srpaulo 618252726Srpaulo ssid_hex[0] = '\0'; 619289549Srpaulo for (i = 0; i < SSID_MAX_LEN; i++) { 620252726Srpaulo if (argv[0][i] == '\0') 621252726Srpaulo break; 622252726Srpaulo os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]); 623252726Srpaulo } 624252726Srpaulo 625252726Srpaulo key_hex[0] = '\0'; 626252726Srpaulo if (argc > 3) { 627252726Srpaulo for (i = 0; i < 64; i++) { 628252726Srpaulo if (argv[3][i] == '\0') 629252726Srpaulo break; 630252726Srpaulo os_snprintf(&key_hex[i * 2], 3, "%02x", 631252726Srpaulo argv[3][i]); 632252726Srpaulo } 633252726Srpaulo } 634252726Srpaulo 635252726Srpaulo if (argc > 3) 636252726Srpaulo snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s", 637252726Srpaulo ssid_hex, argv[1], argv[2], key_hex); 638252726Srpaulo else if (argc > 2) 639252726Srpaulo snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s", 640252726Srpaulo ssid_hex, argv[1], argv[2]); 641252726Srpaulo else 642252726Srpaulo snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s", 643252726Srpaulo ssid_hex, argv[1]); 644252726Srpaulo return wpa_ctrl_command(ctrl, buf); 645252726Srpaulo} 646214503Srpaulo#endif /* CONFIG_WPS */ 647214503Srpaulo 648214503Srpaulo 649252726Srpaulostatic int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc, 650252726Srpaulo char *argv[]) 651252726Srpaulo{ 652252726Srpaulo char buf[300]; 653252726Srpaulo int res; 654252726Srpaulo 655252726Srpaulo if (argc < 2) { 656252726Srpaulo printf("Invalid 'disassoc_imminent' command - two arguments " 657252726Srpaulo "(STA addr and Disassociation Timer) are needed\n"); 658252726Srpaulo return -1; 659252726Srpaulo } 660252726Srpaulo 661252726Srpaulo res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s", 662252726Srpaulo argv[0], argv[1]); 663281806Srpaulo if (os_snprintf_error(sizeof(buf), res)) 664252726Srpaulo return -1; 665252726Srpaulo return wpa_ctrl_command(ctrl, buf); 666252726Srpaulo} 667252726Srpaulo 668252726Srpaulo 669252726Srpaulostatic int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc, 670252726Srpaulo char *argv[]) 671252726Srpaulo{ 672252726Srpaulo char buf[300]; 673252726Srpaulo int res; 674252726Srpaulo 675281806Srpaulo if (argc < 3) { 676281806Srpaulo printf("Invalid 'ess_disassoc' command - three arguments (STA " 677281806Srpaulo "addr, disassoc timer, and URL) are needed\n"); 678252726Srpaulo return -1; 679252726Srpaulo } 680252726Srpaulo 681281806Srpaulo res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s %s", 682281806Srpaulo argv[0], argv[1], argv[2]); 683281806Srpaulo if (os_snprintf_error(sizeof(buf), res)) 684252726Srpaulo return -1; 685252726Srpaulo return wpa_ctrl_command(ctrl, buf); 686252726Srpaulo} 687252726Srpaulo 688252726Srpaulo 689281806Srpaulostatic int hostapd_cli_cmd_bss_tm_req(struct wpa_ctrl *ctrl, int argc, 690281806Srpaulo char *argv[]) 691281806Srpaulo{ 692281806Srpaulo char buf[2000], *tmp; 693281806Srpaulo int res, i, total; 694281806Srpaulo 695281806Srpaulo if (argc < 1) { 696281806Srpaulo printf("Invalid 'bss_tm_req' command - at least one argument (STA addr) is needed\n"); 697281806Srpaulo return -1; 698281806Srpaulo } 699281806Srpaulo 700281806Srpaulo res = os_snprintf(buf, sizeof(buf), "BSS_TM_REQ %s", argv[0]); 701281806Srpaulo if (os_snprintf_error(sizeof(buf), res)) 702281806Srpaulo return -1; 703281806Srpaulo 704281806Srpaulo total = res; 705281806Srpaulo for (i = 1; i < argc; i++) { 706281806Srpaulo tmp = &buf[total]; 707281806Srpaulo res = os_snprintf(tmp, sizeof(buf) - total, " %s", argv[i]); 708281806Srpaulo if (os_snprintf_error(sizeof(buf) - total, res)) 709281806Srpaulo return -1; 710281806Srpaulo total += res; 711281806Srpaulo } 712281806Srpaulo return wpa_ctrl_command(ctrl, buf); 713281806Srpaulo} 714281806Srpaulo 715281806Srpaulo 716252726Srpaulostatic int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc, 717252726Srpaulo char *argv[]) 718252726Srpaulo{ 719252726Srpaulo return wpa_ctrl_command(ctrl, "GET_CONFIG"); 720252726Srpaulo} 721252726Srpaulo 722252726Srpaulo 723346981Scystatic int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, const char *cmd, 724346981Scy char *addr, size_t addr_len, int print) 725214503Srpaulo{ 726214503Srpaulo char buf[4096], *pos; 727214503Srpaulo size_t len; 728214503Srpaulo int ret; 729214503Srpaulo 730214503Srpaulo if (ctrl_conn == NULL) { 731214503Srpaulo printf("Not connected to hostapd - command dropped.\n"); 732214503Srpaulo return -1; 733214503Srpaulo } 734214503Srpaulo len = sizeof(buf) - 1; 735214503Srpaulo ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len, 736214503Srpaulo hostapd_cli_msg_cb); 737214503Srpaulo if (ret == -2) { 738214503Srpaulo printf("'%s' command timed out.\n", cmd); 739214503Srpaulo return -2; 740214503Srpaulo } else if (ret < 0) { 741214503Srpaulo printf("'%s' command failed.\n", cmd); 742214503Srpaulo return -1; 743214503Srpaulo } 744214503Srpaulo 745214503Srpaulo buf[len] = '\0'; 746214503Srpaulo if (memcmp(buf, "FAIL", 4) == 0) 747214503Srpaulo return -1; 748346981Scy if (print) 749346981Scy printf("%s", buf); 750214503Srpaulo 751214503Srpaulo pos = buf; 752214503Srpaulo while (*pos != '\0' && *pos != '\n') 753214503Srpaulo pos++; 754214503Srpaulo *pos = '\0'; 755214503Srpaulo os_strlcpy(addr, buf, addr_len); 756214503Srpaulo return 0; 757214503Srpaulo} 758214503Srpaulo 759214503Srpaulo 760214503Srpaulostatic int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, 761214503Srpaulo char *argv[]) 762214503Srpaulo{ 763214503Srpaulo char addr[32], cmd[64]; 764214503Srpaulo 765346981Scy if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 1)) 766214503Srpaulo return 0; 767214503Srpaulo do { 768214503Srpaulo snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); 769346981Scy } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 1) == 0); 770214503Srpaulo 771214503Srpaulo return -1; 772214503Srpaulo} 773214503Srpaulo 774214503Srpaulo 775346981Scystatic int hostapd_cli_cmd_list_sta(struct wpa_ctrl *ctrl, int argc, 776346981Scy char *argv[]) 777346981Scy{ 778346981Scy char addr[32], cmd[64]; 779346981Scy 780346981Scy if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 0)) 781346981Scy return 0; 782346981Scy do { 783346981Scy if (os_strcmp(addr, "") != 0) 784346981Scy printf("%s\n", addr); 785346981Scy os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); 786346981Scy } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 0) == 0); 787346981Scy 788346981Scy return 0; 789346981Scy} 790346981Scy 791346981Scy 792214503Srpaulostatic int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) 793214503Srpaulo{ 794337817Scy print_help(stdout, argc > 0 ? argv[0] : NULL); 795214503Srpaulo return 0; 796214503Srpaulo} 797214503Srpaulo 798214503Srpaulo 799337817Scystatic char ** hostapd_cli_complete_help(const char *str, int pos) 800337817Scy{ 801337817Scy int arg = get_cmd_arg_num(str, pos); 802337817Scy char **res = NULL; 803337817Scy 804337817Scy switch (arg) { 805337817Scy case 1: 806337817Scy res = list_cmd_list(); 807337817Scy break; 808337817Scy } 809337817Scy 810337817Scy return res; 811337817Scy} 812337817Scy 813337817Scy 814214503Srpaulostatic int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, 815214503Srpaulo char *argv[]) 816214503Srpaulo{ 817337817Scy printf("%s\n\n%s\n", hostapd_cli_version, cli_full_license); 818214503Srpaulo return 0; 819214503Srpaulo} 820214503Srpaulo 821214503Srpaulo 822281806Srpaulostatic int hostapd_cli_cmd_set_qos_map_set(struct wpa_ctrl *ctrl, 823281806Srpaulo int argc, char *argv[]) 824281806Srpaulo{ 825281806Srpaulo char buf[200]; 826281806Srpaulo int res; 827281806Srpaulo 828281806Srpaulo if (argc != 1) { 829281806Srpaulo printf("Invalid 'set_qos_map_set' command - " 830281806Srpaulo "one argument (comma delimited QoS map set) " 831281806Srpaulo "is needed\n"); 832281806Srpaulo return -1; 833281806Srpaulo } 834281806Srpaulo 835281806Srpaulo res = os_snprintf(buf, sizeof(buf), "SET_QOS_MAP_SET %s", argv[0]); 836281806Srpaulo if (os_snprintf_error(sizeof(buf), res)) 837281806Srpaulo return -1; 838281806Srpaulo return wpa_ctrl_command(ctrl, buf); 839281806Srpaulo} 840281806Srpaulo 841281806Srpaulo 842281806Srpaulostatic int hostapd_cli_cmd_send_qos_map_conf(struct wpa_ctrl *ctrl, 843281806Srpaulo int argc, char *argv[]) 844281806Srpaulo{ 845281806Srpaulo char buf[50]; 846281806Srpaulo int res; 847281806Srpaulo 848281806Srpaulo if (argc != 1) { 849281806Srpaulo printf("Invalid 'send_qos_map_conf' command - " 850281806Srpaulo "one argument (STA addr) is needed\n"); 851281806Srpaulo return -1; 852281806Srpaulo } 853281806Srpaulo 854281806Srpaulo res = os_snprintf(buf, sizeof(buf), "SEND_QOS_MAP_CONF %s", argv[0]); 855281806Srpaulo if (os_snprintf_error(sizeof(buf), res)) 856281806Srpaulo return -1; 857281806Srpaulo return wpa_ctrl_command(ctrl, buf); 858281806Srpaulo} 859281806Srpaulo 860281806Srpaulo 861281806Srpaulostatic int hostapd_cli_cmd_hs20_wnm_notif(struct wpa_ctrl *ctrl, int argc, 862281806Srpaulo char *argv[]) 863281806Srpaulo{ 864281806Srpaulo char buf[300]; 865281806Srpaulo int res; 866281806Srpaulo 867281806Srpaulo if (argc < 2) { 868281806Srpaulo printf("Invalid 'hs20_wnm_notif' command - two arguments (STA " 869281806Srpaulo "addr and URL) are needed\n"); 870281806Srpaulo return -1; 871281806Srpaulo } 872281806Srpaulo 873281806Srpaulo res = os_snprintf(buf, sizeof(buf), "HS20_WNM_NOTIF %s %s", 874281806Srpaulo argv[0], argv[1]); 875281806Srpaulo if (os_snprintf_error(sizeof(buf), res)) 876281806Srpaulo return -1; 877281806Srpaulo return wpa_ctrl_command(ctrl, buf); 878281806Srpaulo} 879281806Srpaulo 880281806Srpaulo 881281806Srpaulostatic int hostapd_cli_cmd_hs20_deauth_req(struct wpa_ctrl *ctrl, int argc, 882281806Srpaulo char *argv[]) 883281806Srpaulo{ 884281806Srpaulo char buf[300]; 885281806Srpaulo int res; 886281806Srpaulo 887281806Srpaulo if (argc < 3) { 888281806Srpaulo printf("Invalid 'hs20_deauth_req' command - at least three arguments (STA addr, Code, Re-auth Delay) are needed\n"); 889281806Srpaulo return -1; 890281806Srpaulo } 891281806Srpaulo 892281806Srpaulo if (argc > 3) 893281806Srpaulo res = os_snprintf(buf, sizeof(buf), 894281806Srpaulo "HS20_DEAUTH_REQ %s %s %s %s", 895281806Srpaulo argv[0], argv[1], argv[2], argv[3]); 896281806Srpaulo else 897281806Srpaulo res = os_snprintf(buf, sizeof(buf), 898281806Srpaulo "HS20_DEAUTH_REQ %s %s %s", 899281806Srpaulo argv[0], argv[1], argv[2]); 900281806Srpaulo if (os_snprintf_error(sizeof(buf), res)) 901281806Srpaulo return -1; 902281806Srpaulo return wpa_ctrl_command(ctrl, buf); 903281806Srpaulo} 904281806Srpaulo 905281806Srpaulo 906214503Srpaulostatic int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) 907214503Srpaulo{ 908214503Srpaulo hostapd_cli_quit = 1; 909252726Srpaulo if (interactive) 910252726Srpaulo eloop_terminate(); 911214503Srpaulo return 0; 912214503Srpaulo} 913214503Srpaulo 914214503Srpaulo 915214503Srpaulostatic int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) 916214503Srpaulo{ 917214503Srpaulo char cmd[256]; 918214503Srpaulo if (argc != 1) { 919214503Srpaulo printf("Invalid LEVEL command: needs one argument (debug " 920214503Srpaulo "level)\n"); 921214503Srpaulo return 0; 922214503Srpaulo } 923214503Srpaulo snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]); 924214503Srpaulo return wpa_ctrl_command(ctrl, cmd); 925214503Srpaulo} 926214503Srpaulo 927214503Srpaulo 928346981Scystatic void update_stations(struct wpa_ctrl *ctrl) 929346981Scy{ 930346981Scy char addr[32], cmd[64]; 931346981Scy 932346981Scy if (!ctrl || !interactive) 933346981Scy return; 934346981Scy 935346981Scy cli_txt_list_flush(&stations); 936346981Scy 937346981Scy if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr), 0)) 938346981Scy return; 939346981Scy do { 940346981Scy if (os_strcmp(addr, "") != 0) 941346981Scy cli_txt_list_add(&stations, addr); 942346981Scy os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); 943346981Scy } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr), 0) == 0); 944346981Scy} 945346981Scy 946346981Scy 947337817Scystatic void hostapd_cli_get_interfaces(struct wpa_ctrl *ctrl, 948337817Scy struct dl_list *interfaces) 949337817Scy{ 950337817Scy struct dirent *dent; 951337817Scy DIR *dir; 952337817Scy 953337817Scy if (!ctrl || !interfaces) 954337817Scy return; 955337817Scy dir = opendir(ctrl_iface_dir); 956337817Scy if (dir == NULL) 957337817Scy return; 958337817Scy 959337817Scy while ((dent = readdir(dir))) { 960337817Scy if (strcmp(dent->d_name, ".") == 0 || 961337817Scy strcmp(dent->d_name, "..") == 0) 962337817Scy continue; 963337817Scy cli_txt_list_add(interfaces, dent->d_name); 964337817Scy } 965337817Scy closedir(dir); 966337817Scy} 967337817Scy 968337817Scy 969214503Srpaulostatic void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl) 970214503Srpaulo{ 971214503Srpaulo struct dirent *dent; 972214503Srpaulo DIR *dir; 973214503Srpaulo 974214503Srpaulo dir = opendir(ctrl_iface_dir); 975214503Srpaulo if (dir == NULL) { 976214503Srpaulo printf("Control interface directory '%s' could not be " 977214503Srpaulo "openned.\n", ctrl_iface_dir); 978214503Srpaulo return; 979214503Srpaulo } 980214503Srpaulo 981214503Srpaulo printf("Available interfaces:\n"); 982214503Srpaulo while ((dent = readdir(dir))) { 983214503Srpaulo if (strcmp(dent->d_name, ".") == 0 || 984214503Srpaulo strcmp(dent->d_name, "..") == 0) 985214503Srpaulo continue; 986214503Srpaulo printf("%s\n", dent->d_name); 987214503Srpaulo } 988214503Srpaulo closedir(dir); 989214503Srpaulo} 990214503Srpaulo 991214503Srpaulo 992214503Srpaulostatic int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, 993214503Srpaulo char *argv[]) 994214503Srpaulo{ 995214503Srpaulo if (argc < 1) { 996214503Srpaulo hostapd_cli_list_interfaces(ctrl); 997214503Srpaulo return 0; 998214503Srpaulo } 999346981Scy if (hostapd_cli_reconnect(argv[0]) != 0) { 1000214503Srpaulo printf("Could not connect to interface '%s' - re-trying\n", 1001214503Srpaulo ctrl_ifname); 1002214503Srpaulo } 1003214503Srpaulo return 0; 1004214503Srpaulo} 1005214503Srpaulo 1006214503Srpaulo 1007337817Scystatic char ** hostapd_complete_interface(const char *str, int pos) 1008337817Scy{ 1009337817Scy int arg = get_cmd_arg_num(str, pos); 1010337817Scy char **res = NULL; 1011337817Scy DEFINE_DL_LIST(interfaces); 1012337817Scy 1013337817Scy switch (arg) { 1014337817Scy case 1: 1015337817Scy hostapd_cli_get_interfaces(ctrl_conn, &interfaces); 1016337817Scy res = cli_txt_list_array(&interfaces); 1017337817Scy cli_txt_list_flush(&interfaces); 1018337817Scy break; 1019337817Scy } 1020337817Scy 1021337817Scy return res; 1022337817Scy} 1023337817Scy 1024337817Scy 1025252726Srpaulostatic int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1026252726Srpaulo{ 1027346981Scy char cmd[2048]; 1028252726Srpaulo int res; 1029252726Srpaulo 1030252726Srpaulo if (argc != 2) { 1031252726Srpaulo printf("Invalid SET command: needs two arguments (variable " 1032252726Srpaulo "name and value)\n"); 1033252726Srpaulo return -1; 1034252726Srpaulo } 1035252726Srpaulo 1036252726Srpaulo res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]); 1037281806Srpaulo if (os_snprintf_error(sizeof(cmd), res)) { 1038252726Srpaulo printf("Too long SET command.\n"); 1039252726Srpaulo return -1; 1040252726Srpaulo } 1041252726Srpaulo return wpa_ctrl_command(ctrl, cmd); 1042252726Srpaulo} 1043252726Srpaulo 1044252726Srpaulo 1045346981Scystatic char ** hostapd_complete_set(const char *str, int pos) 1046346981Scy{ 1047346981Scy int arg = get_cmd_arg_num(str, pos); 1048346981Scy const char *fields[] = { 1049346981Scy#ifdef CONFIG_WPS_TESTING 1050346981Scy "wps_version_number", "wps_testing_dummy_cred", 1051346981Scy "wps_corrupt_pkhash", 1052346981Scy#endif /* CONFIG_WPS_TESTING */ 1053346981Scy#ifdef CONFIG_INTERWORKING 1054346981Scy "gas_frag_limit", 1055346981Scy#endif /* CONFIG_INTERWORKING */ 1056346981Scy#ifdef CONFIG_TESTING_OPTIONS 1057346981Scy "ext_mgmt_frame_handling", "ext_eapol_frame_io", 1058346981Scy#endif /* CONFIG_TESTING_OPTIONS */ 1059346981Scy#ifdef CONFIG_MBO 1060346981Scy "mbo_assoc_disallow", 1061346981Scy#endif /* CONFIG_MBO */ 1062346981Scy "deny_mac_file", "accept_mac_file", 1063346981Scy }; 1064346981Scy int i, num_fields = ARRAY_SIZE(fields); 1065346981Scy 1066346981Scy if (arg == 1) { 1067346981Scy char **res; 1068346981Scy 1069346981Scy res = os_calloc(num_fields + 1, sizeof(char *)); 1070346981Scy if (!res) 1071346981Scy return NULL; 1072346981Scy for (i = 0; i < num_fields; i++) { 1073346981Scy res[i] = os_strdup(fields[i]); 1074346981Scy if (!res[i]) 1075346981Scy return res; 1076346981Scy } 1077346981Scy return res; 1078346981Scy } 1079346981Scy return NULL; 1080346981Scy} 1081346981Scy 1082346981Scy 1083252726Srpaulostatic int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1084252726Srpaulo{ 1085252726Srpaulo char cmd[256]; 1086252726Srpaulo int res; 1087252726Srpaulo 1088252726Srpaulo if (argc != 1) { 1089252726Srpaulo printf("Invalid GET command: needs one argument (variable " 1090252726Srpaulo "name)\n"); 1091252726Srpaulo return -1; 1092252726Srpaulo } 1093252726Srpaulo 1094252726Srpaulo res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]); 1095281806Srpaulo if (os_snprintf_error(sizeof(cmd), res)) { 1096252726Srpaulo printf("Too long GET command.\n"); 1097252726Srpaulo return -1; 1098252726Srpaulo } 1099252726Srpaulo return wpa_ctrl_command(ctrl, cmd); 1100252726Srpaulo} 1101252726Srpaulo 1102252726Srpaulo 1103346981Scystatic char ** hostapd_complete_get(const char *str, int pos) 1104346981Scy{ 1105346981Scy int arg = get_cmd_arg_num(str, pos); 1106346981Scy const char *fields[] = { 1107346981Scy "version", "tls_library", 1108346981Scy }; 1109346981Scy int i, num_fields = ARRAY_SIZE(fields); 1110346981Scy 1111346981Scy if (arg == 1) { 1112346981Scy char **res; 1113346981Scy 1114346981Scy res = os_calloc(num_fields + 1, sizeof(char *)); 1115346981Scy if (!res) 1116346981Scy return NULL; 1117346981Scy for (i = 0; i < num_fields; i++) { 1118346981Scy res[i] = os_strdup(fields[i]); 1119346981Scy if (!res[i]) 1120346981Scy return res; 1121346981Scy } 1122346981Scy return res; 1123346981Scy } 1124346981Scy return NULL; 1125346981Scy} 1126346981Scy 1127346981Scy 1128289549Srpaulo#ifdef CONFIG_FST 1129289549Srpaulostatic int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1130289549Srpaulo{ 1131289549Srpaulo char cmd[256]; 1132289549Srpaulo int res; 1133289549Srpaulo int i; 1134289549Srpaulo int total; 1135289549Srpaulo 1136289549Srpaulo if (argc <= 0) { 1137289549Srpaulo printf("FST command: parameters are required.\n"); 1138289549Srpaulo return -1; 1139289549Srpaulo } 1140289549Srpaulo 1141289549Srpaulo total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER"); 1142289549Srpaulo 1143289549Srpaulo for (i = 0; i < argc; i++) { 1144289549Srpaulo res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s", 1145289549Srpaulo argv[i]); 1146289549Srpaulo if (os_snprintf_error(sizeof(cmd) - total, res)) { 1147289549Srpaulo printf("Too long fst command.\n"); 1148289549Srpaulo return -1; 1149289549Srpaulo } 1150289549Srpaulo total += res; 1151289549Srpaulo } 1152289549Srpaulo return wpa_ctrl_command(ctrl, cmd); 1153289549Srpaulo} 1154289549Srpaulo#endif /* CONFIG_FST */ 1155289549Srpaulo 1156289549Srpaulo 1157281806Srpaulostatic int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl, 1158281806Srpaulo int argc, char *argv[]) 1159281806Srpaulo{ 1160281806Srpaulo char cmd[256]; 1161281806Srpaulo int res; 1162281806Srpaulo int i; 1163281806Srpaulo char *tmp; 1164281806Srpaulo int total; 1165281806Srpaulo 1166281806Srpaulo if (argc < 2) { 1167281806Srpaulo printf("Invalid chan_switch command: needs at least two " 1168281806Srpaulo "arguments (count and freq)\n" 1169281806Srpaulo "usage: <cs_count> <freq> [sec_channel_offset=] " 1170281806Srpaulo "[center_freq1=] [center_freq2=] [bandwidth=] " 1171281806Srpaulo "[blocktx] [ht|vht]\n"); 1172281806Srpaulo return -1; 1173281806Srpaulo } 1174281806Srpaulo 1175281806Srpaulo res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s", 1176281806Srpaulo argv[0], argv[1]); 1177281806Srpaulo if (os_snprintf_error(sizeof(cmd), res)) { 1178281806Srpaulo printf("Too long CHAN_SWITCH command.\n"); 1179281806Srpaulo return -1; 1180281806Srpaulo } 1181281806Srpaulo 1182281806Srpaulo total = res; 1183281806Srpaulo for (i = 2; i < argc; i++) { 1184281806Srpaulo tmp = cmd + total; 1185281806Srpaulo res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]); 1186281806Srpaulo if (os_snprintf_error(sizeof(cmd) - total, res)) { 1187281806Srpaulo printf("Too long CHAN_SWITCH command.\n"); 1188281806Srpaulo return -1; 1189281806Srpaulo } 1190281806Srpaulo total += res; 1191281806Srpaulo } 1192281806Srpaulo return wpa_ctrl_command(ctrl, cmd); 1193281806Srpaulo} 1194281806Srpaulo 1195281806Srpaulo 1196281806Srpaulostatic int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc, 1197281806Srpaulo char *argv[]) 1198281806Srpaulo{ 1199281806Srpaulo return wpa_ctrl_command(ctrl, "ENABLE"); 1200281806Srpaulo} 1201281806Srpaulo 1202281806Srpaulo 1203281806Srpaulostatic int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc, 1204281806Srpaulo char *argv[]) 1205281806Srpaulo{ 1206281806Srpaulo return wpa_ctrl_command(ctrl, "RELOAD"); 1207281806Srpaulo} 1208281806Srpaulo 1209281806Srpaulo 1210281806Srpaulostatic int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc, 1211281806Srpaulo char *argv[]) 1212281806Srpaulo{ 1213281806Srpaulo return wpa_ctrl_command(ctrl, "DISABLE"); 1214281806Srpaulo} 1215281806Srpaulo 1216281806Srpaulo 1217351611Scystatic int hostapd_cli_cmd_update_beacon(struct wpa_ctrl *ctrl, int argc, 1218351611Scy char *argv[]) 1219351611Scy{ 1220351611Scy return wpa_ctrl_command(ctrl, "UPDATE_BEACON"); 1221351611Scy} 1222351611Scy 1223351611Scy 1224281806Srpaulostatic int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1225281806Srpaulo{ 1226281806Srpaulo char cmd[256]; 1227281806Srpaulo int res; 1228281806Srpaulo 1229281806Srpaulo if (argc < 2 || argc > 3) { 1230281806Srpaulo printf("Invalid vendor command\n" 1231281806Srpaulo "usage: <vendor id> <command id> [<hex formatted command argument>]\n"); 1232281806Srpaulo return -1; 1233281806Srpaulo } 1234281806Srpaulo 1235281806Srpaulo res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1], 1236281806Srpaulo argc == 3 ? argv[2] : ""); 1237281806Srpaulo if (os_snprintf_error(sizeof(cmd), res)) { 1238281806Srpaulo printf("Too long VENDOR command.\n"); 1239281806Srpaulo return -1; 1240281806Srpaulo } 1241281806Srpaulo return wpa_ctrl_command(ctrl, cmd); 1242281806Srpaulo} 1243281806Srpaulo 1244281806Srpaulo 1245281806Srpaulostatic int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc, 1246281806Srpaulo char *argv[]) 1247281806Srpaulo{ 1248281806Srpaulo return wpa_ctrl_command(ctrl, "ERP_FLUSH"); 1249281806Srpaulo} 1250281806Srpaulo 1251281806Srpaulo 1252289549Srpaulostatic int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, 1253289549Srpaulo char *argv[]) 1254289549Srpaulo{ 1255289549Srpaulo char cmd[256]; 1256289549Srpaulo int res; 1257289549Srpaulo 1258289549Srpaulo res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s", 1259289549Srpaulo argc >= 1 ? " " : "", 1260289549Srpaulo argc >= 1 ? argv[0] : "", 1261289549Srpaulo argc == 2 ? " " : "", 1262289549Srpaulo argc == 2 ? argv[1] : ""); 1263289549Srpaulo if (os_snprintf_error(sizeof(cmd), res)) { 1264289549Srpaulo printf("Too long option\n"); 1265289549Srpaulo return -1; 1266289549Srpaulo } 1267289549Srpaulo return wpa_ctrl_command(ctrl, cmd); 1268289549Srpaulo} 1269289549Srpaulo 1270289549Srpaulo 1271337817Scystatic int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1272337817Scy{ 1273337817Scy if (argc == 0) 1274337817Scy return -1; 1275337817Scy return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]); 1276337817Scy} 1277337817Scy 1278337817Scy 1279337817Scystatic int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1280337817Scy{ 1281337817Scy return wpa_ctrl_command(ctrl, "PMKSA"); 1282337817Scy} 1283337817Scy 1284337817Scy 1285337817Scystatic int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc, 1286337817Scy char *argv[]) 1287337817Scy{ 1288337817Scy return wpa_ctrl_command(ctrl, "PMKSA_FLUSH"); 1289337817Scy} 1290337817Scy 1291337817Scy 1292337817Scystatic int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc, 1293337817Scy char *argv[]) 1294337817Scy{ 1295337817Scy char cmd[2048]; 1296337817Scy int res; 1297337817Scy 1298346981Scy if (argc < 3 || argc > 6) { 1299346981Scy printf("Invalid set_neighbor command: needs 3-6 arguments\n"); 1300337817Scy return -1; 1301337817Scy } 1302337817Scy 1303346981Scy res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s %s", 1304337817Scy argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "", 1305346981Scy argc >= 5 ? argv[4] : "", argc == 6 ? argv[5] : ""); 1306337817Scy if (os_snprintf_error(sizeof(cmd), res)) { 1307337817Scy printf("Too long SET_NEIGHBOR command.\n"); 1308337817Scy return -1; 1309337817Scy } 1310337817Scy return wpa_ctrl_command(ctrl, cmd); 1311337817Scy} 1312337817Scy 1313337817Scy 1314337817Scystatic int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc, 1315337817Scy char *argv[]) 1316337817Scy{ 1317337817Scy char cmd[400]; 1318337817Scy int res; 1319337817Scy 1320337817Scy if (argc != 2) { 1321337817Scy printf("Invalid remove_neighbor command: needs 2 arguments\n"); 1322337817Scy return -1; 1323337817Scy } 1324337817Scy 1325337817Scy res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s", 1326337817Scy argv[0], argv[1]); 1327337817Scy if (os_snprintf_error(sizeof(cmd), res)) { 1328337817Scy printf("Too long REMOVE_NEIGHBOR command.\n"); 1329337817Scy return -1; 1330337817Scy } 1331337817Scy return wpa_ctrl_command(ctrl, cmd); 1332337817Scy} 1333337817Scy 1334337817Scy 1335337817Scystatic int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc, 1336337817Scy char *argv[]) 1337337817Scy{ 1338337817Scy char cmd[256]; 1339337817Scy int res; 1340337817Scy 1341337817Scy if (argc != 1) { 1342337817Scy printf("Invalid req_lci command - requires destination address\n"); 1343337817Scy return -1; 1344337817Scy } 1345337817Scy 1346337817Scy res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]); 1347337817Scy if (os_snprintf_error(sizeof(cmd), res)) { 1348337817Scy printf("Too long REQ_LCI command.\n"); 1349337817Scy return -1; 1350337817Scy } 1351337817Scy return wpa_ctrl_command(ctrl, cmd); 1352337817Scy} 1353337817Scy 1354337817Scy 1355337817Scystatic int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc, 1356337817Scy char *argv[]) 1357337817Scy{ 1358337817Scy if (argc < 4) { 1359337817Scy printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n"); 1360337817Scy return -1; 1361337817Scy } 1362337817Scy 1363337817Scy return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv); 1364337817Scy} 1365337817Scy 1366337817Scy 1367337817Scystatic int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc, 1368337817Scy char *argv[]) 1369337817Scy{ 1370337817Scy return wpa_ctrl_command(ctrl, "DRIVER_FLAGS"); 1371337817Scy} 1372337817Scy 1373337817Scy 1374346981Scy#ifdef CONFIG_DPP 1375346981Scy 1376346981Scystatic int hostapd_cli_cmd_dpp_qr_code(struct wpa_ctrl *ctrl, int argc, 1377346981Scy char *argv[]) 1378346981Scy{ 1379346981Scy return hostapd_cli_cmd(ctrl, "DPP_QR_CODE", 1, argc, argv); 1380346981Scy} 1381346981Scy 1382346981Scy 1383346981Scystatic int hostapd_cli_cmd_dpp_bootstrap_gen(struct wpa_ctrl *ctrl, int argc, 1384346981Scy char *argv[]) 1385346981Scy{ 1386346981Scy return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_GEN", 1, argc, argv); 1387346981Scy} 1388346981Scy 1389346981Scy 1390346981Scystatic int hostapd_cli_cmd_dpp_bootstrap_remove(struct wpa_ctrl *ctrl, int argc, 1391346981Scy char *argv[]) 1392346981Scy{ 1393346981Scy return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_REMOVE", 1, argc, argv); 1394346981Scy} 1395346981Scy 1396346981Scy 1397346981Scystatic int hostapd_cli_cmd_dpp_bootstrap_get_uri(struct wpa_ctrl *ctrl, 1398346981Scy int argc, char *argv[]) 1399346981Scy{ 1400346981Scy return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_GET_URI", 1, argc, argv); 1401346981Scy} 1402346981Scy 1403346981Scy 1404346981Scystatic int hostapd_cli_cmd_dpp_bootstrap_info(struct wpa_ctrl *ctrl, int argc, 1405346981Scy char *argv[]) 1406346981Scy{ 1407346981Scy return hostapd_cli_cmd(ctrl, "DPP_BOOTSTRAP_INFO", 1, argc, argv); 1408346981Scy} 1409346981Scy 1410346981Scy 1411346981Scystatic int hostapd_cli_cmd_dpp_auth_init(struct wpa_ctrl *ctrl, int argc, 1412346981Scy char *argv[]) 1413346981Scy{ 1414346981Scy return hostapd_cli_cmd(ctrl, "DPP_AUTH_INIT", 1, argc, argv); 1415346981Scy} 1416346981Scy 1417346981Scy 1418346981Scystatic int hostapd_cli_cmd_dpp_listen(struct wpa_ctrl *ctrl, int argc, 1419346981Scy char *argv[]) 1420346981Scy{ 1421346981Scy return hostapd_cli_cmd(ctrl, "DPP_LISTEN", 1, argc, argv); 1422346981Scy} 1423346981Scy 1424346981Scy 1425346981Scystatic int hostapd_cli_cmd_dpp_stop_listen(struct wpa_ctrl *ctrl, int argc, 1426346981Scy char *argv[]) 1427346981Scy{ 1428346981Scy return wpa_ctrl_command(ctrl, "DPP_STOP_LISTEN"); 1429346981Scy} 1430346981Scy 1431346981Scy 1432346981Scystatic int hostapd_cli_cmd_dpp_configurator_add(struct wpa_ctrl *ctrl, int argc, 1433346981Scy char *argv[]) 1434346981Scy{ 1435346981Scy return hostapd_cli_cmd(ctrl, "DPP_CONFIGURATOR_ADD", 0, argc, argv); 1436346981Scy} 1437346981Scy 1438346981Scy 1439346981Scystatic int hostapd_cli_cmd_dpp_configurator_remove(struct wpa_ctrl *ctrl, 1440346981Scy int argc, char *argv[]) 1441346981Scy{ 1442346981Scy return hostapd_cli_cmd(ctrl, "DPP_CONFIGURATOR_REMOVE", 1, argc, argv); 1443346981Scy} 1444346981Scy 1445346981Scy 1446346981Scystatic int hostapd_cli_cmd_dpp_configurator_get_key(struct wpa_ctrl *ctrl, 1447346981Scy int argc, char *argv[]) 1448346981Scy{ 1449346981Scy return hostapd_cli_cmd(ctrl, "DPP_CONFIGURATOR_GET_KEY", 1, argc, argv); 1450346981Scy} 1451346981Scy 1452346981Scy 1453346981Scystatic int hostapd_cli_cmd_dpp_configurator_sign(struct wpa_ctrl *ctrl, 1454346981Scy int argc, char *argv[]) 1455346981Scy{ 1456346981Scy return hostapd_cli_cmd(ctrl, "DPP_CONFIGURATOR_SIGN", 1, argc, argv); 1457346981Scy} 1458346981Scy 1459346981Scy 1460346981Scystatic int hostapd_cli_cmd_dpp_pkex_add(struct wpa_ctrl *ctrl, int argc, 1461346981Scy char *argv[]) 1462346981Scy{ 1463346981Scy return hostapd_cli_cmd(ctrl, "DPP_PKEX_ADD", 1, argc, argv); 1464346981Scy} 1465346981Scy 1466346981Scy 1467346981Scystatic int hostapd_cli_cmd_dpp_pkex_remove(struct wpa_ctrl *ctrl, int argc, 1468346981Scy char *argv[]) 1469346981Scy{ 1470346981Scy return hostapd_cli_cmd(ctrl, "DPP_PKEX_REMOVE", 1, argc, argv); 1471346981Scy} 1472346981Scy 1473346981Scy#endif /* CONFIG_DPP */ 1474346981Scy 1475346981Scy 1476346981Scystatic int hostapd_cli_cmd_accept_macacl(struct wpa_ctrl *ctrl, int argc, 1477346981Scy char *argv[]) 1478346981Scy{ 1479346981Scy return hostapd_cli_cmd(ctrl, "ACCEPT_ACL", 1, argc, argv); 1480346981Scy} 1481346981Scy 1482346981Scy 1483346981Scystatic int hostapd_cli_cmd_deny_macacl(struct wpa_ctrl *ctrl, int argc, 1484346981Scy char *argv[]) 1485346981Scy{ 1486346981Scy return hostapd_cli_cmd(ctrl, "DENY_ACL", 1, argc, argv); 1487346981Scy} 1488346981Scy 1489346981Scy 1490346981Scystatic int hostapd_cli_cmd_poll_sta(struct wpa_ctrl *ctrl, int argc, 1491346981Scy char *argv[]) 1492346981Scy{ 1493346981Scy return hostapd_cli_cmd(ctrl, "POLL_STA", 1, argc, argv); 1494346981Scy} 1495346981Scy 1496346981Scy 1497346981Scystatic int hostapd_cli_cmd_req_beacon(struct wpa_ctrl *ctrl, int argc, 1498346981Scy char *argv[]) 1499346981Scy{ 1500346981Scy return hostapd_cli_cmd(ctrl, "REQ_BEACON", 2, argc, argv); 1501346981Scy} 1502346981Scy 1503346981Scy 1504346981Scystatic int hostapd_cli_cmd_reload_wpa_psk(struct wpa_ctrl *ctrl, int argc, 1505346981Scy char *argv[]) 1506346981Scy{ 1507346981Scy return wpa_ctrl_command(ctrl, "RELOAD_WPA_PSK"); 1508346981Scy} 1509346981Scy 1510346981Scy 1511214503Srpaulostruct hostapd_cli_cmd { 1512214503Srpaulo const char *cmd; 1513214503Srpaulo int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); 1514337817Scy char ** (*completion)(const char *str, int pos); 1515337817Scy const char *usage; 1516214503Srpaulo}; 1517214503Srpaulo 1518289549Srpaulostatic const struct hostapd_cli_cmd hostapd_cli_commands[] = { 1519337817Scy { "ping", hostapd_cli_cmd_ping, NULL, 1520337817Scy "= pings hostapd" }, 1521337817Scy { "mib", hostapd_cli_cmd_mib, NULL, 1522337817Scy "= get MIB variables (dot1x, dot11, radius)" }, 1523346981Scy { "relog", hostapd_cli_cmd_relog, NULL, 1524346981Scy "= reload/truncate debug log output file" }, 1525346981Scy { "status", hostapd_cli_cmd_status, NULL, 1526346981Scy "= show interface status info" }, 1527346981Scy { "sta", hostapd_cli_cmd_sta, hostapd_complete_stations, 1528337817Scy "<addr> = get MIB variables for one station" }, 1529337817Scy { "all_sta", hostapd_cli_cmd_all_sta, NULL, 1530337817Scy "= get MIB variables for all stations" }, 1531346981Scy { "list_sta", hostapd_cli_cmd_list_sta, NULL, 1532346981Scy "= list all stations" }, 1533337817Scy { "new_sta", hostapd_cli_cmd_new_sta, NULL, 1534337817Scy "<addr> = add a new station" }, 1535337817Scy { "deauthenticate", hostapd_cli_cmd_deauthenticate, 1536346981Scy hostapd_complete_stations, 1537337817Scy "<addr> = deauthenticate a station" }, 1538337817Scy { "disassociate", hostapd_cli_cmd_disassociate, 1539346981Scy hostapd_complete_stations, 1540337817Scy "<addr> = disassociate a station" }, 1541337817Scy#ifdef CONFIG_TAXONOMY 1542346981Scy { "signature", hostapd_cli_cmd_signature, hostapd_complete_stations, 1543337817Scy "<addr> = get taxonomy signature for a station" }, 1544337817Scy#endif /* CONFIG_TAXONOMY */ 1545214503Srpaulo#ifdef CONFIG_IEEE80211W 1546346981Scy { "sa_query", hostapd_cli_cmd_sa_query, hostapd_complete_stations, 1547337817Scy "<addr> = send SA Query to a station" }, 1548214503Srpaulo#endif /* CONFIG_IEEE80211W */ 1549214503Srpaulo#ifdef CONFIG_WPS 1550337817Scy { "wps_pin", hostapd_cli_cmd_wps_pin, NULL, 1551337817Scy "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" }, 1552337817Scy { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL, 1553337817Scy "<PIN> = verify PIN checksum" }, 1554337817Scy { "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL, 1555337817Scy "= indicate button pushed to initiate PBC" }, 1556337817Scy { "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL, 1557337817Scy "= cancel the pending WPS operation" }, 1558252726Srpaulo#ifdef CONFIG_WPS_NFC 1559337817Scy { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL, 1560337817Scy "<hexdump> = report read NFC tag with WPS data" }, 1561337817Scy { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL, 1562337817Scy "<WPS/NDEF> = build NFC configuration token" }, 1563337817Scy { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL, 1564337817Scy "<WPS/NDEF/enable/disable> = manager NFC password token" }, 1565337817Scy { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL, 1566337817Scy NULL }, 1567252726Srpaulo#endif /* CONFIG_WPS_NFC */ 1568337817Scy { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL, 1569337817Scy "<cmd> [params..] = enable/disable AP PIN" }, 1570337817Scy { "wps_config", hostapd_cli_cmd_wps_config, NULL, 1571337817Scy "<SSID> <auth> <encr> <key> = configure AP" }, 1572337817Scy { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL, 1573337817Scy "= show current WPS status" }, 1574214503Srpaulo#endif /* CONFIG_WPS */ 1575346981Scy { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL, 1576346981Scy "= send Disassociation Imminent notification" }, 1577346981Scy { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL, 1578346981Scy "= send ESS Dissassociation Imminent notification" }, 1579346981Scy { "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL, 1580346981Scy "= send BSS Transition Management Request" }, 1581337817Scy { "get_config", hostapd_cli_cmd_get_config, NULL, 1582337817Scy "= show current configuration" }, 1583337817Scy { "help", hostapd_cli_cmd_help, hostapd_cli_complete_help, 1584337817Scy "= show this usage help" }, 1585337817Scy { "interface", hostapd_cli_cmd_interface, hostapd_complete_interface, 1586337817Scy "[ifname] = show interfaces/select interface" }, 1587289549Srpaulo#ifdef CONFIG_FST 1588346981Scy { "fst", hostapd_cli_cmd_fst, NULL, 1589346981Scy "<params...> = send FST-MANAGER control interface command" }, 1590289549Srpaulo#endif /* CONFIG_FST */ 1591346981Scy { "raw", hostapd_cli_cmd_raw, NULL, 1592346981Scy "<params..> = send unprocessed command" }, 1593337817Scy { "level", hostapd_cli_cmd_level, NULL, 1594337817Scy "<debug level> = change debug level" }, 1595337817Scy { "license", hostapd_cli_cmd_license, NULL, 1596337817Scy "= show full hostapd_cli license" }, 1597337817Scy { "quit", hostapd_cli_cmd_quit, NULL, 1598337817Scy "= exit hostapd_cli" }, 1599346981Scy { "set", hostapd_cli_cmd_set, hostapd_complete_set, 1600346981Scy "<name> <value> = set runtime variables" }, 1601346981Scy { "get", hostapd_cli_cmd_get, hostapd_complete_get, 1602346981Scy "<name> = get runtime info" }, 1603346981Scy { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL, 1604346981Scy "<arg,arg,...> = set QoS Map set element" }, 1605346981Scy { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf, 1606346981Scy hostapd_complete_stations, 1607346981Scy "<addr> = send QoS Map Configure frame" }, 1608346981Scy { "chan_switch", hostapd_cli_cmd_chan_switch, NULL, 1609346981Scy "<cs_count> <freq> [sec_channel_offset=] [center_freq1=]\n" 1610346981Scy " [center_freq2=] [bandwidth=] [blocktx] [ht|vht]\n" 1611346981Scy " = initiate channel switch announcement" }, 1612346981Scy { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, 1613346981Scy "<addr> <url>\n" 1614346981Scy " = send WNM-Notification Subscription Remediation Request" }, 1615346981Scy { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL, 1616346981Scy "<addr> <code (0/1)> <Re-auth-Delay(sec)> [url]\n" 1617346981Scy " = send WNM-Notification imminent deauthentication indication" }, 1618346981Scy { "vendor", hostapd_cli_cmd_vendor, NULL, 1619346981Scy "<vendor id> <sub command id> [<hex formatted data>]\n" 1620346981Scy " = send vendor driver command" }, 1621346981Scy { "enable", hostapd_cli_cmd_enable, NULL, 1622346981Scy "= enable hostapd on current interface" }, 1623346981Scy { "reload", hostapd_cli_cmd_reload, NULL, 1624346981Scy "= reload configuration for current interface" }, 1625346981Scy { "disable", hostapd_cli_cmd_disable, NULL, 1626346981Scy "= disable hostapd on current interface" }, 1627351611Scy { "update_beacon", hostapd_cli_cmd_update_beacon, NULL, 1628351611Scy "= update Beacon frame contents\n"}, 1629346981Scy { "erp_flush", hostapd_cli_cmd_erp_flush, NULL, 1630346981Scy "= drop all ERP keys"}, 1631346981Scy { "log_level", hostapd_cli_cmd_log_level, NULL, 1632346981Scy "[level] = show/change log verbosity level" }, 1633346981Scy { "pmksa", hostapd_cli_cmd_pmksa, NULL, 1634346981Scy " = show PMKSA cache entries" }, 1635346981Scy { "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL, 1636346981Scy " = flush PMKSA cache" }, 1637346981Scy { "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, 1638346981Scy "<addr> <ssid=> <nr=> [lci=] [civic=] [stat]\n" 1639346981Scy " = add AP to neighbor database" }, 1640346981Scy { "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, 1641346981Scy "<addr> <ssid=> = remove AP from neighbor database" }, 1642346981Scy { "req_lci", hostapd_cli_cmd_req_lci, hostapd_complete_stations, 1643346981Scy "<addr> = send LCI request to a station"}, 1644346981Scy { "req_range", hostapd_cli_cmd_req_range, NULL, 1645346981Scy " = send FTM range request"}, 1646346981Scy { "driver_flags", hostapd_cli_cmd_driver_flags, NULL, 1647346981Scy " = show supported driver flags"}, 1648346981Scy#ifdef CONFIG_DPP 1649346981Scy { "dpp_qr_code", hostapd_cli_cmd_dpp_qr_code, NULL, 1650346981Scy "report a scanned DPP URI from a QR Code" }, 1651346981Scy { "dpp_bootstrap_gen", hostapd_cli_cmd_dpp_bootstrap_gen, NULL, 1652346981Scy "type=<qrcode> [chan=..] [mac=..] [info=..] [curve=..] [key=..] = generate DPP bootstrap information" }, 1653346981Scy { "dpp_bootstrap_remove", hostapd_cli_cmd_dpp_bootstrap_remove, NULL, 1654346981Scy "*|<id> = remove DPP bootstrap information" }, 1655346981Scy { "dpp_bootstrap_get_uri", hostapd_cli_cmd_dpp_bootstrap_get_uri, NULL, 1656346981Scy "<id> = get DPP bootstrap URI" }, 1657346981Scy { "dpp_bootstrap_info", hostapd_cli_cmd_dpp_bootstrap_info, NULL, 1658346981Scy "<id> = show DPP bootstrap information" }, 1659346981Scy { "dpp_auth_init", hostapd_cli_cmd_dpp_auth_init, NULL, 1660346981Scy "peer=<id> [own=<id>] = initiate DPP bootstrapping" }, 1661346981Scy { "dpp_listen", hostapd_cli_cmd_dpp_listen, NULL, 1662346981Scy "<freq in MHz> = start DPP listen" }, 1663346981Scy { "dpp_stop_listen", hostapd_cli_cmd_dpp_stop_listen, NULL, 1664346981Scy "= stop DPP listen" }, 1665346981Scy { "dpp_configurator_add", hostapd_cli_cmd_dpp_configurator_add, NULL, 1666346981Scy "[curve=..] [key=..] = add DPP configurator" }, 1667346981Scy { "dpp_configurator_remove", hostapd_cli_cmd_dpp_configurator_remove, 1668346981Scy NULL, 1669346981Scy "*|<id> = remove DPP configurator" }, 1670346981Scy { "dpp_configurator_get_key", hostapd_cli_cmd_dpp_configurator_get_key, 1671346981Scy NULL, 1672346981Scy "<id> = Get DPP configurator's private key" }, 1673346981Scy { "dpp_configurator_sign", hostapd_cli_cmd_dpp_configurator_sign, NULL, 1674346981Scy "conf=<role> configurator=<id> = generate self DPP configuration" }, 1675346981Scy { "dpp_pkex_add", hostapd_cli_cmd_dpp_pkex_add, NULL, 1676346981Scy "add PKEX code" }, 1677346981Scy { "dpp_pkex_remove", hostapd_cli_cmd_dpp_pkex_remove, NULL, 1678346981Scy "*|<id> = remove DPP pkex information" }, 1679346981Scy#endif /* CONFIG_DPP */ 1680346981Scy { "accept_acl", hostapd_cli_cmd_accept_macacl, NULL, 1681346981Scy "=Add/Delete/Show/Clear accept MAC ACL" }, 1682346981Scy { "deny_acl", hostapd_cli_cmd_deny_macacl, NULL, 1683346981Scy "=Add/Delete/Show/Clear deny MAC ACL" }, 1684346981Scy { "poll_sta", hostapd_cli_cmd_poll_sta, hostapd_complete_stations, 1685346981Scy "<addr> = poll a STA to check connectivity with a QoS null frame" }, 1686346981Scy { "req_beacon", hostapd_cli_cmd_req_beacon, NULL, 1687346981Scy "<addr> [req_mode=] <measurement request hexdump> = send a Beacon report request to a station" }, 1688346981Scy { "reload_wpa_psk", hostapd_cli_cmd_reload_wpa_psk, NULL, 1689346981Scy "= reload wpa_psk_file only" }, 1690337817Scy { NULL, NULL, NULL, NULL } 1691214503Srpaulo}; 1692214503Srpaulo 1693214503Srpaulo 1694337817Scy/* 1695337817Scy * Prints command usage, lines are padded with the specified string. 1696337817Scy */ 1697337817Scystatic void print_cmd_help(FILE *stream, const struct hostapd_cli_cmd *cmd, 1698337817Scy const char *pad) 1699337817Scy{ 1700337817Scy char c; 1701337817Scy size_t n; 1702337817Scy 1703337817Scy if (cmd->usage == NULL) 1704337817Scy return; 1705337817Scy fprintf(stream, "%s%s ", pad, cmd->cmd); 1706337817Scy for (n = 0; (c = cmd->usage[n]); n++) { 1707337817Scy fprintf(stream, "%c", c); 1708337817Scy if (c == '\n') 1709337817Scy fprintf(stream, "%s", pad); 1710337817Scy } 1711337817Scy fprintf(stream, "\n"); 1712337817Scy} 1713337817Scy 1714337817Scy 1715337817Scystatic void print_help(FILE *stream, const char *cmd) 1716337817Scy{ 1717337817Scy int n; 1718337817Scy 1719337817Scy fprintf(stream, "commands:\n"); 1720337817Scy for (n = 0; hostapd_cli_commands[n].cmd; n++) { 1721337817Scy if (cmd == NULL || str_starts(hostapd_cli_commands[n].cmd, cmd)) 1722337817Scy print_cmd_help(stream, &hostapd_cli_commands[n], " "); 1723337817Scy } 1724337817Scy} 1725337817Scy 1726337817Scy 1727214503Srpaulostatic void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1728214503Srpaulo{ 1729289549Srpaulo const struct hostapd_cli_cmd *cmd, *match = NULL; 1730214503Srpaulo int count; 1731214503Srpaulo 1732214503Srpaulo count = 0; 1733214503Srpaulo cmd = hostapd_cli_commands; 1734214503Srpaulo while (cmd->cmd) { 1735214503Srpaulo if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) { 1736214503Srpaulo match = cmd; 1737252726Srpaulo if (os_strcasecmp(cmd->cmd, argv[0]) == 0) { 1738252726Srpaulo /* we have an exact match */ 1739252726Srpaulo count = 1; 1740252726Srpaulo break; 1741252726Srpaulo } 1742214503Srpaulo count++; 1743214503Srpaulo } 1744214503Srpaulo cmd++; 1745214503Srpaulo } 1746214503Srpaulo 1747214503Srpaulo if (count > 1) { 1748214503Srpaulo printf("Ambiguous command '%s'; possible commands:", argv[0]); 1749214503Srpaulo cmd = hostapd_cli_commands; 1750214503Srpaulo while (cmd->cmd) { 1751214503Srpaulo if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 1752214503Srpaulo 0) { 1753214503Srpaulo printf(" %s", cmd->cmd); 1754214503Srpaulo } 1755214503Srpaulo cmd++; 1756214503Srpaulo } 1757214503Srpaulo printf("\n"); 1758214503Srpaulo } else if (count == 0) { 1759214503Srpaulo printf("Unknown command '%s'\n", argv[0]); 1760214503Srpaulo } else { 1761214503Srpaulo match->handler(ctrl, argc - 1, &argv[1]); 1762214503Srpaulo } 1763214503Srpaulo} 1764214503Srpaulo 1765214503Srpaulo 1766337817Scystatic void cli_event(const char *str) 1767337817Scy{ 1768337817Scy const char *start, *s; 1769337817Scy 1770337817Scy start = os_strchr(str, '>'); 1771337817Scy if (start == NULL) 1772337817Scy return; 1773337817Scy 1774337817Scy start++; 1775337817Scy 1776337817Scy if (str_starts(start, AP_STA_CONNECTED)) { 1777337817Scy s = os_strchr(start, ' '); 1778337817Scy if (s == NULL) 1779337817Scy return; 1780337817Scy cli_txt_list_add(&stations, s + 1); 1781337817Scy return; 1782337817Scy } 1783337817Scy 1784337817Scy if (str_starts(start, AP_STA_DISCONNECTED)) { 1785337817Scy s = os_strchr(start, ' '); 1786337817Scy if (s == NULL) 1787337817Scy return; 1788337817Scy cli_txt_list_del_addr(&stations, s + 1); 1789337817Scy return; 1790337817Scy } 1791337817Scy} 1792337817Scy 1793337817Scy 1794214503Srpaulostatic void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read, 1795214503Srpaulo int action_monitor) 1796214503Srpaulo{ 1797214503Srpaulo int first = 1; 1798214503Srpaulo if (ctrl_conn == NULL) 1799214503Srpaulo return; 1800214503Srpaulo while (wpa_ctrl_pending(ctrl)) { 1801346981Scy char buf[4096]; 1802214503Srpaulo size_t len = sizeof(buf) - 1; 1803214503Srpaulo if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { 1804214503Srpaulo buf[len] = '\0'; 1805214503Srpaulo if (action_monitor) 1806214503Srpaulo hostapd_cli_action_process(buf, len); 1807214503Srpaulo else { 1808337817Scy cli_event(buf); 1809214503Srpaulo if (in_read && first) 1810214503Srpaulo printf("\n"); 1811214503Srpaulo first = 0; 1812214503Srpaulo printf("%s\n", buf); 1813214503Srpaulo } 1814214503Srpaulo } else { 1815214503Srpaulo printf("Could not read pending message.\n"); 1816214503Srpaulo break; 1817214503Srpaulo } 1818214503Srpaulo } 1819214503Srpaulo} 1820214503Srpaulo 1821214503Srpaulo 1822337817Scystatic void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx) 1823214503Srpaulo{ 1824337817Scy hostapd_cli_recv_pending(ctrl_conn, 0, 0); 1825214503Srpaulo} 1826214503Srpaulo 1827214503Srpaulo 1828252726Srpaulostatic void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx) 1829214503Srpaulo{ 1830214503Srpaulo if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) { 1831214503Srpaulo printf("Connection to hostapd lost - trying to reconnect\n"); 1832214503Srpaulo hostapd_cli_close_connection(); 1833214503Srpaulo } 1834346981Scy if (!ctrl_conn && hostapd_cli_reconnect(ctrl_ifname) == 0) 1835346981Scy printf("Connection to hostapd re-established\n"); 1836214503Srpaulo if (ctrl_conn) 1837214503Srpaulo hostapd_cli_recv_pending(ctrl_conn, 1, 0); 1838252726Srpaulo eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL); 1839214503Srpaulo} 1840214503Srpaulo 1841214503Srpaulo 1842252726Srpaulostatic void hostapd_cli_eloop_terminate(int sig, void *signal_ctx) 1843252726Srpaulo{ 1844252726Srpaulo eloop_terminate(); 1845252726Srpaulo} 1846252726Srpaulo 1847252726Srpaulo 1848252726Srpaulostatic void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd) 1849252726Srpaulo{ 1850252726Srpaulo char *argv[max_args]; 1851252726Srpaulo int argc; 1852252726Srpaulo argc = tokenize_cmd(cmd, argv); 1853252726Srpaulo if (argc) 1854252726Srpaulo wpa_request(ctrl_conn, argc, argv); 1855252726Srpaulo} 1856252726Srpaulo 1857252726Srpaulo 1858252726Srpaulostatic void hostapd_cli_edit_eof_cb(void *ctx) 1859252726Srpaulo{ 1860252726Srpaulo eloop_terminate(); 1861252726Srpaulo} 1862252726Srpaulo 1863252726Srpaulo 1864337817Scystatic char ** list_cmd_list(void) 1865337817Scy{ 1866337817Scy char **res; 1867337817Scy int i, count; 1868337817Scy 1869337817Scy count = ARRAY_SIZE(hostapd_cli_commands); 1870337817Scy res = os_calloc(count + 1, sizeof(char *)); 1871337817Scy if (res == NULL) 1872337817Scy return NULL; 1873337817Scy 1874337817Scy for (i = 0; hostapd_cli_commands[i].cmd; i++) { 1875337817Scy res[i] = os_strdup(hostapd_cli_commands[i].cmd); 1876337817Scy if (res[i] == NULL) 1877337817Scy break; 1878337817Scy } 1879337817Scy 1880337817Scy return res; 1881337817Scy} 1882337817Scy 1883337817Scy 1884337817Scystatic char ** hostapd_cli_cmd_completion(const char *cmd, const char *str, 1885337817Scy int pos) 1886337817Scy{ 1887337817Scy int i; 1888337817Scy 1889337817Scy for (i = 0; hostapd_cli_commands[i].cmd; i++) { 1890337817Scy if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0) 1891337817Scy continue; 1892337817Scy if (hostapd_cli_commands[i].completion) 1893337817Scy return hostapd_cli_commands[i].completion(str, pos); 1894337817Scy if (!hostapd_cli_commands[i].usage) 1895337817Scy return NULL; 1896337817Scy edit_clear_line(); 1897337817Scy printf("\r%s\n", hostapd_cli_commands[i].usage); 1898337817Scy edit_redraw(); 1899337817Scy break; 1900337817Scy } 1901337817Scy 1902337817Scy return NULL; 1903337817Scy} 1904337817Scy 1905337817Scy 1906337817Scystatic char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str, 1907337817Scy int pos) 1908337817Scy{ 1909337817Scy char **res; 1910337817Scy const char *end; 1911337817Scy char *cmd; 1912337817Scy 1913337817Scy end = os_strchr(str, ' '); 1914337817Scy if (end == NULL || str + pos < end) 1915337817Scy return list_cmd_list(); 1916337817Scy 1917337817Scy cmd = os_malloc(pos + 1); 1918337817Scy if (cmd == NULL) 1919337817Scy return NULL; 1920337817Scy os_memcpy(cmd, str, pos); 1921337817Scy cmd[end - str] = '\0'; 1922337817Scy res = hostapd_cli_cmd_completion(cmd, str, pos); 1923337817Scy os_free(cmd); 1924337817Scy return res; 1925337817Scy} 1926337817Scy 1927337817Scy 1928252726Srpaulostatic void hostapd_cli_interactive(void) 1929252726Srpaulo{ 1930346981Scy char *hfile = NULL; 1931346981Scy char *home; 1932346981Scy 1933252726Srpaulo printf("\nInteractive mode\n\n"); 1934252726Srpaulo 1935346981Scy#ifdef CONFIG_HOSTAPD_CLI_HISTORY_DIR 1936346981Scy home = CONFIG_HOSTAPD_CLI_HISTORY_DIR; 1937346981Scy#else /* CONFIG_HOSTAPD_CLI_HISTORY_DIR */ 1938346981Scy home = getenv("HOME"); 1939346981Scy#endif /* CONFIG_HOSTAPD_CLI_HISTORY_DIR */ 1940346981Scy if (home) { 1941346981Scy const char *fname = ".hostapd_cli_history"; 1942346981Scy int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1; 1943346981Scy hfile = os_malloc(hfile_len); 1944346981Scy if (hfile) 1945346981Scy os_snprintf(hfile, hfile_len, "%s/%s", home, fname); 1946346981Scy } 1947346981Scy 1948252726Srpaulo eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL); 1949252726Srpaulo edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb, 1950346981Scy hostapd_cli_edit_completion_cb, NULL, hfile, NULL); 1951252726Srpaulo eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL); 1952252726Srpaulo 1953252726Srpaulo eloop_run(); 1954252726Srpaulo 1955337817Scy cli_txt_list_flush(&stations); 1956346981Scy edit_deinit(hfile, NULL); 1957346981Scy os_free(hfile); 1958252726Srpaulo eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL); 1959252726Srpaulo} 1960252726Srpaulo 1961252726Srpaulo 1962252726Srpaulostatic void hostapd_cli_cleanup(void) 1963252726Srpaulo{ 1964252726Srpaulo hostapd_cli_close_connection(); 1965252726Srpaulo if (pid_file) 1966252726Srpaulo os_daemonize_terminate(pid_file); 1967252726Srpaulo 1968252726Srpaulo os_program_deinit(); 1969252726Srpaulo} 1970252726Srpaulo 1971252726Srpaulo 1972214503Srpaulostatic void hostapd_cli_action(struct wpa_ctrl *ctrl) 1973214503Srpaulo{ 1974214503Srpaulo fd_set rfds; 1975214503Srpaulo int fd, res; 1976214503Srpaulo struct timeval tv; 1977214503Srpaulo char buf[256]; 1978214503Srpaulo size_t len; 1979214503Srpaulo 1980214503Srpaulo fd = wpa_ctrl_get_fd(ctrl); 1981214503Srpaulo 1982214503Srpaulo while (!hostapd_cli_quit) { 1983214503Srpaulo FD_ZERO(&rfds); 1984214503Srpaulo FD_SET(fd, &rfds); 1985214503Srpaulo tv.tv_sec = ping_interval; 1986214503Srpaulo tv.tv_usec = 0; 1987214503Srpaulo res = select(fd + 1, &rfds, NULL, NULL, &tv); 1988214503Srpaulo if (res < 0 && errno != EINTR) { 1989214503Srpaulo perror("select"); 1990214503Srpaulo break; 1991214503Srpaulo } 1992214503Srpaulo 1993214503Srpaulo if (FD_ISSET(fd, &rfds)) 1994214503Srpaulo hostapd_cli_recv_pending(ctrl, 0, 1); 1995214503Srpaulo else { 1996214503Srpaulo len = sizeof(buf) - 1; 1997214503Srpaulo if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len, 1998214503Srpaulo hostapd_cli_action_process) < 0 || 1999214503Srpaulo len < 4 || os_memcmp(buf, "PONG", 4) != 0) { 2000214503Srpaulo printf("hostapd did not reply to PING " 2001214503Srpaulo "command - exiting\n"); 2002214503Srpaulo break; 2003214503Srpaulo } 2004214503Srpaulo } 2005214503Srpaulo } 2006214503Srpaulo} 2007214503Srpaulo 2008214503Srpaulo 2009214503Srpauloint main(int argc, char *argv[]) 2010214503Srpaulo{ 2011214503Srpaulo int warning_displayed = 0; 2012214503Srpaulo int c; 2013214503Srpaulo int daemonize = 0; 2014214503Srpaulo 2015214503Srpaulo if (os_program_init()) 2016214503Srpaulo return -1; 2017214503Srpaulo 2018214503Srpaulo for (;;) { 2019289549Srpaulo c = getopt(argc, argv, "a:BhG:i:p:P:s:v"); 2020214503Srpaulo if (c < 0) 2021214503Srpaulo break; 2022214503Srpaulo switch (c) { 2023214503Srpaulo case 'a': 2024214503Srpaulo action_file = optarg; 2025214503Srpaulo break; 2026214503Srpaulo case 'B': 2027214503Srpaulo daemonize = 1; 2028214503Srpaulo break; 2029214503Srpaulo case 'G': 2030214503Srpaulo ping_interval = atoi(optarg); 2031214503Srpaulo break; 2032214503Srpaulo case 'h': 2033214503Srpaulo usage(); 2034214503Srpaulo return 0; 2035214503Srpaulo case 'v': 2036214503Srpaulo printf("%s\n", hostapd_cli_version); 2037214503Srpaulo return 0; 2038214503Srpaulo case 'i': 2039214503Srpaulo os_free(ctrl_ifname); 2040214503Srpaulo ctrl_ifname = os_strdup(optarg); 2041214503Srpaulo break; 2042214503Srpaulo case 'p': 2043214503Srpaulo ctrl_iface_dir = optarg; 2044214503Srpaulo break; 2045289549Srpaulo case 'P': 2046289549Srpaulo pid_file = optarg; 2047289549Srpaulo break; 2048289549Srpaulo case 's': 2049289549Srpaulo client_socket_dir = optarg; 2050289549Srpaulo break; 2051214503Srpaulo default: 2052214503Srpaulo usage(); 2053214503Srpaulo return -1; 2054214503Srpaulo } 2055214503Srpaulo } 2056214503Srpaulo 2057214503Srpaulo interactive = (argc == optind) && (action_file == NULL); 2058214503Srpaulo 2059214503Srpaulo if (interactive) { 2060337817Scy printf("%s\n\n%s\n\n", hostapd_cli_version, cli_license); 2061214503Srpaulo } 2062214503Srpaulo 2063252726Srpaulo if (eloop_init()) 2064252726Srpaulo return -1; 2065252726Srpaulo 2066214503Srpaulo for (;;) { 2067214503Srpaulo if (ctrl_ifname == NULL) { 2068214503Srpaulo struct dirent *dent; 2069214503Srpaulo DIR *dir = opendir(ctrl_iface_dir); 2070214503Srpaulo if (dir) { 2071214503Srpaulo while ((dent = readdir(dir))) { 2072214503Srpaulo if (os_strcmp(dent->d_name, ".") == 0 2073214503Srpaulo || 2074214503Srpaulo os_strcmp(dent->d_name, "..") == 0) 2075214503Srpaulo continue; 2076214503Srpaulo printf("Selected interface '%s'\n", 2077214503Srpaulo dent->d_name); 2078214503Srpaulo ctrl_ifname = os_strdup(dent->d_name); 2079214503Srpaulo break; 2080214503Srpaulo } 2081214503Srpaulo closedir(dir); 2082214503Srpaulo } 2083214503Srpaulo } 2084346981Scy hostapd_cli_reconnect(ctrl_ifname); 2085214503Srpaulo if (ctrl_conn) { 2086214503Srpaulo if (warning_displayed) 2087214503Srpaulo printf("Connection established.\n"); 2088214503Srpaulo break; 2089214503Srpaulo } 2090214503Srpaulo 2091214503Srpaulo if (!interactive) { 2092214503Srpaulo perror("Failed to connect to hostapd - " 2093214503Srpaulo "wpa_ctrl_open"); 2094214503Srpaulo return -1; 2095214503Srpaulo } 2096214503Srpaulo 2097214503Srpaulo if (!warning_displayed) { 2098214503Srpaulo printf("Could not connect to hostapd - re-trying\n"); 2099214503Srpaulo warning_displayed = 1; 2100214503Srpaulo } 2101214503Srpaulo os_sleep(1, 0); 2102214503Srpaulo continue; 2103214503Srpaulo } 2104214503Srpaulo 2105346981Scy if (action_file && !hostapd_cli_attached) 2106346981Scy return -1; 2107337817Scy if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue()) 2108214503Srpaulo return -1; 2109214503Srpaulo 2110214503Srpaulo if (interactive) 2111214503Srpaulo hostapd_cli_interactive(); 2112214503Srpaulo else if (action_file) 2113214503Srpaulo hostapd_cli_action(ctrl_conn); 2114214503Srpaulo else 2115214503Srpaulo wpa_request(ctrl_conn, argc - optind, &argv[optind]); 2116214503Srpaulo 2117337817Scy unregister_event_handler(ctrl_conn); 2118214503Srpaulo os_free(ctrl_ifname); 2119252726Srpaulo eloop_destroy(); 2120214503Srpaulo hostapd_cli_cleanup(); 2121214503Srpaulo return 0; 2122214503Srpaulo} 2123337817Scy 2124337817Scy#else /* CONFIG_NO_CTRL_IFACE */ 2125337817Scy 2126337817Scyint main(int argc, char *argv[]) 2127337817Scy{ 2128337817Scy return -1; 2129337817Scy} 2130337817Scy 2131337817Scy#endif /* CONFIG_NO_CTRL_IFACE */ 2132