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