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