00001
00016 #include <stdlib.h>
00017 #include <stdio.h>
00018 #include <string.h>
00019 #include <signal.h>
00020 #include <unistd.h>
00021 #include <dirent.h>
00022 #include <errno.h>
00023 #include <sys/time.h>
00024 #ifdef CONFIG_READLINE
00025 #include <readline/readline.h>
00026 #include <readline/history.h>
00027 #endif
00028
00029 #include "wpa_ctrl.h"
00030 #ifdef CONFIG_NATIVE_WINDOWS
00031 #include "common.h"
00032 #endif
00033 #include "version.h"
00034
00035
00036 static const char *wpa_cli_version =
00037 "wpa_cli v" VERSION_STR "\n"
00038 "Copyright (c) 2004-2005, Jouni Malinen <[email protected]> and contributors";
00039
00040
00041 static const char *wpa_cli_license =
00042 "This program is free software. You can distribute it and/or modify it\n"
00043 "under the terms of the GNU General Public License version 2.\n"
00044 "\n"
00045 "Alternatively, this software may be distributed under the terms of the\n"
00046 "BSD license. See README and COPYING for more details.\n";
00047
00048 static const char *wpa_cli_full_license =
00049 "This program is free software; you can redistribute it and/or modify\n"
00050 "it under the terms of the GNU General Public License version 2 as\n"
00051 "published by the Free Software Foundation.\n"
00052 "\n"
00053 "This program is distributed in the hope that it will be useful,\n"
00054 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
00055 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
00056 "GNU General Public License for more details.\n"
00057 "\n"
00058 "You should have received a copy of the GNU General Public License\n"
00059 "along with this program; if not, write to the Free Software\n"
00060 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
00061 "\n"
00062 "Alternatively, this software may be distributed under the terms of the\n"
00063 "BSD license.\n"
00064 "\n"
00065 "Redistribution and use in source and binary forms, with or without\n"
00066 "modification, are permitted provided that the following conditions are\n"
00067 "met:\n"
00068 "\n"
00069 "1. Redistributions of source code must retain the above copyright\n"
00070 " notice, this list of conditions and the following disclaimer.\n"
00071 "\n"
00072 "2. Redistributions in binary form must reproduce the above copyright\n"
00073 " notice, this list of conditions and the following disclaimer in the\n"
00074 " documentation and/or other materials provided with the distribution.\n"
00075 "\n"
00076 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
00077 " names of its contributors may be used to endorse or promote products\n"
00078 " derived from this software without specific prior written permission.\n"
00079 "\n"
00080 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
00081 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
00082 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
00083 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
00084 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
00085 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
00086 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
00087 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
00088 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
00089 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
00090 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
00091 "\n";
00092
00093 static const char *commands_help =
00094 "commands:\n"
00095 " status [verbose] = get current WPA/EAPOL/EAP status\n"
00096 " mib = get MIB variables (dot1x, dot11)\n"
00097 " help = show this usage help\n"
00098 " interface [ifname] = show interfaces/select interface\n"
00099 " level <debug level> = change debug level\n"
00100 " license = show full wpa_cli license\n"
00101 " logoff = IEEE 802.1X EAPOL state machine logoff\n"
00102 " logon = IEEE 802.1X EAPOL state machine logon\n"
00103 " set = set variables (shows list of variables when run without arguments)\n"
00104 " pmksa = show PMKSA cache\n"
00105 " reassociate = force reassociation\n"
00106 " reconfigure = force wpa_supplicant to re-read its configuration file\n"
00107 " preauthenticate <BSSID> = force preauthentication\n"
00108 " identity <network id> <identity> = configure identity for an SSID\n"
00109 " password <network id> <password> = configure password for an SSID\n"
00110 " new_password <network id> <password> = change password for an SSID\n"
00111 " pin <network id> <pin> = configure pin for an SSID\n"
00112 " otp <network id> <password> = configure one-time-password for an SSID\n"
00113 " passphrase <network id> <passphrase> = configure private key passphrase\n"
00114 " for an SSID\n"
00115 " bssid <network id> <BSSID> = set preferred BSSID for an SSID\n"
00116 " list_networks = list configured networks\n"
00117 " select_network <network id> = select a network (disable others)\n"
00118 " enable_network <network id> = enable a network\n"
00119 " disable_network <network id> = disable a network\n"
00120 " add_network = add a network\n"
00121 " remove_network <network id> = remove a network\n"
00122 " set_network <network id> <variable> <value> = set network variables "
00123 "(shows\n"
00124 " list of variables when run without arguments)\n"
00125 " get_network <network id> <variable> = get network variables\n"
00126 " save_config = save the current configuration\n"
00127 " disconnect = disconnect and wait for reassociate command before "
00128 "connecting\n"
00129 " scan = request new BSS scan\n"
00130 " scan_results = get latest scan results\n"
00131 " get_capability <eap/pairwise/group/key_mgmt/proto/auth_alg> = "
00132 "get capabilies\n"
00133 " terminate = terminate wpa_supplicant\n"
00134 " quit = exit wpa_cli\n";
00135
00136 static struct wpa_ctrl *ctrl_conn;
00137 static int wpa_cli_quit = 0;
00138 static int wpa_cli_attached = 0;
00139 static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
00140 static char *ctrl_ifname = NULL;
00141 static const char *pid_file = NULL;
00142 static const char *action_file = NULL;
00143
00144
00145 static void usage(void)
00146 {
00147 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
00148 "[-a<action file>] \\\n"
00149 " [-P<pid file>] [-g<global ctrl>] [command..]\n"
00150 " -h = help (show this usage text)\n"
00151 " -v = shown version information\n"
00152 " -a = run in daemon mode executing the action file based on "
00153 "events from\n"
00154 " wpa_supplicant\n"
00155 " -B = run a daemon in the background\n"
00156 " default path: /var/run/wpa_supplicant\n"
00157 " default interface: first interface found in socket path\n"
00158 "%s",
00159 commands_help);
00160 }
00161
00162
00163 static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
00164 {
00165 #ifdef CONFIG_CTRL_IFACE_UDP
00166 ctrl_conn = wpa_ctrl_open("");
00167 return ctrl_conn;
00168 #else
00169 char *cfile;
00170 int flen;
00171
00172 if (ifname == NULL)
00173 return NULL;
00174
00175 flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
00176 cfile = malloc(flen);
00177 if (cfile == NULL)
00178 return NULL;
00179 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
00180
00181 ctrl_conn = wpa_ctrl_open(cfile);
00182 free(cfile);
00183 return ctrl_conn;
00184 #endif
00185 }
00186
00187
00188 static void wpa_cli_close_connection(void)
00189 {
00190 if (ctrl_conn == NULL)
00191 return;
00192
00193 if (wpa_cli_attached) {
00194 wpa_ctrl_detach(ctrl_conn);
00195 wpa_cli_attached = 0;
00196 }
00197 wpa_ctrl_close(ctrl_conn);
00198 ctrl_conn = NULL;
00199 }
00200
00201
00202 static void wpa_cli_msg_cb(char *msg, size_t len)
00203 {
00204 printf("%s\n", msg);
00205 }
00206
00207
00208 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
00209 {
00210 char buf[2048];
00211 size_t len;
00212 int ret;
00213
00214 if (ctrl_conn == NULL) {
00215 printf("Not connected to wpa_supplicant - command dropped.\n");
00216 return -1;
00217 }
00218 len = sizeof(buf) - 1;
00219 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
00220 wpa_cli_msg_cb);
00221 if (ret == -2) {
00222 printf("'%s' command timed out.\n", cmd);
00223 return -2;
00224 } else if (ret < 0) {
00225 printf("'%s' command failed.\n", cmd);
00226 return -1;
00227 }
00228 if (print) {
00229 buf[len] = '\0';
00230 printf("%s", buf);
00231 }
00232 return 0;
00233 }
00234
00235
00236 static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
00237 {
00238 return _wpa_ctrl_command(ctrl, cmd, 1);
00239 }
00240
00241
00242 static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
00243 {
00244 int verbose = argc > 0 && strcmp(argv[0], "verbose") == 0;
00245 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
00246 }
00247
00248
00249 static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
00250 {
00251 return wpa_ctrl_command(ctrl, "PING");
00252 }
00253
00254
00255 static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
00256 {
00257 return wpa_ctrl_command(ctrl, "MIB");
00258 }
00259
00260
00261 static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
00262 {
00263 return wpa_ctrl_command(ctrl, "PMKSA");
00264 }
00265
00266
00267 static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
00268 {
00269 printf("%s", commands_help);
00270 return 0;
00271 }
00272
00273
00274 static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
00275 {
00276 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
00277 return 0;
00278 }
00279
00280
00281 static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
00282 {
00283 wpa_cli_quit = 1;
00284 return 0;
00285 }
00286
00287
00288 static void wpa_cli_show_variables(void)
00289 {
00290 printf("set variables:\n"
00291 " EAPOL::heldPeriod (EAPOL state machine held period, "
00292 "in seconds)\n"
00293 " EAPOL::authPeriod (EAPOL state machine authentication "
00294 "period, in seconds)\n"
00295 " EAPOL::startPeriod (EAPOL state machine start period, in "
00296 "seconds)\n"
00297 " EAPOL::maxStart (EAPOL state machine maximum start "
00298 "attempts)\n");
00299 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
00300 "seconds)\n"
00301 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
00302 " threshold\n\tpercentage)\n"
00303 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
00304 "security\n\tassociation in seconds)\n");
00305 }
00306
00307
00308 static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
00309 {
00310 char cmd[256];
00311
00312 if (argc == 0) {
00313 wpa_cli_show_variables();
00314 return 0;
00315 }
00316
00317 if (argc != 2) {
00318 printf("Invalid SET command: needs two arguments (variable "
00319 "name and value)\n");
00320 return 0;
00321 }
00322
00323 if (snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]) >=
00324 sizeof(cmd) - 1) {
00325 printf("Too long SET command.\n");
00326 return 0;
00327 }
00328 return wpa_ctrl_command(ctrl, cmd);
00329 }
00330
00331
00332 static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
00333 {
00334 return wpa_ctrl_command(ctrl, "LOGOFF");
00335 }
00336
00337
00338 static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
00339 {
00340 return wpa_ctrl_command(ctrl, "LOGON");
00341 }
00342
00343
00344 static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
00345 char *argv[])
00346 {
00347 return wpa_ctrl_command(ctrl, "REASSOCIATE");
00348 }
00349
00350
00351 static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
00352 char *argv[])
00353 {
00354 char cmd[256];
00355
00356 if (argc != 1) {
00357 printf("Invalid PREAUTH command: needs one argument "
00358 "(BSSID)\n");
00359 return 0;
00360 }
00361
00362 if (snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]) >=
00363 sizeof(cmd) - 1) {
00364 printf("Too long PREAUTH command.\n");
00365 return 0;
00366 }
00367 return wpa_ctrl_command(ctrl, cmd);
00368 }
00369
00370
00371 static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
00372 {
00373 char cmd[256];
00374 if (argc != 1) {
00375 printf("Invalid LEVEL command: needs one argument (debug "
00376 "level)\n");
00377 return 0;
00378 }
00379 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
00380 return wpa_ctrl_command(ctrl, cmd);
00381 }
00382
00383
00384 static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
00385 {
00386 char cmd[256], *pos, *end;
00387 int i;
00388
00389 if (argc < 2) {
00390 printf("Invalid IDENTITY command: needs two arguments "
00391 "(network id and identity)\n");
00392 return 0;
00393 }
00394
00395 end = cmd + sizeof(cmd);
00396 pos = cmd;
00397 pos += snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
00398 argv[0], argv[1]);
00399 for (i = 2; i < argc; i++)
00400 pos += snprintf(pos, end - pos, " %s", argv[i]);
00401
00402 return wpa_ctrl_command(ctrl, cmd);
00403 }
00404
00405
00406 static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
00407 {
00408 char cmd[256], *pos, *end;
00409 int i;
00410
00411 if (argc < 2) {
00412 printf("Invalid PASSWORD command: needs two arguments "
00413 "(network id and password)\n");
00414 return 0;
00415 }
00416
00417 end = cmd + sizeof(cmd);
00418 pos = cmd;
00419 pos += snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
00420 argv[0], argv[1]);
00421 for (i = 2; i < argc; i++)
00422 pos += snprintf(pos, end - pos, " %s", argv[i]);
00423
00424 return wpa_ctrl_command(ctrl, cmd);
00425 }
00426
00427
00428 static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
00429 char *argv[])
00430 {
00431 char cmd[256], *pos, *end;
00432 int i;
00433
00434 if (argc < 2) {
00435 printf("Invalid NEW_PASSWORD command: needs two arguments "
00436 "(network id and password)\n");
00437 return 0;
00438 }
00439
00440 end = cmd + sizeof(cmd);
00441 pos = cmd;
00442 pos += snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
00443 argv[0], argv[1]);
00444 for (i = 2; i < argc; i++)
00445 pos += snprintf(pos, end - pos, " %s", argv[i]);
00446
00447 return wpa_ctrl_command(ctrl, cmd);
00448 }
00449
00450
00451 static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
00452 {
00453 char cmd[256], *pos, *end;
00454 int i;
00455
00456 if (argc < 2) {
00457 printf("Invalid PIN command: needs two arguments "
00458 "(network id and pin)\n");
00459 return 0;
00460 }
00461
00462 end = cmd + sizeof(cmd);
00463 pos = cmd;
00464 pos += snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
00465 argv[0], argv[1]);
00466 for (i = 2; i < argc; i++)
00467 pos += snprintf(pos, end - pos, " %s", argv[i]);
00468
00469 return wpa_ctrl_command(ctrl, cmd);
00470 }
00471
00472
00473 static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
00474 {
00475 char cmd[256], *pos, *end;
00476 int i;
00477
00478 if (argc < 2) {
00479 printf("Invalid OTP command: needs two arguments (network "
00480 "id and password)\n");
00481 return 0;
00482 }
00483
00484 end = cmd + sizeof(cmd);
00485 pos = cmd;
00486 pos += snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
00487 argv[0], argv[1]);
00488 for (i = 2; i < argc; i++)
00489 pos += snprintf(pos, end - pos, " %s", argv[i]);
00490
00491 return wpa_ctrl_command(ctrl, cmd);
00492 }
00493
00494
00495 static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
00496 char *argv[])
00497 {
00498 char cmd[256], *pos, *end;
00499 int i;
00500
00501 if (argc < 2) {
00502 printf("Invalid PASSPHRASE command: needs two arguments "
00503 "(network id and passphrase)\n");
00504 return 0;
00505 }
00506
00507 end = cmd + sizeof(cmd);
00508 pos = cmd;
00509 pos += snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
00510 argv[0], argv[1]);
00511 for (i = 2; i < argc; i++)
00512 pos += snprintf(pos, end - pos, " %s", argv[i]);
00513
00514 return wpa_ctrl_command(ctrl, cmd);
00515 }
00516
00517
00518 static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
00519 {
00520 char cmd[256], *pos, *end;
00521 int i;
00522
00523 if (argc < 2) {
00524 printf("Invalid BSSID command: needs two arguments (network "
00525 "id and BSSID)\n");
00526 return 0;
00527 }
00528
00529 end = cmd + sizeof(cmd);
00530 pos = cmd;
00531 pos += snprintf(pos, end - pos, "BSSID");
00532 for (i = 0; i < argc; i++)
00533 pos += snprintf(pos, end - pos, " %s", argv[i]);
00534
00535 return wpa_ctrl_command(ctrl, cmd);
00536 }
00537
00538
00539 static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
00540 char *argv[])
00541 {
00542 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
00543 }
00544
00545
00546 static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
00547 char *argv[])
00548 {
00549 char cmd[32];
00550
00551 if (argc < 1) {
00552 printf("Invalid SELECT_NETWORK command: needs one argument "
00553 "(network id)\n");
00554 return 0;
00555 }
00556
00557 snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
00558
00559 return wpa_ctrl_command(ctrl, cmd);
00560 }
00561
00562
00563 static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
00564 char *argv[])
00565 {
00566 char cmd[32];
00567
00568 if (argc < 1) {
00569 printf("Invalid ENABLE_NETWORK command: needs one argument "
00570 "(network id)\n");
00571 return 0;
00572 }
00573
00574 snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
00575
00576 return wpa_ctrl_command(ctrl, cmd);
00577 }
00578
00579
00580 static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
00581 char *argv[])
00582 {
00583 char cmd[32];
00584
00585 if (argc < 1) {
00586 printf("Invalid DISABLE_NETWORK command: needs one argument "
00587 "(network id)\n");
00588 return 0;
00589 }
00590
00591 snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
00592
00593 return wpa_ctrl_command(ctrl, cmd);
00594 }
00595
00596
00597 static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
00598 char *argv[])
00599 {
00600 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
00601 }
00602
00603
00604 static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
00605 char *argv[])
00606 {
00607 char cmd[32];
00608
00609 if (argc < 1) {
00610 printf("Invalid REMOVE_NETWORK command: needs one argument "
00611 "(network id)\n");
00612 return 0;
00613 }
00614
00615 snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
00616
00617 return wpa_ctrl_command(ctrl, cmd);
00618 }
00619
00620
00621 static void wpa_cli_show_network_variables(void)
00622 {
00623 printf("set_network variables:\n"
00624 " ssid (network name, SSID)\n"
00625 " psk (WPA passphrase or pre-shared key)\n"
00626 " key_mgmt (key management protocol)\n"
00627 " identity (EAP identity)\n"
00628 " password (EAP password)\n"
00629 " ...\n"
00630 "\n"
00631 "Note: Values are entered in the same format as the "
00632 "configuration file is using,\n"
00633 "i.e., strings values need to be inside double quotation "
00634 "marks.\n"
00635 "For example: set_network 1 ssid \"network name\"\n"
00636 "\n"
00637 "Please see wpa_supplicant.conf documentation for full list "
00638 "of\navailable variables.\n");
00639 }
00640
00641
00642 static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
00643 char *argv[])
00644 {
00645 char cmd[256];
00646
00647 if (argc == 0) {
00648 wpa_cli_show_network_variables();
00649 return 0;
00650 }
00651
00652 if (argc != 3) {
00653 printf("Invalid SET_NETWORK command: needs three arguments\n"
00654 "(network id, variable name, and value)\n");
00655 return 0;
00656 }
00657
00658 if (snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
00659 argv[0], argv[1], argv[2]) >= sizeof(cmd) - 1) {
00660 printf("Too long SET_NETWORK command.\n");
00661 return 0;
00662 }
00663 return wpa_ctrl_command(ctrl, cmd);
00664 }
00665
00666
00667 static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
00668 char *argv[])
00669 {
00670 char cmd[256];
00671
00672 if (argc == 0) {
00673 wpa_cli_show_network_variables();
00674 return 0;
00675 }
00676
00677 if (argc != 2) {
00678 printf("Invalid GET_NETWORK command: needs two arguments\n"
00679 "(network id and variable name)\n");
00680 return 0;
00681 }
00682
00683 if (snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
00684 argv[0], argv[1]) >= sizeof(cmd) - 1) {
00685 printf("Too long GET_NETWORK command.\n");
00686 return 0;
00687 }
00688 return wpa_ctrl_command(ctrl, cmd);
00689 }
00690
00691
00692 static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
00693 char *argv[])
00694 {
00695 return wpa_ctrl_command(ctrl, "DISCONNECT");
00696 }
00697
00698
00699 static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
00700 char *argv[])
00701 {
00702 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
00703 }
00704
00705
00706 static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
00707 {
00708 return wpa_ctrl_command(ctrl, "SCAN");
00709 }
00710
00711
00712 static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
00713 char *argv[])
00714 {
00715 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
00716 }
00717
00718
00719 static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
00720 char *argv[])
00721 {
00722 char cmd[64];
00723
00724 if (argc != 1) {
00725 printf("Invalid GET_CAPABILITY command: needs one argument\n");
00726 return 0;
00727 }
00728
00729 snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s", argv[0]);
00730
00731 return wpa_ctrl_command(ctrl, cmd);
00732 }
00733
00734
00735 static void wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
00736 {
00737 struct dirent *dent;
00738 DIR *dir;
00739
00740 dir = opendir(ctrl_iface_dir);
00741 if (dir == NULL) {
00742 printf("Control interface directory '%s' could not be "
00743 "openned.\n", ctrl_iface_dir);
00744 return;
00745 }
00746
00747 printf("Available interfaces:\n");
00748 while ((dent = readdir(dir))) {
00749 if (strcmp(dent->d_name, ".") == 0 ||
00750 strcmp(dent->d_name, "..") == 0)
00751 continue;
00752 printf("%s\n", dent->d_name);
00753 }
00754 closedir(dir);
00755 }
00756
00757
00758 static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
00759 {
00760 if (argc < 1) {
00761 wpa_cli_list_interfaces(ctrl);
00762 return 0;
00763 }
00764
00765 wpa_cli_close_connection();
00766 free(ctrl_ifname);
00767 ctrl_ifname = strdup(argv[0]);
00768
00769 if (wpa_cli_open_connection(ctrl_ifname)) {
00770 printf("Connected to interface '%s.\n", ctrl_ifname);
00771 if (wpa_ctrl_attach(ctrl_conn) == 0) {
00772 wpa_cli_attached = 1;
00773 } else {
00774 printf("Warning: Failed to attach to "
00775 "wpa_supplicant.\n");
00776 }
00777 } else {
00778 printf("Could not connect to interface '%s' - re-trying\n",
00779 ctrl_ifname);
00780 }
00781 return 0;
00782 }
00783
00784
00785 static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
00786 char *argv[])
00787 {
00788 return wpa_ctrl_command(ctrl, "RECONFIGURE");
00789 }
00790
00791
00792 static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
00793 char *argv[])
00794 {
00795 return wpa_ctrl_command(ctrl, "TERMINATE");
00796 }
00797
00798
00799 static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
00800 char *argv[])
00801 {
00802 char cmd[256];
00803
00804 if (argc < 1) {
00805 printf("Invalid INTERFACE_ADD command: needs at least one "
00806 "argument (interface name)\n"
00807 "All arguments: ifname confname driver ctrl_interface "
00808 "driver_param\n");
00809 return 0;
00810 }
00811
00812
00813
00814
00815
00816 snprintf(cmd, sizeof(cmd), "INTERFACE_ADD %s\t%s\t%s\t%s\t%s", argv[0],
00817 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
00818 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "");
00819 return wpa_ctrl_command(ctrl, cmd);
00820 }
00821
00822
00823 static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
00824 char *argv[])
00825 {
00826 char cmd[128];
00827
00828 if (argc != 1) {
00829 printf("Invalid INTERFACE_REMOVE command: needs one argument "
00830 "(interface name)\n");
00831 return 0;
00832 }
00833
00834 snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
00835 return wpa_ctrl_command(ctrl, cmd);
00836 }
00837
00838
00839 struct wpa_cli_cmd {
00840 const char *cmd;
00841 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
00842 };
00843
00844 static struct wpa_cli_cmd wpa_cli_commands[] = {
00845 { "status", wpa_cli_cmd_status },
00846 { "ping", wpa_cli_cmd_ping },
00847 { "mib", wpa_cli_cmd_mib },
00848 { "help", wpa_cli_cmd_help },
00849 { "interface", wpa_cli_cmd_interface },
00850 { "level", wpa_cli_cmd_level },
00851 { "license", wpa_cli_cmd_license },
00852 { "quit", wpa_cli_cmd_quit },
00853 { "set", wpa_cli_cmd_set },
00854 { "logon", wpa_cli_cmd_logon },
00855 { "logoff", wpa_cli_cmd_logoff },
00856 { "pmksa", wpa_cli_cmd_pmksa },
00857 { "reassociate", wpa_cli_cmd_reassociate },
00858 { "preauthenticate", wpa_cli_cmd_preauthenticate },
00859 { "identity", wpa_cli_cmd_identity },
00860 { "password", wpa_cli_cmd_password },
00861 { "new_password", wpa_cli_cmd_new_password },
00862 { "pin", wpa_cli_cmd_pin },
00863 { "otp", wpa_cli_cmd_otp },
00864 { "passphrase", wpa_cli_cmd_passphrase },
00865 { "bssid", wpa_cli_cmd_bssid },
00866 { "list_networks", wpa_cli_cmd_list_networks },
00867 { "select_network", wpa_cli_cmd_select_network },
00868 { "enable_network", wpa_cli_cmd_enable_network },
00869 { "disable_network", wpa_cli_cmd_disable_network },
00870 { "add_network", wpa_cli_cmd_add_network },
00871 { "remove_network", wpa_cli_cmd_remove_network },
00872 { "set_network", wpa_cli_cmd_set_network },
00873 { "get_network", wpa_cli_cmd_get_network },
00874 { "save_config", wpa_cli_cmd_save_config },
00875 { "disconnect", wpa_cli_cmd_disconnect },
00876 { "scan", wpa_cli_cmd_scan },
00877 { "scan_results", wpa_cli_cmd_scan_results },
00878 { "get_capability", wpa_cli_cmd_get_capability },
00879 { "reconfigure", wpa_cli_cmd_reconfigure },
00880 { "terminate", wpa_cli_cmd_terminate },
00881 { "interface_add", wpa_cli_cmd_interface_add },
00882 { "interface_remove", wpa_cli_cmd_interface_remove },
00883 { NULL, NULL }
00884 };
00885
00886
00887 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
00888 {
00889 struct wpa_cli_cmd *cmd, *match = NULL;
00890 int count;
00891
00892 count = 0;
00893 cmd = wpa_cli_commands;
00894 while (cmd->cmd) {
00895 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
00896 match = cmd;
00897 if (strcasecmp(cmd->cmd, argv[0]) == 0) {
00898
00899 count = 1;
00900 break;
00901 }
00902 count++;
00903 }
00904 cmd++;
00905 }
00906
00907 if (count > 1) {
00908 printf("Ambiguous command '%s'; possible commands:", argv[0]);
00909 cmd = wpa_cli_commands;
00910 while (cmd->cmd) {
00911 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
00912 0) {
00913 printf(" %s", cmd->cmd);
00914 }
00915 cmd++;
00916 }
00917 printf("\n");
00918 } else if (count == 0) {
00919 printf("Unknown command '%s'\n", argv[0]);
00920 } else {
00921 match->handler(ctrl, argc - 1, &argv[1]);
00922 }
00923 }
00924
00925
00926 static int str_match(const char *a, const char *b)
00927 {
00928 return strncmp(a, b, strlen(b)) == 0;
00929 }
00930
00931
00932 static int wpa_cli_exec(const char *program, const char *arg1,
00933 const char *arg2)
00934 {
00935 char *cmd;
00936 size_t len;
00937
00938 len = strlen(program) + strlen(arg1) + strlen(arg2) + 3;
00939 cmd = malloc(len);
00940 if (cmd == NULL)
00941 return -1;
00942 snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
00943 system(cmd);
00944 free(cmd);
00945
00946 return 0;
00947 }
00948
00949
00950 static void wpa_cli_action_process(const char *msg)
00951 {
00952 const char *pos;
00953
00954 pos = msg;
00955 if (*pos == '<') {
00956
00957 pos = strchr(pos, '>');
00958 if (pos)
00959 pos++;
00960 else
00961 pos = msg;
00962 }
00963
00964 if (str_match(pos, WPA_EVENT_CONNECTED)) {
00965 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
00966 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
00967 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
00968 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
00969 printf("wpa_supplicant is terminating - stop monitoring\n");
00970 wpa_cli_quit = 1;
00971 }
00972 }
00973
00974
00975 static void wpa_cli_action_cb(char *msg, size_t len)
00976 {
00977 wpa_cli_action_process(msg);
00978 }
00979
00980
00981 static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
00982 int action_monitor)
00983 {
00984 int first = 1;
00985 if (ctrl_conn == NULL)
00986 return;
00987 while (wpa_ctrl_pending(ctrl)) {
00988 char buf[256];
00989 size_t len = sizeof(buf) - 1;
00990 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
00991 buf[len] = '\0';
00992 if (action_monitor)
00993 wpa_cli_action_process(buf);
00994 else {
00995 if (in_read && first)
00996 printf("\n");
00997 first = 0;
00998 printf("%s\n", buf);
00999 }
01000 } else {
01001 printf("Could not read pending message.\n");
01002 break;
01003 }
01004 }
01005 }
01006
01007
01008 #ifdef CONFIG_READLINE
01009 static char * wpa_cli_cmd_gen(const char *text, int state)
01010 {
01011 static int i, len;
01012 const char *cmd;
01013
01014 if (state == 0) {
01015 i = 0;
01016 len = strlen(text);
01017 }
01018
01019 while ((cmd = wpa_cli_commands[i].cmd)) {
01020 i++;
01021 if (strncasecmp(cmd, text, len) == 0)
01022 return strdup(cmd);
01023 }
01024
01025 return NULL;
01026 }
01027
01028
01029 static char * wpa_cli_dummy_gen(const char *text, int state)
01030 {
01031 return NULL;
01032 }
01033
01034
01035 static char ** wpa_cli_completion(const char *text, int start, int end)
01036 {
01037 return rl_completion_matches(text, start == 0 ?
01038 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
01039 }
01040 #endif
01041
01042
01043 static void wpa_cli_interactive(void)
01044 {
01045 #define max_args 10
01046 char cmdbuf[256], *cmd, *argv[max_args], *pos;
01047 int argc;
01048 #ifdef CONFIG_READLINE
01049 char *home, *hfile = NULL;
01050 #endif
01051
01052 printf("\nInteractive mode\n\n");
01053
01054 #ifdef CONFIG_READLINE
01055 rl_attempted_completion_function = wpa_cli_completion;
01056 home = getenv("HOME");
01057 if (home) {
01058 const char *fname = ".wpa_cli_history";
01059 int hfile_len = strlen(home) + 1 + strlen(fname) + 1;
01060 hfile = malloc(hfile_len);
01061 if (hfile) {
01062 snprintf(hfile, hfile_len, "%s/%s", home, fname);
01063 read_history(hfile);
01064 stifle_history(100);
01065 }
01066 }
01067 #endif
01068
01069 do {
01070 wpa_cli_recv_pending(ctrl_conn, 0, 0);
01071 #ifndef CONFIG_NATIVE_WINDOWS
01072 alarm(1);
01073 #endif
01074 #ifdef CONFIG_READLINE
01075 cmd = readline("> ");
01076 if (cmd && *cmd) {
01077 HIST_ENTRY *h;
01078 while (next_history())
01079 ;
01080 h = previous_history();
01081 if (h == NULL || strcmp(cmd, h->line) != 0)
01082 add_history(cmd);
01083 next_history();
01084 }
01085 #else
01086 printf("> ");
01087 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
01088 #endif
01089 #ifndef CONFIG_NATIVE_WINDOWS
01090 alarm(0);
01091 #endif
01092 if (cmd == NULL)
01093 break;
01094 pos = cmd;
01095 while (*pos != '\0') {
01096 if (*pos == '\n') {
01097 *pos = '\0';
01098 break;
01099 }
01100 pos++;
01101 }
01102 argc = 0;
01103 pos = cmd;
01104 for (;;) {
01105 while (*pos == ' ')
01106 pos++;
01107 if (*pos == '\0')
01108 break;
01109 argv[argc] = pos;
01110 argc++;
01111 if (argc == max_args)
01112 break;
01113 if (*pos == '"') {
01114 char *pos2 = strrchr(pos, '"');
01115 if (pos2)
01116 pos = pos2 + 1;
01117 }
01118 while (*pos != '\0' && *pos != ' ')
01119 pos++;
01120 if (*pos == ' ')
01121 *pos++ = '\0';
01122 }
01123 if (argc)
01124 wpa_request(ctrl_conn, argc, argv);
01125
01126 if (cmd != cmdbuf)
01127 free(cmd);
01128 } while (!wpa_cli_quit);
01129
01130 #ifdef CONFIG_READLINE
01131 if (hfile) {
01132
01133
01134 HIST_ENTRY *h;
01135 history_set_pos(0);
01136 h = next_history();
01137 while (h) {
01138 char *p = h->line;
01139 while (*p == ' ' || *p == '\t')
01140 p++;
01141 if (strncasecmp(p, "pa", 2) == 0 ||
01142 strncasecmp(p, "o", 1) == 0 ||
01143 strncasecmp(p, "n", 1)) {
01144 h = remove_history(where_history());
01145 if (h) {
01146 free(h->line);
01147 free(h->data);
01148 free(h);
01149 }
01150 h = current_history();
01151 } else {
01152 h = next_history();
01153 }
01154 }
01155 write_history(hfile);
01156 free(hfile);
01157 }
01158 #endif
01159 }
01160
01161
01162 static void wpa_cli_action(struct wpa_ctrl *ctrl)
01163 {
01164 fd_set rfds;
01165 int fd, res;
01166 struct timeval tv;
01167 char buf[16];
01168 size_t len;
01169
01170 fd = wpa_ctrl_get_fd(ctrl);
01171
01172 while (!wpa_cli_quit) {
01173 FD_ZERO(&rfds);
01174 FD_SET(fd, &rfds);
01175 tv.tv_sec = 2;
01176 tv.tv_usec = 0;
01177 res = select(fd + 1, &rfds, NULL, NULL, &tv);
01178 if (res < 0 && errno != EINTR) {
01179 perror("select");
01180 break;
01181 }
01182
01183 if (FD_ISSET(fd, &rfds))
01184 wpa_cli_recv_pending(ctrl, 0, 1);
01185 else {
01186
01187 len = sizeof(buf) - 1;
01188 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
01189 wpa_cli_action_cb) < 0 ||
01190 len < 4 || memcmp(buf, "PONG", 4) != 0) {
01191 printf("wpa_supplicant did not reply to PING "
01192 "command - exiting\n");
01193 break;
01194 }
01195 }
01196 }
01197 }
01198
01199
01200 static void wpa_cli_cleanup(void)
01201 {
01202 wpa_cli_close_connection();
01203 if (pid_file)
01204 unlink(pid_file);
01205
01206 #ifdef CONFIG_NATIVE_WINDOWS
01207 WSACleanup();
01208 #endif
01209 }
01210
01211 static void wpa_cli_terminate(int sig)
01212 {
01213 wpa_cli_cleanup();
01214 exit(0);
01215 }
01216
01217
01218 #ifndef CONFIG_NATIVE_WINDOWS
01219 static void wpa_cli_alarm(int sig)
01220 {
01221 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
01222 printf("Connection to wpa_supplicant lost - trying to "
01223 "reconnect\n");
01224 wpa_cli_close_connection();
01225 }
01226 if (!ctrl_conn) {
01227 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
01228 if (ctrl_conn) {
01229 printf("Connection to wpa_supplicant "
01230 "re-established\n");
01231 if (wpa_ctrl_attach(ctrl_conn) == 0) {
01232 wpa_cli_attached = 1;
01233 } else {
01234 printf("Warning: Failed to attach to "
01235 "wpa_supplicant.\n");
01236 }
01237 }
01238 }
01239 if (ctrl_conn)
01240 wpa_cli_recv_pending(ctrl_conn, 1, 0);
01241 alarm(1);
01242 }
01243 #endif
01244
01245
01246 int main(int argc, char *argv[])
01247 {
01248 int interactive;
01249 int warning_displayed = 0;
01250 int c;
01251 int daemonize = 0;
01252 FILE *f;
01253 const char *global = NULL;
01254
01255 #ifdef CONFIG_NATIVE_WINDOWS
01256 WSADATA wsaData;
01257 if (WSAStartup(MAKEWORD(2, 0), &wsaData)) {
01258 printf("Could not find a usable WinSock.dll\n");
01259 return -1;
01260 }
01261 #endif
01262
01263 for (;;) {
01264 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
01265 if (c < 0)
01266 break;
01267 switch (c) {
01268 case 'a':
01269 action_file = optarg;
01270 break;
01271 case 'B':
01272 daemonize = 1;
01273 break;
01274 case 'g':
01275 global = optarg;
01276 break;
01277 case 'h':
01278 usage();
01279 return 0;
01280 case 'v':
01281 printf("%s\n", wpa_cli_version);
01282 return 0;
01283 case 'i':
01284 ctrl_ifname = strdup(optarg);
01285 break;
01286 case 'p':
01287 ctrl_iface_dir = optarg;
01288 break;
01289 case 'P':
01290 pid_file = optarg;
01291 break;
01292 default:
01293 usage();
01294 return -1;
01295 }
01296 }
01297
01298 interactive = (argc == optind) && (action_file == NULL);
01299
01300 if (interactive)
01301 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
01302
01303 if (global) {
01304 ctrl_conn = wpa_ctrl_open(global);
01305 if (ctrl_conn == NULL) {
01306 perror("Failed to connect to wpa_supplicant - "
01307 "wpa_ctrl_open");
01308 return -1;
01309 }
01310 }
01311
01312 for (; !global;) {
01313 if (ctrl_ifname == NULL) {
01314 struct dirent *dent;
01315 DIR *dir = opendir(ctrl_iface_dir);
01316 if (dir) {
01317 while ((dent = readdir(dir))) {
01318 if (strcmp(dent->d_name, ".") == 0 ||
01319 strcmp(dent->d_name, "..") == 0)
01320 continue;
01321 printf("Selected interface '%s'\n",
01322 dent->d_name);
01323 ctrl_ifname = strdup(dent->d_name);
01324 break;
01325 }
01326 closedir(dir);
01327 }
01328 }
01329 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
01330 if (ctrl_conn) {
01331 if (warning_displayed)
01332 printf("Connection established.\n");
01333 break;
01334 }
01335
01336 if (!interactive) {
01337 perror("Failed to connect to wpa_supplicant - "
01338 "wpa_ctrl_open");
01339 return -1;
01340 }
01341
01342 if (!warning_displayed) {
01343 printf("Could not connect to wpa_supplicant - "
01344 "re-trying\n");
01345 warning_displayed = 1;
01346 }
01347 sleep(1);
01348 continue;
01349 }
01350
01351 signal(SIGINT, wpa_cli_terminate);
01352 signal(SIGTERM, wpa_cli_terminate);
01353 #ifndef CONFIG_NATIVE_WINDOWS
01354 signal(SIGALRM, wpa_cli_alarm);
01355 #endif
01356
01357 if (interactive || action_file) {
01358 if (wpa_ctrl_attach(ctrl_conn) == 0) {
01359 wpa_cli_attached = 1;
01360 } else {
01361 printf("Warning: Failed to attach to "
01362 "wpa_supplicant.\n");
01363 if (!interactive)
01364 return -1;
01365 }
01366 }
01367
01368 if (daemonize && daemon(0, 0)) {
01369 perror("daemon");
01370 return -1;
01371 }
01372
01373 if (pid_file) {
01374 f = fopen(pid_file, "w");
01375 if (f) {
01376 fprintf(f, "%u\n", getpid());
01377 fclose(f);
01378 }
01379 }
01380
01381 if (interactive)
01382 wpa_cli_interactive();
01383 else if (action_file)
01384 wpa_cli_action(ctrl_conn);
01385 else
01386 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
01387
01388 free(ctrl_ifname);
01389 wpa_cli_cleanup();
01390
01391 return 0;
01392 }
01393