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