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