1 /* 2 * WPA Supplicant - command line interface for wpa_supplicant daemon 3 * Copyright (c) 2004-2012, 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 11 #ifdef CONFIG_CTRL_IFACE 12 13 #ifdef CONFIG_CTRL_IFACE_UNIX 14 #include <dirent.h> 15 #endif /* CONFIG_CTRL_IFACE_UNIX */ 16 17 #include "common/wpa_ctrl.h" 18 #include "utils/common.h" 19 #include "utils/eloop.h" 20 #include "utils/edit.h" 21 #include "utils/list.h" 22 #include "common/version.h" 23 #include "common/ieee802_11_defs.h" 24 #ifdef ANDROID 25 #include <cutils/properties.h> 26 #endif /* ANDROID */ 27 28 29 static const char *wpa_cli_version = 30 "wpa_cli v" VERSION_STR "\n" 31 "Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> and contributors"; 32 33 34 static const char *wpa_cli_license = 35 "This software may be distributed under the terms of the BSD license.\n" 36 "See README for more details.\n"; 37 38 static const char *wpa_cli_full_license = 39 "This software may be distributed under the terms of the BSD license.\n" 40 "\n" 41 "Redistribution and use in source and binary forms, with or without\n" 42 "modification, are permitted provided that the following conditions are\n" 43 "met:\n" 44 "\n" 45 "1. Redistributions of source code must retain the above copyright\n" 46 " notice, this list of conditions and the following disclaimer.\n" 47 "\n" 48 "2. Redistributions in binary form must reproduce the above copyright\n" 49 " notice, this list of conditions and the following disclaimer in the\n" 50 " documentation and/or other materials provided with the distribution.\n" 51 "\n" 52 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n" 53 " names of its contributors may be used to endorse or promote products\n" 54 " derived from this software without specific prior written permission.\n" 55 "\n" 56 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n" 57 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n" 58 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n" 59 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n" 60 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n" 61 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n" 62 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n" 63 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n" 64 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n" 65 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n" 66 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n" 67 "\n"; 68 69 static struct wpa_ctrl *ctrl_conn; 70 static struct wpa_ctrl *mon_conn; 71 static int wpa_cli_quit = 0; 72 static int wpa_cli_attached = 0; 73 static int wpa_cli_connected = 0; 74 static int wpa_cli_last_id = 0; 75 #ifndef CONFIG_CTRL_IFACE_DIR 76 #define CONFIG_CTRL_IFACE_DIR "/var/run/wpa_supplicant" 77 #endif /* CONFIG_CTRL_IFACE_DIR */ 78 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR; 79 static char *ctrl_ifname = NULL; 80 static const char *pid_file = NULL; 81 static const char *action_file = NULL; 82 static int ping_interval = 5; 83 static int interactive = 0; 84 85 struct cli_txt_entry { 86 struct dl_list list; 87 char *txt; 88 }; 89 90 static DEFINE_DL_LIST(bsses); /* struct cli_txt_entry */ 91 static DEFINE_DL_LIST(p2p_peers); /* struct cli_txt_entry */ 92 static DEFINE_DL_LIST(p2p_groups); /* struct cli_txt_entry */ 93 94 95 static void print_help(const char *cmd); 96 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx); 97 static void wpa_cli_close_connection(void); 98 static char * wpa_cli_get_default_ifname(void); 99 static char ** wpa_list_cmd_list(void); 100 101 102 static void usage(void) 103 { 104 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] " 105 "[-a<action file>] \\\n" 106 " [-P<pid file>] [-g<global ctrl>] [-G<ping interval>] " 107 "[command..]\n" 108 " -h = help (show this usage text)\n" 109 " -v = shown version information\n" 110 " -a = run in daemon mode executing the action file based on " 111 "events from\n" 112 " wpa_supplicant\n" 113 " -B = run a daemon in the background\n" 114 " default path: " CONFIG_CTRL_IFACE_DIR "\n" 115 " default interface: first interface found in socket path\n"); 116 print_help(NULL); 117 } 118 119 120 static void cli_txt_list_free(struct cli_txt_entry *e) 121 { 122 dl_list_del(&e->list); 123 os_free(e->txt); 124 os_free(e); 125 } 126 127 128 static void cli_txt_list_flush(struct dl_list *list) 129 { 130 struct cli_txt_entry *e; 131 while ((e = dl_list_first(list, struct cli_txt_entry, list))) 132 cli_txt_list_free(e); 133 } 134 135 136 static struct cli_txt_entry * cli_txt_list_get(struct dl_list *txt_list, 137 const char *txt) 138 { 139 struct cli_txt_entry *e; 140 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) { 141 if (os_strcmp(e->txt, txt) == 0) 142 return e; 143 } 144 return NULL; 145 } 146 147 148 static void cli_txt_list_del(struct dl_list *txt_list, const char *txt) 149 { 150 struct cli_txt_entry *e; 151 e = cli_txt_list_get(txt_list, txt); 152 if (e) 153 cli_txt_list_free(e); 154 } 155 156 157 static void cli_txt_list_del_addr(struct dl_list *txt_list, const char *txt) 158 { 159 u8 addr[ETH_ALEN]; 160 char buf[18]; 161 if (hwaddr_aton(txt, addr) < 0) 162 return; 163 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); 164 cli_txt_list_del(txt_list, buf); 165 } 166 167 168 #ifdef CONFIG_P2P 169 static void cli_txt_list_del_word(struct dl_list *txt_list, const char *txt) 170 { 171 const char *end; 172 char *buf; 173 end = os_strchr(txt, ' '); 174 if (end == NULL) 175 end = txt + os_strlen(txt); 176 buf = os_malloc(end - txt + 1); 177 if (buf == NULL) 178 return; 179 os_memcpy(buf, txt, end - txt); 180 buf[end - txt] = '\0'; 181 cli_txt_list_del(txt_list, buf); 182 os_free(buf); 183 } 184 #endif /* CONFIG_P2P */ 185 186 187 static int cli_txt_list_add(struct dl_list *txt_list, const char *txt) 188 { 189 struct cli_txt_entry *e; 190 e = cli_txt_list_get(txt_list, txt); 191 if (e) 192 return 0; 193 e = os_zalloc(sizeof(*e)); 194 if (e == NULL) 195 return -1; 196 e->txt = os_strdup(txt); 197 if (e->txt == NULL) { 198 os_free(e); 199 return -1; 200 } 201 dl_list_add(txt_list, &e->list); 202 return 0; 203 } 204 205 206 #ifdef CONFIG_P2P 207 static int cli_txt_list_add_addr(struct dl_list *txt_list, const char *txt) 208 { 209 u8 addr[ETH_ALEN]; 210 char buf[18]; 211 if (hwaddr_aton(txt, addr) < 0) 212 return -1; 213 os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(addr)); 214 return cli_txt_list_add(txt_list, buf); 215 } 216 217 218 static int cli_txt_list_add_word(struct dl_list *txt_list, const char *txt) 219 { 220 const char *end; 221 char *buf; 222 int ret; 223 end = os_strchr(txt, ' '); 224 if (end == NULL) 225 end = txt + os_strlen(txt); 226 buf = os_malloc(end - txt + 1); 227 if (buf == NULL) 228 return -1; 229 os_memcpy(buf, txt, end - txt); 230 buf[end - txt] = '\0'; 231 ret = cli_txt_list_add(txt_list, buf); 232 os_free(buf); 233 return ret; 234 } 235 #endif /* CONFIG_P2P */ 236 237 238 static char ** cli_txt_list_array(struct dl_list *txt_list) 239 { 240 unsigned int i, count = dl_list_len(txt_list); 241 char **res; 242 struct cli_txt_entry *e; 243 244 res = os_calloc(count + 1, sizeof(char *)); 245 if (res == NULL) 246 return NULL; 247 248 i = 0; 249 dl_list_for_each(e, txt_list, struct cli_txt_entry, list) { 250 res[i] = os_strdup(e->txt); 251 if (res[i] == NULL) 252 break; 253 i++; 254 } 255 256 return res; 257 } 258 259 260 static int get_cmd_arg_num(const char *str, int pos) 261 { 262 int arg = 0, i; 263 264 for (i = 0; i <= pos; i++) { 265 if (str[i] != ' ') { 266 arg++; 267 while (i <= pos && str[i] != ' ') 268 i++; 269 } 270 } 271 272 if (arg > 0) 273 arg--; 274 return arg; 275 } 276 277 278 static int str_starts(const char *src, const char *match) 279 { 280 return os_strncmp(src, match, os_strlen(match)) == 0; 281 } 282 283 284 static int wpa_cli_show_event(const char *event) 285 { 286 const char *start; 287 288 start = os_strchr(event, '>'); 289 if (start == NULL) 290 return 1; 291 292 start++; 293 /* 294 * Skip BSS added/removed events since they can be relatively frequent 295 * and are likely of not much use for an interactive user. 296 */ 297 if (str_starts(start, WPA_EVENT_BSS_ADDED) || 298 str_starts(start, WPA_EVENT_BSS_REMOVED)) 299 return 0; 300 301 return 1; 302 } 303 304 305 static int wpa_cli_open_connection(const char *ifname, int attach) 306 { 307 #if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE) 308 ctrl_conn = wpa_ctrl_open(ifname); 309 if (ctrl_conn == NULL) 310 return -1; 311 312 if (attach && interactive) 313 mon_conn = wpa_ctrl_open(ifname); 314 else 315 mon_conn = NULL; 316 #else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ 317 char *cfile = NULL; 318 int flen, res; 319 320 if (ifname == NULL) 321 return -1; 322 323 #ifdef ANDROID 324 if (access(ctrl_iface_dir, F_OK) < 0) { 325 cfile = os_strdup(ifname); 326 if (cfile == NULL) 327 return -1; 328 } 329 #endif /* ANDROID */ 330 331 if (cfile == NULL) { 332 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2; 333 cfile = os_malloc(flen); 334 if (cfile == NULL) 335 return -1; 336 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, 337 ifname); 338 if (res < 0 || res >= flen) { 339 os_free(cfile); 340 return -1; 341 } 342 } 343 344 ctrl_conn = wpa_ctrl_open(cfile); 345 if (ctrl_conn == NULL) { 346 os_free(cfile); 347 return -1; 348 } 349 350 if (attach && interactive) 351 mon_conn = wpa_ctrl_open(cfile); 352 else 353 mon_conn = NULL; 354 os_free(cfile); 355 #endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */ 356 357 if (mon_conn) { 358 if (wpa_ctrl_attach(mon_conn) == 0) { 359 wpa_cli_attached = 1; 360 if (interactive) 361 eloop_register_read_sock( 362 wpa_ctrl_get_fd(mon_conn), 363 wpa_cli_mon_receive, NULL, NULL); 364 } else { 365 printf("Warning: Failed to attach to " 366 "wpa_supplicant.\n"); 367 wpa_cli_close_connection(); 368 return -1; 369 } 370 } 371 372 return 0; 373 } 374 375 376 static void wpa_cli_close_connection(void) 377 { 378 if (ctrl_conn == NULL) 379 return; 380 381 if (wpa_cli_attached) { 382 wpa_ctrl_detach(interactive ? mon_conn : ctrl_conn); 383 wpa_cli_attached = 0; 384 } 385 wpa_ctrl_close(ctrl_conn); 386 ctrl_conn = NULL; 387 if (mon_conn) { 388 eloop_unregister_read_sock(wpa_ctrl_get_fd(mon_conn)); 389 wpa_ctrl_close(mon_conn); 390 mon_conn = NULL; 391 } 392 } 393 394 395 static void wpa_cli_msg_cb(char *msg, size_t len) 396 { 397 printf("%s\n", msg); 398 } 399 400 401 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print) 402 { 403 char buf[2048]; 404 size_t len; 405 int ret; 406 407 if (ctrl_conn == NULL) { 408 printf("Not connected to wpa_supplicant - command dropped.\n"); 409 return -1; 410 } 411 len = sizeof(buf) - 1; 412 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, 413 wpa_cli_msg_cb); 414 if (ret == -2) { 415 printf("'%s' command timed out.\n", cmd); 416 return -2; 417 } else if (ret < 0) { 418 printf("'%s' command failed.\n", cmd); 419 return -1; 420 } 421 if (print) { 422 buf[len] = '\0'; 423 printf("%s", buf); 424 if (interactive && len > 0 && buf[len - 1] != '\n') 425 printf("\n"); 426 } 427 return 0; 428 } 429 430 431 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd) 432 { 433 return _wpa_ctrl_command(ctrl, cmd, 1); 434 } 435 436 437 static int write_cmd(char *buf, size_t buflen, const char *cmd, int argc, 438 char *argv[]) 439 { 440 int i, res; 441 char *pos, *end; 442 443 pos = buf; 444 end = buf + buflen; 445 446 res = os_snprintf(pos, end - pos, "%s", cmd); 447 if (res < 0 || res >= end - pos) 448 goto fail; 449 pos += res; 450 451 for (i = 0; i < argc; i++) { 452 res = os_snprintf(pos, end - pos, " %s", argv[i]); 453 if (res < 0 || res >= end - pos) 454 goto fail; 455 pos += res; 456 } 457 458 buf[buflen - 1] = '\0'; 459 return 0; 460 461 fail: 462 printf("Too long command\n"); 463 return -1; 464 } 465 466 467 static int wpa_cli_cmd(struct wpa_ctrl *ctrl, const char *cmd, int min_args, 468 int argc, char *argv[]) 469 { 470 char buf[256]; 471 if (argc < min_args) { 472 printf("Invalid %s command - at least %d argument%s " 473 "required.\n", cmd, min_args, 474 min_args > 1 ? "s are" : " is"); 475 return -1; 476 } 477 if (write_cmd(buf, sizeof(buf), cmd, argc, argv) < 0) 478 return -1; 479 return wpa_ctrl_command(ctrl, buf); 480 } 481 482 483 static int wpa_cli_cmd_ifname(struct wpa_ctrl *ctrl, int argc, char *argv[]) 484 { 485 return wpa_ctrl_command(ctrl, "IFNAME"); 486 } 487 488 489 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[]) 490 { 491 if (argc > 0 && os_strcmp(argv[0], "verbose") == 0) 492 return wpa_ctrl_command(ctrl, "STATUS-VERBOSE"); 493 if (argc > 0 && os_strcmp(argv[0], "wps") == 0) 494 return wpa_ctrl_command(ctrl, "STATUS-WPS"); 495 return wpa_ctrl_command(ctrl, "STATUS"); 496 } 497 498 499 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[]) 500 { 501 return wpa_ctrl_command(ctrl, "PING"); 502 } 503 504 505 static int wpa_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[]) 506 { 507 return wpa_ctrl_command(ctrl, "RELOG"); 508 } 509 510 511 static int wpa_cli_cmd_note(struct wpa_ctrl *ctrl, int argc, char *argv[]) 512 { 513 return wpa_cli_cmd(ctrl, "NOTE", 1, argc, argv); 514 } 515 516 517 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[]) 518 { 519 return wpa_ctrl_command(ctrl, "MIB"); 520 } 521 522 523 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[]) 524 { 525 return wpa_ctrl_command(ctrl, "PMKSA"); 526 } 527 528 529 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[]) 530 { 531 print_help(argc > 0 ? argv[0] : NULL); 532 return 0; 533 } 534 535 536 static char ** wpa_cli_complete_help(const char *str, int pos) 537 { 538 int arg = get_cmd_arg_num(str, pos); 539 char **res = NULL; 540 541 switch (arg) { 542 case 1: 543 res = wpa_list_cmd_list(); 544 break; 545 } 546 547 return res; 548 } 549 550 551 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[]) 552 { 553 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license); 554 return 0; 555 } 556 557 558 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[]) 559 { 560 wpa_cli_quit = 1; 561 if (interactive) 562 eloop_terminate(); 563 return 0; 564 } 565 566 567 static void wpa_cli_show_variables(void) 568 { 569 printf("set variables:\n" 570 " EAPOL::heldPeriod (EAPOL state machine held period, " 571 "in seconds)\n" 572 " EAPOL::authPeriod (EAPOL state machine authentication " 573 "period, in seconds)\n" 574 " EAPOL::startPeriod (EAPOL state machine start period, in " 575 "seconds)\n" 576 " EAPOL::maxStart (EAPOL state machine maximum start " 577 "attempts)\n"); 578 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in " 579 "seconds)\n" 580 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication" 581 " threshold\n\tpercentage)\n" 582 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing " 583 "security\n\tassociation in seconds)\n"); 584 } 585 586 587 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) 588 { 589 char cmd[256]; 590 int res; 591 592 if (argc == 0) { 593 wpa_cli_show_variables(); 594 return 0; 595 } 596 597 if (argc != 1 && argc != 2) { 598 printf("Invalid SET command: needs two arguments (variable " 599 "name and value)\n"); 600 return -1; 601 } 602 603 if (argc == 1) 604 res = os_snprintf(cmd, sizeof(cmd), "SET %s ", argv[0]); 605 else 606 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", 607 argv[0], argv[1]); 608 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 609 printf("Too long SET command.\n"); 610 return -1; 611 } 612 return wpa_ctrl_command(ctrl, cmd); 613 } 614 615 616 static int wpa_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[]) 617 { 618 return wpa_cli_cmd(ctrl, "GET", 1, argc, argv); 619 } 620 621 622 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[]) 623 { 624 return wpa_ctrl_command(ctrl, "LOGOFF"); 625 } 626 627 628 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[]) 629 { 630 return wpa_ctrl_command(ctrl, "LOGON"); 631 } 632 633 634 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc, 635 char *argv[]) 636 { 637 return wpa_ctrl_command(ctrl, "REASSOCIATE"); 638 } 639 640 641 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc, 642 char *argv[]) 643 { 644 return wpa_cli_cmd(ctrl, "PREAUTH", 1, argc, argv); 645 } 646 647 648 static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) 649 { 650 return wpa_cli_cmd(ctrl, "AP_SCAN", 1, argc, argv); 651 } 652 653 654 static int wpa_cli_cmd_scan_interval(struct wpa_ctrl *ctrl, int argc, 655 char *argv[]) 656 { 657 return wpa_cli_cmd(ctrl, "SCAN_INTERVAL", 1, argc, argv); 658 } 659 660 661 static int wpa_cli_cmd_bss_expire_age(struct wpa_ctrl *ctrl, int argc, 662 char *argv[]) 663 { 664 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_AGE", 1, argc, argv); 665 } 666 667 668 static int wpa_cli_cmd_bss_expire_count(struct wpa_ctrl *ctrl, int argc, 669 char *argv[]) 670 { 671 return wpa_cli_cmd(ctrl, "BSS_EXPIRE_COUNT", 1, argc, argv); 672 } 673 674 675 static int wpa_cli_cmd_bss_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) 676 { 677 char cmd[256]; 678 int res; 679 680 if (argc < 1) 681 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH 0"); 682 else 683 res = os_snprintf(cmd, sizeof(cmd), "BSS_FLUSH %s", argv[0]); 684 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 685 printf("Too long BSS_FLUSH command.\n"); 686 return -1; 687 } 688 return wpa_ctrl_command(ctrl, cmd); 689 } 690 691 692 static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc, 693 char *argv[]) 694 { 695 return wpa_cli_cmd(ctrl, "STKSTART", 1, argc, argv); 696 } 697 698 699 static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[]) 700 { 701 return wpa_cli_cmd(ctrl, "FT_DS", 1, argc, argv); 702 } 703 704 705 static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[]) 706 { 707 return wpa_cli_cmd(ctrl, "WPS_PBC", 0, argc, argv); 708 } 709 710 711 static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) 712 { 713 if (argc == 0) { 714 printf("Invalid WPS_PIN command: need one or two arguments:\n" 715 "- BSSID: use 'any' to select any\n" 716 "- PIN: optional, used only with devices that have no " 717 "display\n"); 718 return -1; 719 } 720 721 return wpa_cli_cmd(ctrl, "WPS_PIN", 1, argc, argv); 722 } 723 724 725 static int wpa_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc, 726 char *argv[]) 727 { 728 return wpa_cli_cmd(ctrl, "WPS_CHECK_PIN", 1, argc, argv); 729 } 730 731 732 static int wpa_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc, 733 char *argv[]) 734 { 735 return wpa_ctrl_command(ctrl, "WPS_CANCEL"); 736 } 737 738 739 #ifdef CONFIG_WPS_NFC 740 741 static int wpa_cli_cmd_wps_nfc(struct wpa_ctrl *ctrl, int argc, char *argv[]) 742 { 743 return wpa_cli_cmd(ctrl, "WPS_NFC", 0, argc, argv); 744 } 745 746 747 static int wpa_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl, int argc, 748 char *argv[]) 749 { 750 return wpa_cli_cmd(ctrl, "WPS_NFC_TOKEN", 1, argc, argv); 751 } 752 753 754 static int wpa_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc, 755 char *argv[]) 756 { 757 int ret; 758 char *buf; 759 size_t buflen; 760 761 if (argc != 1) { 762 printf("Invalid 'wps_nfc_tag_read' command - one argument " 763 "is required.\n"); 764 return -1; 765 } 766 767 buflen = 18 + os_strlen(argv[0]); 768 buf = os_malloc(buflen); 769 if (buf == NULL) 770 return -1; 771 os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]); 772 773 ret = wpa_ctrl_command(ctrl, buf); 774 os_free(buf); 775 776 return ret; 777 } 778 779 780 static int wpa_cli_cmd_nfc_get_handover_req(struct wpa_ctrl *ctrl, int argc, 781 char *argv[]) 782 { 783 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_REQ", 2, argc, argv); 784 } 785 786 787 static int wpa_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl, int argc, 788 char *argv[]) 789 { 790 return wpa_cli_cmd(ctrl, "NFC_GET_HANDOVER_SEL", 2, argc, argv); 791 } 792 793 794 static int wpa_cli_cmd_nfc_rx_handover_req(struct wpa_ctrl *ctrl, int argc, 795 char *argv[]) 796 { 797 int ret; 798 char *buf; 799 size_t buflen; 800 801 if (argc != 1) { 802 printf("Invalid 'nfc_rx_handover_req' command - one argument " 803 "is required.\n"); 804 return -1; 805 } 806 807 buflen = 21 + os_strlen(argv[0]); 808 buf = os_malloc(buflen); 809 if (buf == NULL) 810 return -1; 811 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_REQ %s", argv[0]); 812 813 ret = wpa_ctrl_command(ctrl, buf); 814 os_free(buf); 815 816 return ret; 817 } 818 819 820 static int wpa_cli_cmd_nfc_rx_handover_sel(struct wpa_ctrl *ctrl, int argc, 821 char *argv[]) 822 { 823 int ret; 824 char *buf; 825 size_t buflen; 826 827 if (argc != 1) { 828 printf("Invalid 'nfc_rx_handover_sel' command - one argument " 829 "is required.\n"); 830 return -1; 831 } 832 833 buflen = 21 + os_strlen(argv[0]); 834 buf = os_malloc(buflen); 835 if (buf == NULL) 836 return -1; 837 os_snprintf(buf, buflen, "NFC_RX_HANDOVER_SEL %s", argv[0]); 838 839 ret = wpa_ctrl_command(ctrl, buf); 840 os_free(buf); 841 842 return ret; 843 } 844 845 #endif /* CONFIG_WPS_NFC */ 846 847 848 static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[]) 849 { 850 char cmd[256]; 851 int res; 852 853 if (argc == 2) 854 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", 855 argv[0], argv[1]); 856 else if (argc == 5 || argc == 6) { 857 char ssid_hex[2 * 32 + 1]; 858 char key_hex[2 * 64 + 1]; 859 int i; 860 861 ssid_hex[0] = '\0'; 862 for (i = 0; i < 32; i++) { 863 if (argv[2][i] == '\0') 864 break; 865 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]); 866 } 867 868 key_hex[0] = '\0'; 869 if (argc == 6) { 870 for (i = 0; i < 64; i++) { 871 if (argv[5][i] == '\0') 872 break; 873 os_snprintf(&key_hex[i * 2], 3, "%02x", 874 argv[5][i]); 875 } 876 } 877 878 res = os_snprintf(cmd, sizeof(cmd), 879 "WPS_REG %s %s %s %s %s %s", 880 argv[0], argv[1], ssid_hex, argv[3], argv[4], 881 key_hex); 882 } else { 883 printf("Invalid WPS_REG command: need two arguments:\n" 884 "- BSSID of the target AP\n" 885 "- AP PIN\n"); 886 printf("Alternatively, six arguments can be used to " 887 "reconfigure the AP:\n" 888 "- BSSID of the target AP\n" 889 "- AP PIN\n" 890 "- new SSID\n" 891 "- new auth (OPEN, WPAPSK, WPA2PSK)\n" 892 "- new encr (NONE, WEP, TKIP, CCMP)\n" 893 "- new key\n"); 894 return -1; 895 } 896 897 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 898 printf("Too long WPS_REG command.\n"); 899 return -1; 900 } 901 return wpa_ctrl_command(ctrl, cmd); 902 } 903 904 905 static int wpa_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc, 906 char *argv[]) 907 { 908 return wpa_cli_cmd(ctrl, "WPS_AP_PIN", 1, argc, argv); 909 } 910 911 912 static int wpa_cli_cmd_wps_er_start(struct wpa_ctrl *ctrl, int argc, 913 char *argv[]) 914 { 915 return wpa_cli_cmd(ctrl, "WPS_ER_START", 0, argc, argv); 916 } 917 918 919 static int wpa_cli_cmd_wps_er_stop(struct wpa_ctrl *ctrl, int argc, 920 char *argv[]) 921 { 922 return wpa_ctrl_command(ctrl, "WPS_ER_STOP"); 923 924 } 925 926 927 static int wpa_cli_cmd_wps_er_pin(struct wpa_ctrl *ctrl, int argc, 928 char *argv[]) 929 { 930 if (argc < 2) { 931 printf("Invalid WPS_ER_PIN command: need at least two " 932 "arguments:\n" 933 "- UUID: use 'any' to select any\n" 934 "- PIN: Enrollee PIN\n" 935 "optional: - Enrollee MAC address\n"); 936 return -1; 937 } 938 939 return wpa_cli_cmd(ctrl, "WPS_ER_PIN", 2, argc, argv); 940 } 941 942 943 static int wpa_cli_cmd_wps_er_pbc(struct wpa_ctrl *ctrl, int argc, 944 char *argv[]) 945 { 946 return wpa_cli_cmd(ctrl, "WPS_ER_PBC", 1, argc, argv); 947 } 948 949 950 static int wpa_cli_cmd_wps_er_learn(struct wpa_ctrl *ctrl, int argc, 951 char *argv[]) 952 { 953 if (argc != 2) { 954 printf("Invalid WPS_ER_LEARN command: need two arguments:\n" 955 "- UUID: specify which AP to use\n" 956 "- PIN: AP PIN\n"); 957 return -1; 958 } 959 960 return wpa_cli_cmd(ctrl, "WPS_ER_LEARN", 2, argc, argv); 961 } 962 963 964 static int wpa_cli_cmd_wps_er_set_config(struct wpa_ctrl *ctrl, int argc, 965 char *argv[]) 966 { 967 if (argc != 2) { 968 printf("Invalid WPS_ER_SET_CONFIG command: need two " 969 "arguments:\n" 970 "- UUID: specify which AP to use\n" 971 "- Network configuration id\n"); 972 return -1; 973 } 974 975 return wpa_cli_cmd(ctrl, "WPS_ER_SET_CONFIG", 2, argc, argv); 976 } 977 978 979 static int wpa_cli_cmd_wps_er_config(struct wpa_ctrl *ctrl, int argc, 980 char *argv[]) 981 { 982 char cmd[256]; 983 int res; 984 985 if (argc == 5 || argc == 6) { 986 char ssid_hex[2 * 32 + 1]; 987 char key_hex[2 * 64 + 1]; 988 int i; 989 990 ssid_hex[0] = '\0'; 991 for (i = 0; i < 32; i++) { 992 if (argv[2][i] == '\0') 993 break; 994 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[2][i]); 995 } 996 997 key_hex[0] = '\0'; 998 if (argc == 6) { 999 for (i = 0; i < 64; i++) { 1000 if (argv[5][i] == '\0') 1001 break; 1002 os_snprintf(&key_hex[i * 2], 3, "%02x", 1003 argv[5][i]); 1004 } 1005 } 1006 1007 res = os_snprintf(cmd, sizeof(cmd), 1008 "WPS_ER_CONFIG %s %s %s %s %s %s", 1009 argv[0], argv[1], ssid_hex, argv[3], argv[4], 1010 key_hex); 1011 } else { 1012 printf("Invalid WPS_ER_CONFIG command: need six arguments:\n" 1013 "- AP UUID\n" 1014 "- AP PIN\n" 1015 "- new SSID\n" 1016 "- new auth (OPEN, WPAPSK, WPA2PSK)\n" 1017 "- new encr (NONE, WEP, TKIP, CCMP)\n" 1018 "- new key\n"); 1019 return -1; 1020 } 1021 1022 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) { 1023 printf("Too long WPS_ER_CONFIG command.\n"); 1024 return -1; 1025 } 1026 return wpa_ctrl_command(ctrl, cmd); 1027 } 1028 1029 1030 #ifdef CONFIG_WPS_NFC 1031 static int wpa_cli_cmd_wps_er_nfc_config_token(struct wpa_ctrl *ctrl, int argc, 1032 char *argv[]) 1033 { 1034 if (argc != 2) { 1035 printf("Invalid WPS_ER_NFC_CONFIG_TOKEN command: need two " 1036 "arguments:\n" 1037 "- WPS/NDEF: token format\n" 1038 "- UUID: specify which AP to use\n"); 1039 return -1; 1040 } 1041 1042 return wpa_cli_cmd(ctrl, "WPS_ER_NFC_CONFIG_TOKEN", 2, argc, argv); 1043 } 1044 #endif /* CONFIG_WPS_NFC */ 1045 1046 1047 static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1048 { 1049 return wpa_cli_cmd(ctrl, "IBSS_RSN", 1, argc, argv); 1050 } 1051 1052 1053 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1054 { 1055 return wpa_cli_cmd(ctrl, "LEVEL", 1, argc, argv); 1056 } 1057 1058 1059 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1060 { 1061 char cmd[256], *pos, *end; 1062 int i, ret; 1063 1064 if (argc < 2) { 1065 printf("Invalid IDENTITY command: needs two arguments " 1066 "(network id and identity)\n"); 1067 return -1; 1068 } 1069 1070 end = cmd + sizeof(cmd); 1071 pos = cmd; 1072 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s", 1073 argv[0], argv[1]); 1074 if (ret < 0 || ret >= end - pos) { 1075 printf("Too long IDENTITY command.\n"); 1076 return -1; 1077 } 1078 pos += ret; 1079 for (i = 2; i < argc; i++) { 1080 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 1081 if (ret < 0 || ret >= end - pos) { 1082 printf("Too long IDENTITY command.\n"); 1083 return -1; 1084 } 1085 pos += ret; 1086 } 1087 1088 return wpa_ctrl_command(ctrl, cmd); 1089 } 1090 1091 1092 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1093 { 1094 char cmd[256], *pos, *end; 1095 int i, ret; 1096 1097 if (argc < 2) { 1098 printf("Invalid PASSWORD command: needs two arguments " 1099 "(network id and password)\n"); 1100 return -1; 1101 } 1102 1103 end = cmd + sizeof(cmd); 1104 pos = cmd; 1105 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s", 1106 argv[0], argv[1]); 1107 if (ret < 0 || ret >= end - pos) { 1108 printf("Too long PASSWORD command.\n"); 1109 return -1; 1110 } 1111 pos += ret; 1112 for (i = 2; i < argc; i++) { 1113 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 1114 if (ret < 0 || ret >= end - pos) { 1115 printf("Too long PASSWORD command.\n"); 1116 return -1; 1117 } 1118 pos += ret; 1119 } 1120 1121 return wpa_ctrl_command(ctrl, cmd); 1122 } 1123 1124 1125 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc, 1126 char *argv[]) 1127 { 1128 char cmd[256], *pos, *end; 1129 int i, ret; 1130 1131 if (argc < 2) { 1132 printf("Invalid NEW_PASSWORD command: needs two arguments " 1133 "(network id and password)\n"); 1134 return -1; 1135 } 1136 1137 end = cmd + sizeof(cmd); 1138 pos = cmd; 1139 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s", 1140 argv[0], argv[1]); 1141 if (ret < 0 || ret >= end - pos) { 1142 printf("Too long NEW_PASSWORD command.\n"); 1143 return -1; 1144 } 1145 pos += ret; 1146 for (i = 2; i < argc; i++) { 1147 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 1148 if (ret < 0 || ret >= end - pos) { 1149 printf("Too long NEW_PASSWORD command.\n"); 1150 return -1; 1151 } 1152 pos += ret; 1153 } 1154 1155 return wpa_ctrl_command(ctrl, cmd); 1156 } 1157 1158 1159 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1160 { 1161 char cmd[256], *pos, *end; 1162 int i, ret; 1163 1164 if (argc < 2) { 1165 printf("Invalid PIN command: needs two arguments " 1166 "(network id and pin)\n"); 1167 return -1; 1168 } 1169 1170 end = cmd + sizeof(cmd); 1171 pos = cmd; 1172 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s", 1173 argv[0], argv[1]); 1174 if (ret < 0 || ret >= end - pos) { 1175 printf("Too long PIN command.\n"); 1176 return -1; 1177 } 1178 pos += ret; 1179 for (i = 2; i < argc; i++) { 1180 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 1181 if (ret < 0 || ret >= end - pos) { 1182 printf("Too long PIN command.\n"); 1183 return -1; 1184 } 1185 pos += ret; 1186 } 1187 return wpa_ctrl_command(ctrl, cmd); 1188 } 1189 1190 1191 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1192 { 1193 char cmd[256], *pos, *end; 1194 int i, ret; 1195 1196 if (argc < 2) { 1197 printf("Invalid OTP command: needs two arguments (network " 1198 "id and password)\n"); 1199 return -1; 1200 } 1201 1202 end = cmd + sizeof(cmd); 1203 pos = cmd; 1204 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s", 1205 argv[0], argv[1]); 1206 if (ret < 0 || ret >= end - pos) { 1207 printf("Too long OTP command.\n"); 1208 return -1; 1209 } 1210 pos += ret; 1211 for (i = 2; i < argc; i++) { 1212 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 1213 if (ret < 0 || ret >= end - pos) { 1214 printf("Too long OTP command.\n"); 1215 return -1; 1216 } 1217 pos += ret; 1218 } 1219 1220 return wpa_ctrl_command(ctrl, cmd); 1221 } 1222 1223 1224 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc, 1225 char *argv[]) 1226 { 1227 char cmd[256], *pos, *end; 1228 int i, ret; 1229 1230 if (argc < 2) { 1231 printf("Invalid PASSPHRASE command: needs two arguments " 1232 "(network id and passphrase)\n"); 1233 return -1; 1234 } 1235 1236 end = cmd + sizeof(cmd); 1237 pos = cmd; 1238 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s", 1239 argv[0], argv[1]); 1240 if (ret < 0 || ret >= end - pos) { 1241 printf("Too long PASSPHRASE command.\n"); 1242 return -1; 1243 } 1244 pos += ret; 1245 for (i = 2; i < argc; i++) { 1246 ret = os_snprintf(pos, end - pos, " %s", argv[i]); 1247 if (ret < 0 || ret >= end - pos) { 1248 printf("Too long PASSPHRASE command.\n"); 1249 return -1; 1250 } 1251 pos += ret; 1252 } 1253 1254 return wpa_ctrl_command(ctrl, cmd); 1255 } 1256 1257 1258 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1259 { 1260 if (argc < 2) { 1261 printf("Invalid BSSID command: needs two arguments (network " 1262 "id and BSSID)\n"); 1263 return -1; 1264 } 1265 1266 return wpa_cli_cmd(ctrl, "BSSID", 2, argc, argv); 1267 } 1268 1269 1270 static int wpa_cli_cmd_blacklist(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1271 { 1272 return wpa_cli_cmd(ctrl, "BLACKLIST", 0, argc, argv); 1273 } 1274 1275 1276 static int wpa_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1277 { 1278 return wpa_cli_cmd(ctrl, "LOG_LEVEL", 0, argc, argv); 1279 } 1280 1281 1282 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc, 1283 char *argv[]) 1284 { 1285 return wpa_ctrl_command(ctrl, "LIST_NETWORKS"); 1286 } 1287 1288 1289 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc, 1290 char *argv[]) 1291 { 1292 return wpa_cli_cmd(ctrl, "SELECT_NETWORK", 1, argc, argv); 1293 } 1294 1295 1296 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc, 1297 char *argv[]) 1298 { 1299 return wpa_cli_cmd(ctrl, "ENABLE_NETWORK", 1, argc, argv); 1300 } 1301 1302 1303 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc, 1304 char *argv[]) 1305 { 1306 return wpa_cli_cmd(ctrl, "DISABLE_NETWORK", 1, argc, argv); 1307 } 1308 1309 1310 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc, 1311 char *argv[]) 1312 { 1313 return wpa_ctrl_command(ctrl, "ADD_NETWORK"); 1314 } 1315 1316 1317 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc, 1318 char *argv[]) 1319 { 1320 return wpa_cli_cmd(ctrl, "REMOVE_NETWORK", 1, argc, argv); 1321 } 1322 1323 1324 static void wpa_cli_show_network_variables(void) 1325 { 1326 printf("set_network variables:\n" 1327 " ssid (network name, SSID)\n" 1328 " psk (WPA passphrase or pre-shared key)\n" 1329 " key_mgmt (key management protocol)\n" 1330 " identity (EAP identity)\n" 1331 " password (EAP password)\n" 1332 " ...\n" 1333 "\n" 1334 "Note: Values are entered in the same format as the " 1335 "configuration file is using,\n" 1336 "i.e., strings values need to be inside double quotation " 1337 "marks.\n" 1338 "For example: set_network 1 ssid \"network name\"\n" 1339 "\n" 1340 "Please see wpa_supplicant.conf documentation for full list " 1341 "of\navailable variables.\n"); 1342 } 1343 1344 1345 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc, 1346 char *argv[]) 1347 { 1348 if (argc == 0) { 1349 wpa_cli_show_network_variables(); 1350 return 0; 1351 } 1352 1353 if (argc < 3) { 1354 printf("Invalid SET_NETWORK command: needs three arguments\n" 1355 "(network id, variable name, and value)\n"); 1356 return -1; 1357 } 1358 1359 return wpa_cli_cmd(ctrl, "SET_NETWORK", 3, argc, argv); 1360 } 1361 1362 1363 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc, 1364 char *argv[]) 1365 { 1366 if (argc == 0) { 1367 wpa_cli_show_network_variables(); 1368 return 0; 1369 } 1370 1371 if (argc != 2) { 1372 printf("Invalid GET_NETWORK command: needs two arguments\n" 1373 "(network id and variable name)\n"); 1374 return -1; 1375 } 1376 1377 return wpa_cli_cmd(ctrl, "GET_NETWORK", 2, argc, argv); 1378 } 1379 1380 1381 static int wpa_cli_cmd_list_creds(struct wpa_ctrl *ctrl, int argc, 1382 char *argv[]) 1383 { 1384 return wpa_ctrl_command(ctrl, "LIST_CREDS"); 1385 } 1386 1387 1388 static int wpa_cli_cmd_add_cred(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1389 { 1390 return wpa_ctrl_command(ctrl, "ADD_CRED"); 1391 } 1392 1393 1394 static int wpa_cli_cmd_remove_cred(struct wpa_ctrl *ctrl, int argc, 1395 char *argv[]) 1396 { 1397 return wpa_cli_cmd(ctrl, "REMOVE_CRED", 1, argc, argv); 1398 } 1399 1400 1401 static int wpa_cli_cmd_set_cred(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1402 { 1403 if (argc != 3) { 1404 printf("Invalid SET_CRED command: needs three arguments\n" 1405 "(cred id, variable name, and value)\n"); 1406 return -1; 1407 } 1408 1409 return wpa_cli_cmd(ctrl, "SET_CRED", 3, argc, argv); 1410 } 1411 1412 1413 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc, 1414 char *argv[]) 1415 { 1416 return wpa_ctrl_command(ctrl, "DISCONNECT"); 1417 } 1418 1419 1420 static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc, 1421 char *argv[]) 1422 { 1423 return wpa_ctrl_command(ctrl, "RECONNECT"); 1424 } 1425 1426 1427 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc, 1428 char *argv[]) 1429 { 1430 return wpa_ctrl_command(ctrl, "SAVE_CONFIG"); 1431 } 1432 1433 1434 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1435 { 1436 return wpa_ctrl_command(ctrl, "SCAN"); 1437 } 1438 1439 1440 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc, 1441 char *argv[]) 1442 { 1443 return wpa_ctrl_command(ctrl, "SCAN_RESULTS"); 1444 } 1445 1446 1447 static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1448 { 1449 return wpa_cli_cmd(ctrl, "BSS", 1, argc, argv); 1450 } 1451 1452 1453 static char ** wpa_cli_complete_bss(const char *str, int pos) 1454 { 1455 int arg = get_cmd_arg_num(str, pos); 1456 char **res = NULL; 1457 1458 switch (arg) { 1459 case 1: 1460 res = cli_txt_list_array(&bsses); 1461 break; 1462 } 1463 1464 return res; 1465 } 1466 1467 1468 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc, 1469 char *argv[]) 1470 { 1471 if (argc < 1 || argc > 2) { 1472 printf("Invalid GET_CAPABILITY command: need either one or " 1473 "two arguments\n"); 1474 return -1; 1475 } 1476 1477 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) { 1478 printf("Invalid GET_CAPABILITY command: second argument, " 1479 "if any, must be 'strict'\n"); 1480 return -1; 1481 } 1482 1483 return wpa_cli_cmd(ctrl, "GET_CAPABILITY", 1, argc, argv); 1484 } 1485 1486 1487 static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl) 1488 { 1489 printf("Available interfaces:\n"); 1490 return wpa_ctrl_command(ctrl, "INTERFACES"); 1491 } 1492 1493 1494 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1495 { 1496 if (argc < 1) { 1497 wpa_cli_list_interfaces(ctrl); 1498 return 0; 1499 } 1500 1501 wpa_cli_close_connection(); 1502 os_free(ctrl_ifname); 1503 ctrl_ifname = os_strdup(argv[0]); 1504 1505 if (wpa_cli_open_connection(ctrl_ifname, 1)) { 1506 printf("Connected to interface '%s.\n", ctrl_ifname); 1507 } else { 1508 printf("Could not connect to interface '%s' - re-trying\n", 1509 ctrl_ifname); 1510 } 1511 return 0; 1512 } 1513 1514 1515 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc, 1516 char *argv[]) 1517 { 1518 return wpa_ctrl_command(ctrl, "RECONFIGURE"); 1519 } 1520 1521 1522 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc, 1523 char *argv[]) 1524 { 1525 return wpa_ctrl_command(ctrl, "TERMINATE"); 1526 } 1527 1528 1529 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc, 1530 char *argv[]) 1531 { 1532 char cmd[256]; 1533 int res; 1534 1535 if (argc < 1) { 1536 printf("Invalid INTERFACE_ADD command: needs at least one " 1537 "argument (interface name)\n" 1538 "All arguments: ifname confname driver ctrl_interface " 1539 "driver_param bridge_name\n"); 1540 return -1; 1541 } 1542 1543 /* 1544 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB 1545 * <driver_param>TAB<bridge_name> 1546 */ 1547 res = os_snprintf(cmd, sizeof(cmd), 1548 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s", 1549 argv[0], 1550 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "", 1551 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "", 1552 argc > 5 ? argv[5] : ""); 1553 if (res < 0 || (size_t) res >= sizeof(cmd)) 1554 return -1; 1555 cmd[sizeof(cmd) - 1] = '\0'; 1556 return wpa_ctrl_command(ctrl, cmd); 1557 } 1558 1559 1560 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc, 1561 char *argv[]) 1562 { 1563 return wpa_cli_cmd(ctrl, "INTERFACE_REMOVE", 1, argc, argv); 1564 } 1565 1566 1567 static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc, 1568 char *argv[]) 1569 { 1570 return wpa_ctrl_command(ctrl, "INTERFACE_LIST"); 1571 } 1572 1573 1574 #ifdef CONFIG_AP 1575 static int wpa_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1576 { 1577 return wpa_cli_cmd(ctrl, "STA", 1, argc, argv); 1578 } 1579 1580 1581 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd, 1582 char *addr, size_t addr_len) 1583 { 1584 char buf[4096], *pos; 1585 size_t len; 1586 int ret; 1587 1588 if (ctrl_conn == NULL) { 1589 printf("Not connected to hostapd - command dropped.\n"); 1590 return -1; 1591 } 1592 len = sizeof(buf) - 1; 1593 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, 1594 wpa_cli_msg_cb); 1595 if (ret == -2) { 1596 printf("'%s' command timed out.\n", cmd); 1597 return -2; 1598 } else if (ret < 0) { 1599 printf("'%s' command failed.\n", cmd); 1600 return -1; 1601 } 1602 1603 buf[len] = '\0'; 1604 if (os_memcmp(buf, "FAIL", 4) == 0) 1605 return -1; 1606 printf("%s", buf); 1607 1608 pos = buf; 1609 while (*pos != '\0' && *pos != '\n') 1610 pos++; 1611 *pos = '\0'; 1612 os_strlcpy(addr, buf, addr_len); 1613 return 0; 1614 } 1615 1616 1617 static int wpa_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1618 { 1619 char addr[32], cmd[64]; 1620 1621 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr))) 1622 return 0; 1623 do { 1624 os_snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr); 1625 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0); 1626 1627 return -1; 1628 } 1629 1630 1631 static int wpa_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc, 1632 char *argv[]) 1633 { 1634 return wpa_cli_cmd(ctrl, "DEAUTHENTICATE", 1, argc, argv); 1635 } 1636 1637 1638 static int wpa_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc, 1639 char *argv[]) 1640 { 1641 return wpa_cli_cmd(ctrl, "DISASSOCIATE", 1, argc, argv); 1642 } 1643 #endif /* CONFIG_AP */ 1644 1645 1646 static int wpa_cli_cmd_suspend(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1647 { 1648 return wpa_ctrl_command(ctrl, "SUSPEND"); 1649 } 1650 1651 1652 static int wpa_cli_cmd_resume(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1653 { 1654 return wpa_ctrl_command(ctrl, "RESUME"); 1655 } 1656 1657 1658 static int wpa_cli_cmd_drop_sa(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1659 { 1660 return wpa_ctrl_command(ctrl, "DROP_SA"); 1661 } 1662 1663 1664 static int wpa_cli_cmd_roam(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1665 { 1666 return wpa_cli_cmd(ctrl, "ROAM", 1, argc, argv); 1667 } 1668 1669 1670 #ifdef CONFIG_P2P 1671 1672 static int wpa_cli_cmd_p2p_find(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1673 { 1674 return wpa_cli_cmd(ctrl, "P2P_FIND", 0, argc, argv); 1675 } 1676 1677 1678 static char ** wpa_cli_complete_p2p_find(const char *str, int pos) 1679 { 1680 char **res = NULL; 1681 int arg = get_cmd_arg_num(str, pos); 1682 1683 res = os_calloc(6, sizeof(char *)); 1684 if (res == NULL) 1685 return NULL; 1686 res[0] = os_strdup("type=social"); 1687 if (res[0] == NULL) { 1688 os_free(res); 1689 return NULL; 1690 } 1691 res[1] = os_strdup("type=progressive"); 1692 if (res[1] == NULL) 1693 return res; 1694 res[2] = os_strdup("delay="); 1695 if (res[2] == NULL) 1696 return res; 1697 res[3] = os_strdup("dev_id="); 1698 if (res[3] == NULL) 1699 return res; 1700 if (arg == 1) 1701 res[4] = os_strdup("[timeout]"); 1702 1703 return res; 1704 } 1705 1706 1707 static int wpa_cli_cmd_p2p_stop_find(struct wpa_ctrl *ctrl, int argc, 1708 char *argv[]) 1709 { 1710 return wpa_ctrl_command(ctrl, "P2P_STOP_FIND"); 1711 } 1712 1713 1714 static int wpa_cli_cmd_p2p_connect(struct wpa_ctrl *ctrl, int argc, 1715 char *argv[]) 1716 { 1717 return wpa_cli_cmd(ctrl, "P2P_CONNECT", 2, argc, argv); 1718 } 1719 1720 1721 static char ** wpa_cli_complete_p2p_connect(const char *str, int pos) 1722 { 1723 int arg = get_cmd_arg_num(str, pos); 1724 char **res = NULL; 1725 1726 switch (arg) { 1727 case 1: 1728 res = cli_txt_list_array(&p2p_peers); 1729 break; 1730 } 1731 1732 return res; 1733 } 1734 1735 1736 static int wpa_cli_cmd_p2p_listen(struct wpa_ctrl *ctrl, int argc, 1737 char *argv[]) 1738 { 1739 return wpa_cli_cmd(ctrl, "P2P_LISTEN", 0, argc, argv); 1740 } 1741 1742 1743 static int wpa_cli_cmd_p2p_group_remove(struct wpa_ctrl *ctrl, int argc, 1744 char *argv[]) 1745 { 1746 return wpa_cli_cmd(ctrl, "P2P_GROUP_REMOVE", 1, argc, argv); 1747 } 1748 1749 1750 static char ** wpa_cli_complete_p2p_group_remove(const char *str, int pos) 1751 { 1752 int arg = get_cmd_arg_num(str, pos); 1753 char **res = NULL; 1754 1755 switch (arg) { 1756 case 1: 1757 res = cli_txt_list_array(&p2p_groups); 1758 break; 1759 } 1760 1761 return res; 1762 } 1763 1764 1765 static int wpa_cli_cmd_p2p_group_add(struct wpa_ctrl *ctrl, int argc, 1766 char *argv[]) 1767 { 1768 return wpa_cli_cmd(ctrl, "P2P_GROUP_ADD", 0, argc, argv); 1769 } 1770 1771 1772 static int wpa_cli_cmd_p2p_prov_disc(struct wpa_ctrl *ctrl, int argc, 1773 char *argv[]) 1774 { 1775 if (argc != 2 && argc != 3) { 1776 printf("Invalid P2P_PROV_DISC command: needs at least " 1777 "two arguments, address and config method\n" 1778 "(display, keypad, or pbc) and an optional join\n"); 1779 return -1; 1780 } 1781 1782 return wpa_cli_cmd(ctrl, "P2P_PROV_DISC", 2, argc, argv); 1783 } 1784 1785 1786 static int wpa_cli_cmd_p2p_get_passphrase(struct wpa_ctrl *ctrl, int argc, 1787 char *argv[]) 1788 { 1789 return wpa_ctrl_command(ctrl, "P2P_GET_PASSPHRASE"); 1790 } 1791 1792 1793 static int wpa_cli_cmd_p2p_serv_disc_req(struct wpa_ctrl *ctrl, int argc, 1794 char *argv[]) 1795 { 1796 char cmd[4096]; 1797 1798 if (argc != 2 && argc != 4) { 1799 printf("Invalid P2P_SERV_DISC_REQ command: needs two " 1800 "arguments (address and TLVs) or four arguments " 1801 "(address, \"upnp\", version, search target " 1802 "(SSDP ST:)\n"); 1803 return -1; 1804 } 1805 1806 if (write_cmd(cmd, sizeof(cmd), "P2P_SERV_DISC_REQ", argc, argv) < 0) 1807 return -1; 1808 return wpa_ctrl_command(ctrl, cmd); 1809 } 1810 1811 1812 static int wpa_cli_cmd_p2p_serv_disc_cancel_req(struct wpa_ctrl *ctrl, 1813 int argc, char *argv[]) 1814 { 1815 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_CANCEL_REQ", 1, argc, argv); 1816 } 1817 1818 1819 static int wpa_cli_cmd_p2p_serv_disc_resp(struct wpa_ctrl *ctrl, int argc, 1820 char *argv[]) 1821 { 1822 char cmd[4096]; 1823 int res; 1824 1825 if (argc != 4) { 1826 printf("Invalid P2P_SERV_DISC_RESP command: needs four " 1827 "arguments (freq, address, dialog token, and TLVs)\n"); 1828 return -1; 1829 } 1830 1831 res = os_snprintf(cmd, sizeof(cmd), "P2P_SERV_DISC_RESP %s %s %s %s", 1832 argv[0], argv[1], argv[2], argv[3]); 1833 if (res < 0 || (size_t) res >= sizeof(cmd)) 1834 return -1; 1835 cmd[sizeof(cmd) - 1] = '\0'; 1836 return wpa_ctrl_command(ctrl, cmd); 1837 } 1838 1839 1840 static int wpa_cli_cmd_p2p_service_update(struct wpa_ctrl *ctrl, int argc, 1841 char *argv[]) 1842 { 1843 return wpa_ctrl_command(ctrl, "P2P_SERVICE_UPDATE"); 1844 } 1845 1846 1847 static int wpa_cli_cmd_p2p_serv_disc_external(struct wpa_ctrl *ctrl, 1848 int argc, char *argv[]) 1849 { 1850 return wpa_cli_cmd(ctrl, "P2P_SERV_DISC_EXTERNAL", 1, argc, argv); 1851 } 1852 1853 1854 static int wpa_cli_cmd_p2p_service_flush(struct wpa_ctrl *ctrl, int argc, 1855 char *argv[]) 1856 { 1857 return wpa_ctrl_command(ctrl, "P2P_SERVICE_FLUSH"); 1858 } 1859 1860 1861 static int wpa_cli_cmd_p2p_service_add(struct wpa_ctrl *ctrl, int argc, 1862 char *argv[]) 1863 { 1864 char cmd[4096]; 1865 int res; 1866 1867 if (argc != 3 && argc != 4) { 1868 printf("Invalid P2P_SERVICE_ADD command: needs three or four " 1869 "arguments\n"); 1870 return -1; 1871 } 1872 1873 if (argc == 4) 1874 res = os_snprintf(cmd, sizeof(cmd), 1875 "P2P_SERVICE_ADD %s %s %s %s", 1876 argv[0], argv[1], argv[2], argv[3]); 1877 else 1878 res = os_snprintf(cmd, sizeof(cmd), 1879 "P2P_SERVICE_ADD %s %s %s", 1880 argv[0], argv[1], argv[2]); 1881 if (res < 0 || (size_t) res >= sizeof(cmd)) 1882 return -1; 1883 cmd[sizeof(cmd) - 1] = '\0'; 1884 return wpa_ctrl_command(ctrl, cmd); 1885 } 1886 1887 1888 static int wpa_cli_cmd_p2p_service_del(struct wpa_ctrl *ctrl, int argc, 1889 char *argv[]) 1890 { 1891 char cmd[4096]; 1892 int res; 1893 1894 if (argc != 2 && argc != 3) { 1895 printf("Invalid P2P_SERVICE_DEL command: needs two or three " 1896 "arguments\n"); 1897 return -1; 1898 } 1899 1900 if (argc == 3) 1901 res = os_snprintf(cmd, sizeof(cmd), 1902 "P2P_SERVICE_DEL %s %s %s", 1903 argv[0], argv[1], argv[2]); 1904 else 1905 res = os_snprintf(cmd, sizeof(cmd), 1906 "P2P_SERVICE_DEL %s %s", 1907 argv[0], argv[1]); 1908 if (res < 0 || (size_t) res >= sizeof(cmd)) 1909 return -1; 1910 cmd[sizeof(cmd) - 1] = '\0'; 1911 return wpa_ctrl_command(ctrl, cmd); 1912 } 1913 1914 1915 static int wpa_cli_cmd_p2p_reject(struct wpa_ctrl *ctrl, 1916 int argc, char *argv[]) 1917 { 1918 return wpa_cli_cmd(ctrl, "P2P_REJECT", 1, argc, argv); 1919 } 1920 1921 1922 static int wpa_cli_cmd_p2p_invite(struct wpa_ctrl *ctrl, 1923 int argc, char *argv[]) 1924 { 1925 return wpa_cli_cmd(ctrl, "P2P_INVITE", 1, argc, argv); 1926 } 1927 1928 1929 static int wpa_cli_cmd_p2p_peer(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1930 { 1931 return wpa_cli_cmd(ctrl, "P2P_PEER", 1, argc, argv); 1932 } 1933 1934 1935 static char ** wpa_cli_complete_p2p_peer(const char *str, int pos) 1936 { 1937 int arg = get_cmd_arg_num(str, pos); 1938 char **res = NULL; 1939 1940 switch (arg) { 1941 case 1: 1942 res = cli_txt_list_array(&p2p_peers); 1943 break; 1944 } 1945 1946 return res; 1947 } 1948 1949 1950 static int wpa_ctrl_command_p2p_peer(struct wpa_ctrl *ctrl, char *cmd, 1951 char *addr, size_t addr_len, 1952 int discovered) 1953 { 1954 char buf[4096], *pos; 1955 size_t len; 1956 int ret; 1957 1958 if (ctrl_conn == NULL) 1959 return -1; 1960 len = sizeof(buf) - 1; 1961 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len, 1962 wpa_cli_msg_cb); 1963 if (ret == -2) { 1964 printf("'%s' command timed out.\n", cmd); 1965 return -2; 1966 } else if (ret < 0) { 1967 printf("'%s' command failed.\n", cmd); 1968 return -1; 1969 } 1970 1971 buf[len] = '\0'; 1972 if (os_memcmp(buf, "FAIL", 4) == 0) 1973 return -1; 1974 1975 pos = buf; 1976 while (*pos != '\0' && *pos != '\n') 1977 pos++; 1978 *pos++ = '\0'; 1979 os_strlcpy(addr, buf, addr_len); 1980 if (!discovered || os_strstr(pos, "[PROBE_REQ_ONLY]") == NULL) 1981 printf("%s\n", addr); 1982 return 0; 1983 } 1984 1985 1986 static int wpa_cli_cmd_p2p_peers(struct wpa_ctrl *ctrl, int argc, char *argv[]) 1987 { 1988 char addr[32], cmd[64]; 1989 int discovered; 1990 1991 discovered = argc > 0 && os_strcmp(argv[0], "discovered") == 0; 1992 1993 if (wpa_ctrl_command_p2p_peer(ctrl, "P2P_PEER FIRST", 1994 addr, sizeof(addr), discovered)) 1995 return -1; 1996 do { 1997 os_snprintf(cmd, sizeof(cmd), "P2P_PEER NEXT-%s", addr); 1998 } while (wpa_ctrl_command_p2p_peer(ctrl, cmd, addr, sizeof(addr), 1999 discovered) == 0); 2000 2001 return 0; 2002 } 2003 2004 2005 static int wpa_cli_cmd_p2p_set(struct wpa_ctrl *ctrl, int argc, char *argv[]) 2006 { 2007 return wpa_cli_cmd(ctrl, "P2P_SET", 2, argc, argv); 2008 } 2009 2010 2011 static int wpa_cli_cmd_p2p_flush(struct wpa_ctrl *ctrl, int argc, char *argv[]) 2012 { 2013 return wpa_ctrl_command(ctrl, "P2P_FLUSH"); 2014 } 2015 2016 2017 static int wpa_cli_cmd_p2p_cancel(struct wpa_ctrl *ctrl, int argc, 2018 char *argv[]) 2019 { 2020 return wpa_ctrl_command(ctrl, "P2P_CANCEL"); 2021 } 2022 2023 2024 static int wpa_cli_cmd_p2p_unauthorize(struct wpa_ctrl *ctrl, int argc, 2025 char *argv[]) 2026 { 2027 return wpa_cli_cmd(ctrl, "P2P_UNAUTHORIZE", 1, argc, argv); 2028 } 2029 2030 2031 static int wpa_cli_cmd_p2p_presence_req(struct wpa_ctrl *ctrl, int argc, 2032 char *argv[]) 2033 { 2034 if (argc != 0 && argc != 2 && argc != 4) { 2035 printf("Invalid P2P_PRESENCE_REQ command: needs two arguments " 2036 "(preferred duration, interval; in microsecods).\n" 2037 "Optional second pair can be used to provide " 2038 "acceptable values.\n"); 2039 return -1; 2040 } 2041 2042 return wpa_cli_cmd(ctrl, "P2P_PRESENCE_REQ", 0, argc, argv); 2043 } 2044 2045 2046 static int wpa_cli_cmd_p2p_ext_listen(struct wpa_ctrl *ctrl, int argc, 2047 char *argv[]) 2048 { 2049 if (argc != 0 && argc != 2) { 2050 printf("Invalid P2P_EXT_LISTEN command: needs two arguments " 2051 "(availability period, availability interval; in " 2052 "millisecods).\n" 2053 "Extended Listen Timing can be cancelled with this " 2054 "command when used without parameters.\n"); 2055 return -1; 2056 } 2057 2058 return wpa_cli_cmd(ctrl, "P2P_EXT_LISTEN", 0, argc, argv); 2059 } 2060 2061 #endif /* CONFIG_P2P */ 2062 2063 #ifdef CONFIG_WIFI_DISPLAY 2064 2065 static int wpa_cli_cmd_wfd_subelem_set(struct wpa_ctrl *ctrl, int argc, 2066 char *argv[]) 2067 { 2068 char cmd[100]; 2069 int res; 2070 2071 if (argc != 1 && argc != 2) { 2072 printf("Invalid WFD_SUBELEM_SET command: needs one or two " 2073 "arguments (subelem, hexdump)\n"); 2074 return -1; 2075 } 2076 2077 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_SET %s %s", 2078 argv[0], argc > 1 ? argv[1] : ""); 2079 if (res < 0 || (size_t) res >= sizeof(cmd)) 2080 return -1; 2081 cmd[sizeof(cmd) - 1] = '\0'; 2082 return wpa_ctrl_command(ctrl, cmd); 2083 } 2084 2085 2086 static int wpa_cli_cmd_wfd_subelem_get(struct wpa_ctrl *ctrl, int argc, 2087 char *argv[]) 2088 { 2089 char cmd[100]; 2090 int res; 2091 2092 if (argc != 1) { 2093 printf("Invalid WFD_SUBELEM_GET command: needs one " 2094 "argument (subelem)\n"); 2095 return -1; 2096 } 2097 2098 res = os_snprintf(cmd, sizeof(cmd), "WFD_SUBELEM_GET %s", 2099 argv[0]); 2100 if (res < 0 || (size_t) res >= sizeof(cmd)) 2101 return -1; 2102 cmd[sizeof(cmd) - 1] = '\0'; 2103 return wpa_ctrl_command(ctrl, cmd); 2104 } 2105 #endif /* CONFIG_WIFI_DISPLAY */ 2106 2107 2108 #ifdef CONFIG_INTERWORKING 2109 static int wpa_cli_cmd_fetch_anqp(struct wpa_ctrl *ctrl, int argc, 2110 char *argv[]) 2111 { 2112 return wpa_ctrl_command(ctrl, "FETCH_ANQP"); 2113 } 2114 2115 2116 static int wpa_cli_cmd_stop_fetch_anqp(struct wpa_ctrl *ctrl, int argc, 2117 char *argv[]) 2118 { 2119 return wpa_ctrl_command(ctrl, "STOP_FETCH_ANQP"); 2120 } 2121 2122 2123 static int wpa_cli_cmd_interworking_select(struct wpa_ctrl *ctrl, int argc, 2124 char *argv[]) 2125 { 2126 return wpa_cli_cmd(ctrl, "INTERWORKING_SELECT", 0, argc, argv); 2127 } 2128 2129 2130 static int wpa_cli_cmd_interworking_connect(struct wpa_ctrl *ctrl, int argc, 2131 char *argv[]) 2132 { 2133 return wpa_cli_cmd(ctrl, "INTERWORKING_CONNECT", 1, argc, argv); 2134 } 2135 2136 2137 static int wpa_cli_cmd_anqp_get(struct wpa_ctrl *ctrl, int argc, char *argv[]) 2138 { 2139 return wpa_cli_cmd(ctrl, "ANQP_GET", 2, argc, argv); 2140 } 2141 2142 2143 static int wpa_cli_cmd_gas_request(struct wpa_ctrl *ctrl, int argc, 2144 char *argv[]) 2145 { 2146 return wpa_cli_cmd(ctrl, "GAS_REQUEST", 2, argc, argv); 2147 } 2148 2149 2150 static int wpa_cli_cmd_gas_response_get(struct wpa_ctrl *ctrl, int argc, 2151 char *argv[]) 2152 { 2153 return wpa_cli_cmd(ctrl, "GAS_RESPONSE_GET", 2, argc, argv); 2154 } 2155 #endif /* CONFIG_INTERWORKING */ 2156 2157 2158 #ifdef CONFIG_HS20 2159 2160 static int wpa_cli_cmd_hs20_anqp_get(struct wpa_ctrl *ctrl, int argc, 2161 char *argv[]) 2162 { 2163 return wpa_cli_cmd(ctrl, "HS20_ANQP_GET", 2, argc, argv); 2164 } 2165 2166 2167 static int wpa_cli_cmd_get_nai_home_realm_list(struct wpa_ctrl *ctrl, int argc, 2168 char *argv[]) 2169 { 2170 char cmd[512]; 2171 2172 if (argc == 0) { 2173 printf("Command needs one or two arguments (dst mac addr and " 2174 "optional home realm)\n"); 2175 return -1; 2176 } 2177 2178 if (write_cmd(cmd, sizeof(cmd), "HS20_GET_NAI_HOME_REALM_LIST", 2179 argc, argv) < 0) 2180 return -1; 2181 2182 return wpa_ctrl_command(ctrl, cmd); 2183 } 2184 2185 #endif /* CONFIG_HS20 */ 2186 2187 2188 static int wpa_cli_cmd_sta_autoconnect(struct wpa_ctrl *ctrl, int argc, 2189 char *argv[]) 2190 { 2191 return wpa_cli_cmd(ctrl, "STA_AUTOCONNECT", 1, argc, argv); 2192 } 2193 2194 2195 static int wpa_cli_cmd_tdls_discover(struct wpa_ctrl *ctrl, int argc, 2196 char *argv[]) 2197 { 2198 return wpa_cli_cmd(ctrl, "TDLS_DISCOVER", 1, argc, argv); 2199 } 2200 2201 2202 static int wpa_cli_cmd_tdls_setup(struct wpa_ctrl *ctrl, int argc, 2203 char *argv[]) 2204 { 2205 return wpa_cli_cmd(ctrl, "TDLS_SETUP", 1, argc, argv); 2206 } 2207 2208 2209 static int wpa_cli_cmd_tdls_teardown(struct wpa_ctrl *ctrl, int argc, 2210 char *argv[]) 2211 { 2212 return wpa_cli_cmd(ctrl, "TDLS_TEARDOWN", 1, argc, argv); 2213 } 2214 2215 2216 static int wpa_cli_cmd_signal_poll(struct wpa_ctrl *ctrl, int argc, 2217 char *argv[]) 2218 { 2219 return wpa_ctrl_command(ctrl, "SIGNAL_POLL"); 2220 } 2221 2222 2223 static int wpa_cli_cmd_pktcnt_poll(struct wpa_ctrl *ctrl, int argc, 2224 char *argv[]) 2225 { 2226 return wpa_ctrl_command(ctrl, "PKTCNT_POLL"); 2227 } 2228 2229 2230 static int wpa_cli_cmd_reauthenticate(struct wpa_ctrl *ctrl, int argc, 2231 char *argv[]) 2232 { 2233 return wpa_ctrl_command(ctrl, "REAUTHENTICATE"); 2234 } 2235 2236 2237 #ifdef CONFIG_AUTOSCAN 2238 2239 static int wpa_cli_cmd_autoscan(struct wpa_ctrl *ctrl, int argc, char *argv[]) 2240 { 2241 if (argc == 0) 2242 return wpa_ctrl_command(ctrl, "AUTOSCAN "); 2243 2244 return wpa_cli_cmd(ctrl, "AUTOSCAN", 0, argc, argv); 2245 } 2246 2247 #endif /* CONFIG_AUTOSCAN */ 2248 2249 2250 #ifdef CONFIG_WNM 2251 2252 static int wpa_cli_cmd_wnm_sleep(struct wpa_ctrl *ctrl, int argc, char *argv[]) 2253 { 2254 return wpa_cli_cmd(ctrl, "WNM_SLEEP", 0, argc, argv); 2255 } 2256 2257 #endif /* CONFIG_WNM */ 2258 2259 2260 static int wpa_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[]) 2261 { 2262 if (argc == 0) 2263 return -1; 2264 return wpa_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]); 2265 } 2266 2267 2268 enum wpa_cli_cmd_flags { 2269 cli_cmd_flag_none = 0x00, 2270 cli_cmd_flag_sensitive = 0x01 2271 }; 2272 2273 struct wpa_cli_cmd { 2274 const char *cmd; 2275 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]); 2276 char ** (*completion)(const char *str, int pos); 2277 enum wpa_cli_cmd_flags flags; 2278 const char *usage; 2279 }; 2280 2281 static struct wpa_cli_cmd wpa_cli_commands[] = { 2282 { "status", wpa_cli_cmd_status, NULL, 2283 cli_cmd_flag_none, 2284 "[verbose] = get current WPA/EAPOL/EAP status" }, 2285 { "ifname", wpa_cli_cmd_ifname, NULL, 2286 cli_cmd_flag_none, 2287 "= get current interface name" }, 2288 { "ping", wpa_cli_cmd_ping, NULL, 2289 cli_cmd_flag_none, 2290 "= pings wpa_supplicant" }, 2291 { "relog", wpa_cli_cmd_relog, NULL, 2292 cli_cmd_flag_none, 2293 "= re-open log-file (allow rolling logs)" }, 2294 { "note", wpa_cli_cmd_note, NULL, 2295 cli_cmd_flag_none, 2296 "<text> = add a note to wpa_supplicant debug log" }, 2297 { "mib", wpa_cli_cmd_mib, NULL, 2298 cli_cmd_flag_none, 2299 "= get MIB variables (dot1x, dot11)" }, 2300 { "help", wpa_cli_cmd_help, wpa_cli_complete_help, 2301 cli_cmd_flag_none, 2302 "[command] = show usage help" }, 2303 { "interface", wpa_cli_cmd_interface, NULL, 2304 cli_cmd_flag_none, 2305 "[ifname] = show interfaces/select interface" }, 2306 { "level", wpa_cli_cmd_level, NULL, 2307 cli_cmd_flag_none, 2308 "<debug level> = change debug level" }, 2309 { "license", wpa_cli_cmd_license, NULL, 2310 cli_cmd_flag_none, 2311 "= show full wpa_cli license" }, 2312 { "quit", wpa_cli_cmd_quit, NULL, 2313 cli_cmd_flag_none, 2314 "= exit wpa_cli" }, 2315 { "set", wpa_cli_cmd_set, NULL, 2316 cli_cmd_flag_none, 2317 "= set variables (shows list of variables when run without " 2318 "arguments)" }, 2319 { "get", wpa_cli_cmd_get, NULL, 2320 cli_cmd_flag_none, 2321 "<name> = get information" }, 2322 { "logon", wpa_cli_cmd_logon, NULL, 2323 cli_cmd_flag_none, 2324 "= IEEE 802.1X EAPOL state machine logon" }, 2325 { "logoff", wpa_cli_cmd_logoff, NULL, 2326 cli_cmd_flag_none, 2327 "= IEEE 802.1X EAPOL state machine logoff" }, 2328 { "pmksa", wpa_cli_cmd_pmksa, NULL, 2329 cli_cmd_flag_none, 2330 "= show PMKSA cache" }, 2331 { "reassociate", wpa_cli_cmd_reassociate, NULL, 2332 cli_cmd_flag_none, 2333 "= force reassociation" }, 2334 { "preauthenticate", wpa_cli_cmd_preauthenticate, wpa_cli_complete_bss, 2335 cli_cmd_flag_none, 2336 "<BSSID> = force preauthentication" }, 2337 { "identity", wpa_cli_cmd_identity, NULL, 2338 cli_cmd_flag_none, 2339 "<network id> <identity> = configure identity for an SSID" }, 2340 { "password", wpa_cli_cmd_password, NULL, 2341 cli_cmd_flag_sensitive, 2342 "<network id> <password> = configure password for an SSID" }, 2343 { "new_password", wpa_cli_cmd_new_password, NULL, 2344 cli_cmd_flag_sensitive, 2345 "<network id> <password> = change password for an SSID" }, 2346 { "pin", wpa_cli_cmd_pin, NULL, 2347 cli_cmd_flag_sensitive, 2348 "<network id> <pin> = configure pin for an SSID" }, 2349 { "otp", wpa_cli_cmd_otp, NULL, 2350 cli_cmd_flag_sensitive, 2351 "<network id> <password> = configure one-time-password for an SSID" 2352 }, 2353 { "passphrase", wpa_cli_cmd_passphrase, NULL, 2354 cli_cmd_flag_sensitive, 2355 "<network id> <passphrase> = configure private key passphrase\n" 2356 " for an SSID" }, 2357 { "bssid", wpa_cli_cmd_bssid, NULL, 2358 cli_cmd_flag_none, 2359 "<network id> <BSSID> = set preferred BSSID for an SSID" }, 2360 { "blacklist", wpa_cli_cmd_blacklist, wpa_cli_complete_bss, 2361 cli_cmd_flag_none, 2362 "<BSSID> = add a BSSID to the blacklist\n" 2363 "blacklist clear = clear the blacklist\n" 2364 "blacklist = display the blacklist" }, 2365 { "log_level", wpa_cli_cmd_log_level, NULL, 2366 cli_cmd_flag_none, 2367 "<level> [<timestamp>] = update the log level/timestamp\n" 2368 "log_level = display the current log level and log options" }, 2369 { "list_networks", wpa_cli_cmd_list_networks, NULL, 2370 cli_cmd_flag_none, 2371 "= list configured networks" }, 2372 { "select_network", wpa_cli_cmd_select_network, NULL, 2373 cli_cmd_flag_none, 2374 "<network id> = select a network (disable others)" }, 2375 { "enable_network", wpa_cli_cmd_enable_network, NULL, 2376 cli_cmd_flag_none, 2377 "<network id> = enable a network" }, 2378 { "disable_network", wpa_cli_cmd_disable_network, NULL, 2379 cli_cmd_flag_none, 2380 "<network id> = disable a network" }, 2381 { "add_network", wpa_cli_cmd_add_network, NULL, 2382 cli_cmd_flag_none, 2383 "= add a network" }, 2384 { "remove_network", wpa_cli_cmd_remove_network, NULL, 2385 cli_cmd_flag_none, 2386 "<network id> = remove a network" }, 2387 { "set_network", wpa_cli_cmd_set_network, NULL, 2388 cli_cmd_flag_sensitive, 2389 "<network id> <variable> <value> = set network variables (shows\n" 2390 " list of variables when run without arguments)" }, 2391 { "get_network", wpa_cli_cmd_get_network, NULL, 2392 cli_cmd_flag_none, 2393 "<network id> <variable> = get network variables" }, 2394 { "list_creds", wpa_cli_cmd_list_creds, NULL, 2395 cli_cmd_flag_none, 2396 "= list configured credentials" }, 2397 { "add_cred", wpa_cli_cmd_add_cred, NULL, 2398 cli_cmd_flag_none, 2399 "= add a credential" }, 2400 { "remove_cred", wpa_cli_cmd_remove_cred, NULL, 2401 cli_cmd_flag_none, 2402 "<cred id> = remove a credential" }, 2403 { "set_cred", wpa_cli_cmd_set_cred, NULL, 2404 cli_cmd_flag_sensitive, 2405 "<cred id> <variable> <value> = set credential variables" }, 2406 { "save_config", wpa_cli_cmd_save_config, NULL, 2407 cli_cmd_flag_none, 2408 "= save the current configuration" }, 2409 { "disconnect", wpa_cli_cmd_disconnect, NULL, 2410 cli_cmd_flag_none, 2411 "= disconnect and wait for reassociate/reconnect command before\n" 2412 " connecting" }, 2413 { "reconnect", wpa_cli_cmd_reconnect, NULL, 2414 cli_cmd_flag_none, 2415 "= like reassociate, but only takes effect if already disconnected" 2416 }, 2417 { "scan", wpa_cli_cmd_scan, NULL, 2418 cli_cmd_flag_none, 2419 "= request new BSS scan" }, 2420 { "scan_results", wpa_cli_cmd_scan_results, NULL, 2421 cli_cmd_flag_none, 2422 "= get latest scan results" }, 2423 { "bss", wpa_cli_cmd_bss, wpa_cli_complete_bss, 2424 cli_cmd_flag_none, 2425 "<<idx> | <bssid>> = get detailed scan result info" }, 2426 { "get_capability", wpa_cli_cmd_get_capability, NULL, 2427 cli_cmd_flag_none, 2428 "<eap/pairwise/group/key_mgmt/proto/auth_alg/channels> " 2429 "= get capabilies" }, 2430 { "reconfigure", wpa_cli_cmd_reconfigure, NULL, 2431 cli_cmd_flag_none, 2432 "= force wpa_supplicant to re-read its configuration file" }, 2433 { "terminate", wpa_cli_cmd_terminate, NULL, 2434 cli_cmd_flag_none, 2435 "= terminate wpa_supplicant" }, 2436 { "interface_add", wpa_cli_cmd_interface_add, NULL, 2437 cli_cmd_flag_none, 2438 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n" 2439 " <bridge_name> = adds new interface, all parameters but <ifname>\n" 2440 " are optional" }, 2441 { "interface_remove", wpa_cli_cmd_interface_remove, NULL, 2442 cli_cmd_flag_none, 2443 "<ifname> = removes the interface" }, 2444 { "interface_list", wpa_cli_cmd_interface_list, NULL, 2445 cli_cmd_flag_none, 2446 "= list available interfaces" }, 2447 { "ap_scan", wpa_cli_cmd_ap_scan, NULL, 2448 cli_cmd_flag_none, 2449 "<value> = set ap_scan parameter" }, 2450 { "scan_interval", wpa_cli_cmd_scan_interval, NULL, 2451 cli_cmd_flag_none, 2452 "<value> = set scan_interval parameter (in seconds)" }, 2453 { "bss_expire_age", wpa_cli_cmd_bss_expire_age, NULL, 2454 cli_cmd_flag_none, 2455 "<value> = set BSS expiration age parameter" }, 2456 { "bss_expire_count", wpa_cli_cmd_bss_expire_count, NULL, 2457 cli_cmd_flag_none, 2458 "<value> = set BSS expiration scan count parameter" }, 2459 { "bss_flush", wpa_cli_cmd_bss_flush, NULL, 2460 cli_cmd_flag_none, 2461 "<value> = set BSS flush age (0 by default)" }, 2462 { "stkstart", wpa_cli_cmd_stkstart, NULL, 2463 cli_cmd_flag_none, 2464 "<addr> = request STK negotiation with <addr>" }, 2465 { "ft_ds", wpa_cli_cmd_ft_ds, wpa_cli_complete_bss, 2466 cli_cmd_flag_none, 2467 "<addr> = request over-the-DS FT with <addr>" }, 2468 { "wps_pbc", wpa_cli_cmd_wps_pbc, wpa_cli_complete_bss, 2469 cli_cmd_flag_none, 2470 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" }, 2471 { "wps_pin", wpa_cli_cmd_wps_pin, wpa_cli_complete_bss, 2472 cli_cmd_flag_sensitive, 2473 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not " 2474 "hardcoded)" }, 2475 { "wps_check_pin", wpa_cli_cmd_wps_check_pin, NULL, 2476 cli_cmd_flag_sensitive, 2477 "<PIN> = verify PIN checksum" }, 2478 { "wps_cancel", wpa_cli_cmd_wps_cancel, NULL, cli_cmd_flag_none, 2479 "Cancels the pending WPS operation" }, 2480 #ifdef CONFIG_WPS_NFC 2481 { "wps_nfc", wpa_cli_cmd_wps_nfc, wpa_cli_complete_bss, 2482 cli_cmd_flag_none, 2483 "[BSSID] = start Wi-Fi Protected Setup: NFC" }, 2484 { "wps_nfc_token", wpa_cli_cmd_wps_nfc_token, NULL, 2485 cli_cmd_flag_none, 2486 "<WPS|NDEF> = create password token" }, 2487 { "wps_nfc_tag_read", wpa_cli_cmd_wps_nfc_tag_read, NULL, 2488 cli_cmd_flag_sensitive, 2489 "<hexdump of payload> = report read NFC tag with WPS data" }, 2490 { "nfc_get_handover_req", wpa_cli_cmd_nfc_get_handover_req, NULL, 2491 cli_cmd_flag_none, 2492 "<NDEF> <WPS> = create NFC handover request" }, 2493 { "nfc_get_handover_sel", wpa_cli_cmd_nfc_get_handover_sel, NULL, 2494 cli_cmd_flag_none, 2495 "<NDEF> <WPS> = create NFC handover select" }, 2496 { "nfc_rx_handover_req", wpa_cli_cmd_nfc_rx_handover_req, NULL, 2497 cli_cmd_flag_none, 2498 "<hexdump of payload> = report received NFC handover request" }, 2499 { "nfc_rx_handover_sel", wpa_cli_cmd_nfc_rx_handover_sel, NULL, 2500 cli_cmd_flag_none, 2501 "<hexdump of payload> = report received NFC handover select" }, 2502 #endif /* CONFIG_WPS_NFC */ 2503 { "wps_reg", wpa_cli_cmd_wps_reg, wpa_cli_complete_bss, 2504 cli_cmd_flag_sensitive, 2505 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" }, 2506 { "wps_ap_pin", wpa_cli_cmd_wps_ap_pin, NULL, 2507 cli_cmd_flag_sensitive, 2508 "[params..] = enable/disable AP PIN" }, 2509 { "wps_er_start", wpa_cli_cmd_wps_er_start, NULL, 2510 cli_cmd_flag_none, 2511 "[IP address] = start Wi-Fi Protected Setup External Registrar" }, 2512 { "wps_er_stop", wpa_cli_cmd_wps_er_stop, NULL, 2513 cli_cmd_flag_none, 2514 "= stop Wi-Fi Protected Setup External Registrar" }, 2515 { "wps_er_pin", wpa_cli_cmd_wps_er_pin, NULL, 2516 cli_cmd_flag_sensitive, 2517 "<UUID> <PIN> = add an Enrollee PIN to External Registrar" }, 2518 { "wps_er_pbc", wpa_cli_cmd_wps_er_pbc, NULL, 2519 cli_cmd_flag_none, 2520 "<UUID> = accept an Enrollee PBC using External Registrar" }, 2521 { "wps_er_learn", wpa_cli_cmd_wps_er_learn, NULL, 2522 cli_cmd_flag_sensitive, 2523 "<UUID> <PIN> = learn AP configuration" }, 2524 { "wps_er_set_config", wpa_cli_cmd_wps_er_set_config, NULL, 2525 cli_cmd_flag_none, 2526 "<UUID> <network id> = set AP configuration for enrolling" }, 2527 { "wps_er_config", wpa_cli_cmd_wps_er_config, NULL, 2528 cli_cmd_flag_sensitive, 2529 "<UUID> <PIN> <SSID> <auth> <encr> <key> = configure AP" }, 2530 #ifdef CONFIG_WPS_NFC 2531 { "wps_er_nfc_config_token", wpa_cli_cmd_wps_er_nfc_config_token, NULL, 2532 cli_cmd_flag_none, 2533 "<WPS/NDEF> <UUID> = build NFC configuration token" }, 2534 #endif /* CONFIG_WPS_NFC */ 2535 { "ibss_rsn", wpa_cli_cmd_ibss_rsn, NULL, 2536 cli_cmd_flag_none, 2537 "<addr> = request RSN authentication with <addr> in IBSS" }, 2538 #ifdef CONFIG_AP 2539 { "sta", wpa_cli_cmd_sta, NULL, 2540 cli_cmd_flag_none, 2541 "<addr> = get information about an associated station (AP)" }, 2542 { "all_sta", wpa_cli_cmd_all_sta, NULL, 2543 cli_cmd_flag_none, 2544 "= get information about all associated stations (AP)" }, 2545 { "deauthenticate", wpa_cli_cmd_deauthenticate, NULL, 2546 cli_cmd_flag_none, 2547 "<addr> = deauthenticate a station" }, 2548 { "disassociate", wpa_cli_cmd_disassociate, NULL, 2549 cli_cmd_flag_none, 2550 "<addr> = disassociate a station" }, 2551 #endif /* CONFIG_AP */ 2552 { "suspend", wpa_cli_cmd_suspend, NULL, cli_cmd_flag_none, 2553 "= notification of suspend/hibernate" }, 2554 { "resume", wpa_cli_cmd_resume, NULL, cli_cmd_flag_none, 2555 "= notification of resume/thaw" }, 2556 { "drop_sa", wpa_cli_cmd_drop_sa, NULL, cli_cmd_flag_none, 2557 "= drop SA without deauth/disassoc (test command)" }, 2558 { "roam", wpa_cli_cmd_roam, wpa_cli_complete_bss, 2559 cli_cmd_flag_none, 2560 "<addr> = roam to the specified BSS" }, 2561 #ifdef CONFIG_P2P 2562 { "p2p_find", wpa_cli_cmd_p2p_find, wpa_cli_complete_p2p_find, 2563 cli_cmd_flag_none, 2564 "[timeout] [type=*] = find P2P Devices for up-to timeout seconds" }, 2565 { "p2p_stop_find", wpa_cli_cmd_p2p_stop_find, NULL, cli_cmd_flag_none, 2566 "= stop P2P Devices search" }, 2567 { "p2p_connect", wpa_cli_cmd_p2p_connect, wpa_cli_complete_p2p_connect, 2568 cli_cmd_flag_none, 2569 "<addr> <\"pbc\"|PIN> [ht40] = connect to a P2P Device" }, 2570 { "p2p_listen", wpa_cli_cmd_p2p_listen, NULL, cli_cmd_flag_none, 2571 "[timeout] = listen for P2P Devices for up-to timeout seconds" }, 2572 { "p2p_group_remove", wpa_cli_cmd_p2p_group_remove, 2573 wpa_cli_complete_p2p_group_remove, cli_cmd_flag_none, 2574 "<ifname> = remove P2P group interface (terminate group if GO)" }, 2575 { "p2p_group_add", wpa_cli_cmd_p2p_group_add, NULL, cli_cmd_flag_none, 2576 "[ht40] = add a new P2P group (local end as GO)" }, 2577 { "p2p_prov_disc", wpa_cli_cmd_p2p_prov_disc, 2578 wpa_cli_complete_p2p_peer, cli_cmd_flag_none, 2579 "<addr> <method> = request provisioning discovery" }, 2580 { "p2p_get_passphrase", wpa_cli_cmd_p2p_get_passphrase, NULL, 2581 cli_cmd_flag_none, 2582 "= get the passphrase for a group (GO only)" }, 2583 { "p2p_serv_disc_req", wpa_cli_cmd_p2p_serv_disc_req, 2584 wpa_cli_complete_p2p_peer, cli_cmd_flag_none, 2585 "<addr> <TLVs> = schedule service discovery request" }, 2586 { "p2p_serv_disc_cancel_req", wpa_cli_cmd_p2p_serv_disc_cancel_req, 2587 NULL, cli_cmd_flag_none, 2588 "<id> = cancel pending service discovery request" }, 2589 { "p2p_serv_disc_resp", wpa_cli_cmd_p2p_serv_disc_resp, NULL, 2590 cli_cmd_flag_none, 2591 "<freq> <addr> <dialog token> <TLVs> = service discovery response" }, 2592 { "p2p_service_update", wpa_cli_cmd_p2p_service_update, NULL, 2593 cli_cmd_flag_none, 2594 "= indicate change in local services" }, 2595 { "p2p_serv_disc_external", wpa_cli_cmd_p2p_serv_disc_external, NULL, 2596 cli_cmd_flag_none, 2597 "<external> = set external processing of service discovery" }, 2598 { "p2p_service_flush", wpa_cli_cmd_p2p_service_flush, NULL, 2599 cli_cmd_flag_none, 2600 "= remove all stored service entries" }, 2601 { "p2p_service_add", wpa_cli_cmd_p2p_service_add, NULL, 2602 cli_cmd_flag_none, 2603 "<bonjour|upnp> <query|version> <response|service> = add a local " 2604 "service" }, 2605 { "p2p_service_del", wpa_cli_cmd_p2p_service_del, NULL, 2606 cli_cmd_flag_none, 2607 "<bonjour|upnp> <query|version> [|service] = remove a local " 2608 "service" }, 2609 { "p2p_reject", wpa_cli_cmd_p2p_reject, wpa_cli_complete_p2p_peer, 2610 cli_cmd_flag_none, 2611 "<addr> = reject connection attempts from a specific peer" }, 2612 { "p2p_invite", wpa_cli_cmd_p2p_invite, NULL, 2613 cli_cmd_flag_none, 2614 "<cmd> [peer=addr] = invite peer" }, 2615 { "p2p_peers", wpa_cli_cmd_p2p_peers, NULL, cli_cmd_flag_none, 2616 "[discovered] = list known (optionally, only fully discovered) P2P " 2617 "peers" }, 2618 { "p2p_peer", wpa_cli_cmd_p2p_peer, wpa_cli_complete_p2p_peer, 2619 cli_cmd_flag_none, 2620 "<address> = show information about known P2P peer" }, 2621 { "p2p_set", wpa_cli_cmd_p2p_set, NULL, cli_cmd_flag_none, 2622 "<field> <value> = set a P2P parameter" }, 2623 { "p2p_flush", wpa_cli_cmd_p2p_flush, NULL, cli_cmd_flag_none, 2624 "= flush P2P state" }, 2625 { "p2p_cancel", wpa_cli_cmd_p2p_cancel, NULL, cli_cmd_flag_none, 2626 "= cancel P2P group formation" }, 2627 { "p2p_unauthorize", wpa_cli_cmd_p2p_unauthorize, 2628 wpa_cli_complete_p2p_peer, cli_cmd_flag_none, 2629 "<address> = unauthorize a peer" }, 2630 { "p2p_presence_req", wpa_cli_cmd_p2p_presence_req, NULL, 2631 cli_cmd_flag_none, 2632 "[<duration> <interval>] [<duration> <interval>] = request GO " 2633 "presence" }, 2634 { "p2p_ext_listen", wpa_cli_cmd_p2p_ext_listen, NULL, 2635 cli_cmd_flag_none, 2636 "[<period> <interval>] = set extended listen timing" }, 2637 #endif /* CONFIG_P2P */ 2638 #ifdef CONFIG_WIFI_DISPLAY 2639 { "wfd_subelem_set", wpa_cli_cmd_wfd_subelem_set, NULL, 2640 cli_cmd_flag_none, 2641 "<subelem> [contents] = set Wi-Fi Display subelement" }, 2642 { "wfd_subelem_get", wpa_cli_cmd_wfd_subelem_get, NULL, 2643 cli_cmd_flag_none, 2644 "<subelem> = get Wi-Fi Display subelement" }, 2645 #endif /* CONFIG_WIFI_DISPLAY */ 2646 #ifdef CONFIG_INTERWORKING 2647 { "fetch_anqp", wpa_cli_cmd_fetch_anqp, NULL, cli_cmd_flag_none, 2648 "= fetch ANQP information for all APs" }, 2649 { "stop_fetch_anqp", wpa_cli_cmd_stop_fetch_anqp, NULL, 2650 cli_cmd_flag_none, 2651 "= stop fetch_anqp operation" }, 2652 { "interworking_select", wpa_cli_cmd_interworking_select, NULL, 2653 cli_cmd_flag_none, 2654 "[auto] = perform Interworking network selection" }, 2655 { "interworking_connect", wpa_cli_cmd_interworking_connect, 2656 wpa_cli_complete_bss, cli_cmd_flag_none, 2657 "<BSSID> = connect using Interworking credentials" }, 2658 { "anqp_get", wpa_cli_cmd_anqp_get, wpa_cli_complete_bss, 2659 cli_cmd_flag_none, 2660 "<addr> <info id>[,<info id>]... = request ANQP information" }, 2661 { "gas_request", wpa_cli_cmd_gas_request, wpa_cli_complete_bss, 2662 cli_cmd_flag_none, 2663 "<addr> <AdvProtoID> [QueryReq] = GAS request" }, 2664 { "gas_response_get", wpa_cli_cmd_gas_response_get, 2665 wpa_cli_complete_bss, cli_cmd_flag_none, 2666 "<addr> <dialog token> [start,len] = Fetch last GAS response" }, 2667 #endif /* CONFIG_INTERWORKING */ 2668 #ifdef CONFIG_HS20 2669 { "hs20_anqp_get", wpa_cli_cmd_hs20_anqp_get, wpa_cli_complete_bss, 2670 cli_cmd_flag_none, 2671 "<addr> <subtype>[,<subtype>]... = request HS 2.0 ANQP information" 2672 }, 2673 { "nai_home_realm_list", wpa_cli_cmd_get_nai_home_realm_list, 2674 wpa_cli_complete_bss, cli_cmd_flag_none, 2675 "<addr> <home realm> = get HS20 nai home realm list" }, 2676 #endif /* CONFIG_HS20 */ 2677 { "sta_autoconnect", wpa_cli_cmd_sta_autoconnect, NULL, 2678 cli_cmd_flag_none, 2679 "<0/1> = disable/enable automatic reconnection" }, 2680 { "tdls_discover", wpa_cli_cmd_tdls_discover, NULL, 2681 cli_cmd_flag_none, 2682 "<addr> = request TDLS discovery with <addr>" }, 2683 { "tdls_setup", wpa_cli_cmd_tdls_setup, NULL, 2684 cli_cmd_flag_none, 2685 "<addr> = request TDLS setup with <addr>" }, 2686 { "tdls_teardown", wpa_cli_cmd_tdls_teardown, NULL, 2687 cli_cmd_flag_none, 2688 "<addr> = tear down TDLS with <addr>" }, 2689 { "signal_poll", wpa_cli_cmd_signal_poll, NULL, 2690 cli_cmd_flag_none, 2691 "= get signal parameters" }, 2692 { "pktcnt_poll", wpa_cli_cmd_pktcnt_poll, NULL, 2693 cli_cmd_flag_none, 2694 "= get TX/RX packet counters" }, 2695 { "reauthenticate", wpa_cli_cmd_reauthenticate, NULL, 2696 cli_cmd_flag_none, 2697 "= trigger IEEE 802.1X/EAPOL reauthentication" }, 2698 #ifdef CONFIG_AUTOSCAN 2699 { "autoscan", wpa_cli_cmd_autoscan, NULL, cli_cmd_flag_none, 2700 "[params] = Set or unset (if none) autoscan parameters" }, 2701 #endif /* CONFIG_AUTOSCAN */ 2702 #ifdef CONFIG_WNM 2703 { "wnm_sleep", wpa_cli_cmd_wnm_sleep, NULL, cli_cmd_flag_none, 2704 "<enter/exit> [interval=#] = enter/exit WNM-Sleep mode" }, 2705 #endif /* CONFIG_WNM */ 2706 { "raw", wpa_cli_cmd_raw, NULL, cli_cmd_flag_sensitive, 2707 "<params..> = Sent unprocessed command" }, 2708 { NULL, NULL, NULL, cli_cmd_flag_none, NULL } 2709 }; 2710 2711 2712 /* 2713 * Prints command usage, lines are padded with the specified string. 2714 */ 2715 static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad) 2716 { 2717 char c; 2718 size_t n; 2719 2720 printf("%s%s ", pad, cmd->cmd); 2721 for (n = 0; (c = cmd->usage[n]); n++) { 2722 printf("%c", c); 2723 if (c == '\n') 2724 printf("%s", pad); 2725 } 2726 printf("\n"); 2727 } 2728 2729 2730 static void print_help(const char *cmd) 2731 { 2732 int n; 2733 printf("commands:\n"); 2734 for (n = 0; wpa_cli_commands[n].cmd; n++) { 2735 if (cmd == NULL || str_starts(wpa_cli_commands[n].cmd, cmd)) 2736 print_cmd_help(&wpa_cli_commands[n], " "); 2737 } 2738 } 2739 2740 2741 static int wpa_cli_edit_filter_history_cb(void *ctx, const char *cmd) 2742 { 2743 const char *c, *delim; 2744 int n; 2745 size_t len; 2746 2747 delim = os_strchr(cmd, ' '); 2748 if (delim) 2749 len = delim - cmd; 2750 else 2751 len = os_strlen(cmd); 2752 2753 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) { 2754 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c)) 2755 return (wpa_cli_commands[n].flags & 2756 cli_cmd_flag_sensitive); 2757 } 2758 return 0; 2759 } 2760 2761 2762 static char ** wpa_list_cmd_list(void) 2763 { 2764 char **res; 2765 int i, count; 2766 2767 count = sizeof(wpa_cli_commands) / sizeof(wpa_cli_commands[0]); 2768 res = os_calloc(count, sizeof(char *)); 2769 if (res == NULL) 2770 return NULL; 2771 2772 for (i = 0; wpa_cli_commands[i].cmd; i++) { 2773 res[i] = os_strdup(wpa_cli_commands[i].cmd); 2774 if (res[i] == NULL) 2775 break; 2776 } 2777 2778 return res; 2779 } 2780 2781 2782 static char ** wpa_cli_cmd_completion(const char *cmd, const char *str, 2783 int pos) 2784 { 2785 int i; 2786 2787 for (i = 0; wpa_cli_commands[i].cmd; i++) { 2788 if (os_strcasecmp(wpa_cli_commands[i].cmd, cmd) == 0) { 2789 if (wpa_cli_commands[i].completion) 2790 return wpa_cli_commands[i].completion(str, 2791 pos); 2792 edit_clear_line(); 2793 printf("\r%s\n", wpa_cli_commands[i].usage); 2794 edit_redraw(); 2795 break; 2796 } 2797 } 2798 2799 return NULL; 2800 } 2801 2802 2803 static char ** wpa_cli_edit_completion_cb(void *ctx, const char *str, int pos) 2804 { 2805 char **res; 2806 const char *end; 2807 char *cmd; 2808 2809 end = os_strchr(str, ' '); 2810 if (end == NULL || str + pos < end) 2811 return wpa_list_cmd_list(); 2812 2813 cmd = os_malloc(pos + 1); 2814 if (cmd == NULL) 2815 return NULL; 2816 os_memcpy(cmd, str, pos); 2817 cmd[end - str] = '\0'; 2818 res = wpa_cli_cmd_completion(cmd, str, pos); 2819 os_free(cmd); 2820 return res; 2821 } 2822 2823 2824 static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[]) 2825 { 2826 struct wpa_cli_cmd *cmd, *match = NULL; 2827 int count; 2828 int ret = 0; 2829 2830 count = 0; 2831 cmd = wpa_cli_commands; 2832 while (cmd->cmd) { 2833 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0) 2834 { 2835 match = cmd; 2836 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) { 2837 /* we have an exact match */ 2838 count = 1; 2839 break; 2840 } 2841 count++; 2842 } 2843 cmd++; 2844 } 2845 2846 if (count > 1) { 2847 printf("Ambiguous command '%s'; possible commands:", argv[0]); 2848 cmd = wpa_cli_commands; 2849 while (cmd->cmd) { 2850 if (os_strncasecmp(cmd->cmd, argv[0], 2851 os_strlen(argv[0])) == 0) { 2852 printf(" %s", cmd->cmd); 2853 } 2854 cmd++; 2855 } 2856 printf("\n"); 2857 ret = 1; 2858 } else if (count == 0) { 2859 printf("Unknown command '%s'\n", argv[0]); 2860 ret = 1; 2861 } else { 2862 ret = match->handler(ctrl, argc - 1, &argv[1]); 2863 } 2864 2865 return ret; 2866 } 2867 2868 2869 static int str_match(const char *a, const char *b) 2870 { 2871 return os_strncmp(a, b, os_strlen(b)) == 0; 2872 } 2873 2874 2875 static int wpa_cli_exec(const char *program, const char *arg1, 2876 const char *arg2) 2877 { 2878 char *cmd; 2879 size_t len; 2880 int res; 2881 int ret = 0; 2882 2883 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3; 2884 cmd = os_malloc(len); 2885 if (cmd == NULL) 2886 return -1; 2887 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2); 2888 if (res < 0 || (size_t) res >= len) { 2889 os_free(cmd); 2890 return -1; 2891 } 2892 cmd[len - 1] = '\0'; 2893 #ifndef _WIN32_WCE 2894 if (system(cmd) < 0) 2895 ret = -1; 2896 #endif /* _WIN32_WCE */ 2897 os_free(cmd); 2898 2899 return ret; 2900 } 2901 2902 2903 static void wpa_cli_action_process(const char *msg) 2904 { 2905 const char *pos; 2906 char *copy = NULL, *id, *pos2; 2907 2908 pos = msg; 2909 if (*pos == '<') { 2910 /* skip priority */ 2911 pos = os_strchr(pos, '>'); 2912 if (pos) 2913 pos++; 2914 else 2915 pos = msg; 2916 } 2917 2918 if (str_match(pos, WPA_EVENT_CONNECTED)) { 2919 int new_id = -1; 2920 os_unsetenv("WPA_ID"); 2921 os_unsetenv("WPA_ID_STR"); 2922 os_unsetenv("WPA_CTRL_DIR"); 2923 2924 pos = os_strstr(pos, "[id="); 2925 if (pos) 2926 copy = os_strdup(pos + 4); 2927 2928 if (copy) { 2929 pos2 = id = copy; 2930 while (*pos2 && *pos2 != ' ') 2931 pos2++; 2932 *pos2++ = '\0'; 2933 new_id = atoi(id); 2934 os_setenv("WPA_ID", id, 1); 2935 while (*pos2 && *pos2 != '=') 2936 pos2++; 2937 if (*pos2 == '=') 2938 pos2++; 2939 id = pos2; 2940 while (*pos2 && *pos2 != ']') 2941 pos2++; 2942 *pos2 = '\0'; 2943 os_setenv("WPA_ID_STR", id, 1); 2944 os_free(copy); 2945 } 2946 2947 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1); 2948 2949 if (!wpa_cli_connected || new_id != wpa_cli_last_id) { 2950 wpa_cli_connected = 1; 2951 wpa_cli_last_id = new_id; 2952 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED"); 2953 } 2954 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) { 2955 if (wpa_cli_connected) { 2956 wpa_cli_connected = 0; 2957 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED"); 2958 } 2959 } else if (str_match(pos, P2P_EVENT_GROUP_STARTED)) { 2960 wpa_cli_exec(action_file, ctrl_ifname, pos); 2961 } else if (str_match(pos, P2P_EVENT_GROUP_REMOVED)) { 2962 wpa_cli_exec(action_file, ctrl_ifname, pos); 2963 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_ENABLE)) { 2964 wpa_cli_exec(action_file, ctrl_ifname, pos); 2965 } else if (str_match(pos, P2P_EVENT_CROSS_CONNECT_DISABLE)) { 2966 wpa_cli_exec(action_file, ctrl_ifname, pos); 2967 } else if (str_match(pos, P2P_EVENT_GO_NEG_FAILURE)) { 2968 wpa_cli_exec(action_file, ctrl_ifname, pos); 2969 } else if (str_match(pos, WPS_EVENT_SUCCESS)) { 2970 wpa_cli_exec(action_file, ctrl_ifname, pos); 2971 } else if (str_match(pos, WPS_EVENT_FAIL)) { 2972 wpa_cli_exec(action_file, ctrl_ifname, pos); 2973 } else if (str_match(pos, AP_STA_CONNECTED)) { 2974 wpa_cli_exec(action_file, ctrl_ifname, pos); 2975 } else if (str_match(pos, AP_STA_DISCONNECTED)) { 2976 wpa_cli_exec(action_file, ctrl_ifname, pos); 2977 } else if (str_match(pos, WPA_EVENT_TERMINATING)) { 2978 printf("wpa_supplicant is terminating - stop monitoring\n"); 2979 wpa_cli_quit = 1; 2980 } 2981 } 2982 2983 2984 #ifndef CONFIG_ANSI_C_EXTRA 2985 static void wpa_cli_action_cb(char *msg, size_t len) 2986 { 2987 wpa_cli_action_process(msg); 2988 } 2989 #endif /* CONFIG_ANSI_C_EXTRA */ 2990 2991 2992 static void wpa_cli_reconnect(void) 2993 { 2994 wpa_cli_close_connection(); 2995 if (wpa_cli_open_connection(ctrl_ifname, 1) < 0) 2996 return; 2997 2998 if (interactive) { 2999 edit_clear_line(); 3000 printf("\rConnection to wpa_supplicant re-established\n"); 3001 edit_redraw(); 3002 } 3003 } 3004 3005 3006 static void cli_event(const char *str) 3007 { 3008 const char *start, *s; 3009 3010 start = os_strchr(str, '>'); 3011 if (start == NULL) 3012 return; 3013 3014 start++; 3015 3016 if (str_starts(start, WPA_EVENT_BSS_ADDED)) { 3017 s = os_strchr(start, ' '); 3018 if (s == NULL) 3019 return; 3020 s = os_strchr(s + 1, ' '); 3021 if (s == NULL) 3022 return; 3023 cli_txt_list_add(&bsses, s + 1); 3024 return; 3025 } 3026 3027 if (str_starts(start, WPA_EVENT_BSS_REMOVED)) { 3028 s = os_strchr(start, ' '); 3029 if (s == NULL) 3030 return; 3031 s = os_strchr(s + 1, ' '); 3032 if (s == NULL) 3033 return; 3034 cli_txt_list_del_addr(&bsses, s + 1); 3035 return; 3036 } 3037 3038 #ifdef CONFIG_P2P 3039 if (str_starts(start, P2P_EVENT_DEVICE_FOUND)) { 3040 s = os_strstr(start, " p2p_dev_addr="); 3041 if (s == NULL) 3042 return; 3043 cli_txt_list_add_addr(&p2p_peers, s + 14); 3044 return; 3045 } 3046 3047 if (str_starts(start, P2P_EVENT_DEVICE_LOST)) { 3048 s = os_strstr(start, " p2p_dev_addr="); 3049 if (s == NULL) 3050 return; 3051 cli_txt_list_del_addr(&p2p_peers, s + 14); 3052 return; 3053 } 3054 3055 if (str_starts(start, P2P_EVENT_GROUP_STARTED)) { 3056 s = os_strchr(start, ' '); 3057 if (s == NULL) 3058 return; 3059 cli_txt_list_add_word(&p2p_groups, s + 1); 3060 return; 3061 } 3062 3063 if (str_starts(start, P2P_EVENT_GROUP_REMOVED)) { 3064 s = os_strchr(start, ' '); 3065 if (s == NULL) 3066 return; 3067 cli_txt_list_del_word(&p2p_groups, s + 1); 3068 return; 3069 } 3070 #endif /* CONFIG_P2P */ 3071 } 3072 3073 3074 static int check_terminating(const char *msg) 3075 { 3076 const char *pos = msg; 3077 3078 if (*pos == '<') { 3079 /* skip priority */ 3080 pos = os_strchr(pos, '>'); 3081 if (pos) 3082 pos++; 3083 else 3084 pos = msg; 3085 } 3086 3087 if (str_match(pos, WPA_EVENT_TERMINATING) && ctrl_conn) { 3088 edit_clear_line(); 3089 printf("\rConnection to wpa_supplicant lost - trying to " 3090 "reconnect\n"); 3091 edit_redraw(); 3092 wpa_cli_attached = 0; 3093 wpa_cli_close_connection(); 3094 return 1; 3095 } 3096 3097 return 0; 3098 } 3099 3100 3101 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int action_monitor) 3102 { 3103 if (ctrl_conn == NULL) { 3104 wpa_cli_reconnect(); 3105 return; 3106 } 3107 while (wpa_ctrl_pending(ctrl) > 0) { 3108 char buf[256]; 3109 size_t len = sizeof(buf) - 1; 3110 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) { 3111 buf[len] = '\0'; 3112 if (action_monitor) 3113 wpa_cli_action_process(buf); 3114 else { 3115 cli_event(buf); 3116 if (wpa_cli_show_event(buf)) { 3117 edit_clear_line(); 3118 printf("\r%s\n", buf); 3119 edit_redraw(); 3120 } 3121 3122 if (interactive && check_terminating(buf) > 0) 3123 return; 3124 } 3125 } else { 3126 printf("Could not read pending message.\n"); 3127 break; 3128 } 3129 } 3130 3131 if (wpa_ctrl_pending(ctrl) < 0) { 3132 printf("Connection to wpa_supplicant lost - trying to " 3133 "reconnect\n"); 3134 wpa_cli_reconnect(); 3135 } 3136 } 3137 3138 #define max_args 10 3139 3140 static int tokenize_cmd(char *cmd, char *argv[]) 3141 { 3142 char *pos; 3143 int argc = 0; 3144 3145 pos = cmd; 3146 for (;;) { 3147 while (*pos == ' ') 3148 pos++; 3149 if (*pos == '\0') 3150 break; 3151 argv[argc] = pos; 3152 argc++; 3153 if (argc == max_args) 3154 break; 3155 if (*pos == '"') { 3156 char *pos2 = os_strrchr(pos, '"'); 3157 if (pos2) 3158 pos = pos2 + 1; 3159 } 3160 while (*pos != '\0' && *pos != ' ') 3161 pos++; 3162 if (*pos == ' ') 3163 *pos++ = '\0'; 3164 } 3165 3166 return argc; 3167 } 3168 3169 3170 static void wpa_cli_ping(void *eloop_ctx, void *timeout_ctx) 3171 { 3172 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) { 3173 printf("Connection to wpa_supplicant lost - trying to " 3174 "reconnect\n"); 3175 wpa_cli_close_connection(); 3176 } 3177 if (!ctrl_conn) 3178 wpa_cli_reconnect(); 3179 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL); 3180 } 3181 3182 3183 static void wpa_cli_mon_receive(int sock, void *eloop_ctx, void *sock_ctx) 3184 { 3185 wpa_cli_recv_pending(mon_conn, 0); 3186 } 3187 3188 3189 static void wpa_cli_edit_cmd_cb(void *ctx, char *cmd) 3190 { 3191 char *argv[max_args]; 3192 int argc; 3193 argc = tokenize_cmd(cmd, argv); 3194 if (argc) 3195 wpa_request(ctrl_conn, argc, argv); 3196 } 3197 3198 3199 static void wpa_cli_edit_eof_cb(void *ctx) 3200 { 3201 eloop_terminate(); 3202 } 3203 3204 3205 static int warning_displayed = 0; 3206 static char *hfile = NULL; 3207 static int edit_started = 0; 3208 3209 static void start_edit(void) 3210 { 3211 char *home; 3212 char *ps = NULL; 3213 3214 #ifdef CONFIG_CTRL_IFACE_UDP_REMOTE 3215 ps = wpa_ctrl_get_remote_ifname(ctrl_conn); 3216 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ 3217 3218 home = getenv("HOME"); 3219 if (home) { 3220 const char *fname = ".wpa_cli_history"; 3221 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1; 3222 hfile = os_malloc(hfile_len); 3223 if (hfile) 3224 os_snprintf(hfile, hfile_len, "%s/%s", home, fname); 3225 } 3226 3227 if (edit_init(wpa_cli_edit_cmd_cb, wpa_cli_edit_eof_cb, 3228 wpa_cli_edit_completion_cb, NULL, hfile, ps) < 0) { 3229 eloop_terminate(); 3230 return; 3231 } 3232 3233 edit_started = 1; 3234 eloop_register_timeout(ping_interval, 0, wpa_cli_ping, NULL, NULL); 3235 } 3236 3237 3238 static void try_connection(void *eloop_ctx, void *timeout_ctx) 3239 { 3240 if (ctrl_ifname == NULL) 3241 ctrl_ifname = wpa_cli_get_default_ifname(); 3242 3243 if (!wpa_cli_open_connection(ctrl_ifname, 1) == 0) { 3244 if (!warning_displayed) { 3245 printf("Could not connect to wpa_supplicant: " 3246 "%s - re-trying\n", ctrl_ifname); 3247 warning_displayed = 1; 3248 } 3249 eloop_register_timeout(1, 0, try_connection, NULL, NULL); 3250 return; 3251 } 3252 3253 if (warning_displayed) 3254 printf("Connection established.\n"); 3255 3256 start_edit(); 3257 } 3258 3259 3260 static void wpa_cli_interactive(void) 3261 { 3262 printf("\nInteractive mode\n\n"); 3263 3264 eloop_register_timeout(0, 0, try_connection, NULL, NULL); 3265 eloop_run(); 3266 eloop_cancel_timeout(try_connection, NULL, NULL); 3267 3268 cli_txt_list_flush(&p2p_peers); 3269 cli_txt_list_flush(&p2p_groups); 3270 cli_txt_list_flush(&bsses); 3271 if (edit_started) 3272 edit_deinit(hfile, wpa_cli_edit_filter_history_cb); 3273 os_free(hfile); 3274 eloop_cancel_timeout(wpa_cli_ping, NULL, NULL); 3275 wpa_cli_close_connection(); 3276 } 3277 3278 3279 static void wpa_cli_action(struct wpa_ctrl *ctrl) 3280 { 3281 #ifdef CONFIG_ANSI_C_EXTRA 3282 /* TODO: ANSI C version(?) */ 3283 printf("Action processing not supported in ANSI C build.\n"); 3284 #else /* CONFIG_ANSI_C_EXTRA */ 3285 fd_set rfds; 3286 int fd, res; 3287 struct timeval tv; 3288 char buf[256]; /* note: large enough to fit in unsolicited messages */ 3289 size_t len; 3290 3291 fd = wpa_ctrl_get_fd(ctrl); 3292 3293 while (!wpa_cli_quit) { 3294 FD_ZERO(&rfds); 3295 FD_SET(fd, &rfds); 3296 tv.tv_sec = ping_interval; 3297 tv.tv_usec = 0; 3298 res = select(fd + 1, &rfds, NULL, NULL, &tv); 3299 if (res < 0 && errno != EINTR) { 3300 perror("select"); 3301 break; 3302 } 3303 3304 if (FD_ISSET(fd, &rfds)) 3305 wpa_cli_recv_pending(ctrl, 1); 3306 else { 3307 /* verify that connection is still working */ 3308 len = sizeof(buf) - 1; 3309 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len, 3310 wpa_cli_action_cb) < 0 || 3311 len < 4 || os_memcmp(buf, "PONG", 4) != 0) { 3312 printf("wpa_supplicant did not reply to PING " 3313 "command - exiting\n"); 3314 break; 3315 } 3316 } 3317 } 3318 #endif /* CONFIG_ANSI_C_EXTRA */ 3319 } 3320 3321 3322 static void wpa_cli_cleanup(void) 3323 { 3324 wpa_cli_close_connection(); 3325 if (pid_file) 3326 os_daemonize_terminate(pid_file); 3327 3328 os_program_deinit(); 3329 } 3330 3331 3332 static void wpa_cli_terminate(int sig, void *ctx) 3333 { 3334 eloop_terminate(); 3335 } 3336 3337 3338 static char * wpa_cli_get_default_ifname(void) 3339 { 3340 char *ifname = NULL; 3341 3342 #ifdef CONFIG_CTRL_IFACE_UNIX 3343 struct dirent *dent; 3344 DIR *dir = opendir(ctrl_iface_dir); 3345 if (!dir) { 3346 #ifdef ANDROID 3347 char ifprop[PROPERTY_VALUE_MAX]; 3348 if (property_get("wifi.interface", ifprop, NULL) != 0) { 3349 ifname = os_strdup(ifprop); 3350 printf("Using interface '%s'\n", ifname); 3351 return ifname; 3352 } 3353 #endif /* ANDROID */ 3354 return NULL; 3355 } 3356 while ((dent = readdir(dir))) { 3357 #ifdef _DIRENT_HAVE_D_TYPE 3358 /* 3359 * Skip the file if it is not a socket. Also accept 3360 * DT_UNKNOWN (0) in case the C library or underlying 3361 * file system does not support d_type. 3362 */ 3363 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN) 3364 continue; 3365 #endif /* _DIRENT_HAVE_D_TYPE */ 3366 if (os_strcmp(dent->d_name, ".") == 0 || 3367 os_strcmp(dent->d_name, "..") == 0) 3368 continue; 3369 printf("Selected interface '%s'\n", dent->d_name); 3370 ifname = os_strdup(dent->d_name); 3371 break; 3372 } 3373 closedir(dir); 3374 #endif /* CONFIG_CTRL_IFACE_UNIX */ 3375 3376 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 3377 char buf[2048], *pos; 3378 size_t len; 3379 struct wpa_ctrl *ctrl; 3380 int ret; 3381 3382 ctrl = wpa_ctrl_open(NULL); 3383 if (ctrl == NULL) 3384 return NULL; 3385 3386 len = sizeof(buf) - 1; 3387 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL); 3388 if (ret >= 0) { 3389 buf[len] = '\0'; 3390 pos = os_strchr(buf, '\n'); 3391 if (pos) 3392 *pos = '\0'; 3393 ifname = os_strdup(buf); 3394 } 3395 wpa_ctrl_close(ctrl); 3396 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 3397 3398 return ifname; 3399 } 3400 3401 3402 int main(int argc, char *argv[]) 3403 { 3404 int c; 3405 int daemonize = 0; 3406 int ret = 0; 3407 const char *global = NULL; 3408 3409 if (os_program_init()) 3410 return -1; 3411 3412 for (;;) { 3413 c = getopt(argc, argv, "a:Bg:G:hi:p:P:v"); 3414 if (c < 0) 3415 break; 3416 switch (c) { 3417 case 'a': 3418 action_file = optarg; 3419 break; 3420 case 'B': 3421 daemonize = 1; 3422 break; 3423 case 'g': 3424 global = optarg; 3425 break; 3426 case 'G': 3427 ping_interval = atoi(optarg); 3428 break; 3429 case 'h': 3430 usage(); 3431 return 0; 3432 case 'v': 3433 printf("%s\n", wpa_cli_version); 3434 return 0; 3435 case 'i': 3436 os_free(ctrl_ifname); 3437 ctrl_ifname = os_strdup(optarg); 3438 break; 3439 case 'p': 3440 ctrl_iface_dir = optarg; 3441 break; 3442 case 'P': 3443 pid_file = optarg; 3444 break; 3445 default: 3446 usage(); 3447 return -1; 3448 } 3449 } 3450 3451 interactive = (argc == optind) && (action_file == NULL); 3452 3453 if (interactive) 3454 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license); 3455 3456 if (eloop_init()) 3457 return -1; 3458 3459 if (global) { 3460 #ifdef CONFIG_CTRL_IFACE_NAMED_PIPE 3461 ctrl_conn = wpa_ctrl_open(NULL); 3462 #else /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 3463 ctrl_conn = wpa_ctrl_open(global); 3464 #endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */ 3465 if (ctrl_conn == NULL) { 3466 fprintf(stderr, "Failed to connect to wpa_supplicant " 3467 "global interface: %s error: %s\n", 3468 global, strerror(errno)); 3469 return -1; 3470 } 3471 } 3472 3473 eloop_register_signal_terminate(wpa_cli_terminate, NULL); 3474 3475 if (ctrl_ifname == NULL) 3476 ctrl_ifname = wpa_cli_get_default_ifname(); 3477 3478 if (interactive) { 3479 wpa_cli_interactive(); 3480 } else { 3481 if (!global && 3482 wpa_cli_open_connection(ctrl_ifname, 0) < 0) { 3483 fprintf(stderr, "Failed to connect to non-global " 3484 "ctrl_ifname: %s error: %s\n", 3485 ctrl_ifname, strerror(errno)); 3486 return -1; 3487 } 3488 3489 if (action_file) { 3490 if (wpa_ctrl_attach(ctrl_conn) == 0) { 3491 wpa_cli_attached = 1; 3492 } else { 3493 printf("Warning: Failed to attach to " 3494 "wpa_supplicant.\n"); 3495 return -1; 3496 } 3497 } 3498 3499 if (daemonize && os_daemonize(pid_file)) 3500 return -1; 3501 3502 if (action_file) 3503 wpa_cli_action(ctrl_conn); 3504 else 3505 ret = wpa_request(ctrl_conn, argc - optind, 3506 &argv[optind]); 3507 } 3508 3509 os_free(ctrl_ifname); 3510 eloop_destroy(); 3511 wpa_cli_cleanup(); 3512 3513 return ret; 3514 } 3515 3516 #else /* CONFIG_CTRL_IFACE */ 3517 int main(int argc, char *argv[]) 3518 { 3519 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n"); 3520 return -1; 3521 } 3522 #endif /* CONFIG_CTRL_IFACE */ 3523