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