]> git.ipfire.org Git - thirdparty/hostap.git/blame - wpa_supplicant/wpa_cli.c
Added initial step for IBSS RSN support
[thirdparty/hostap.git] / wpa_supplicant / wpa_cli.c
CommitLineData
6fc6879b
JM
1/*
2 * WPA Supplicant - command line interface for wpa_supplicant daemon
6f78f2fb 3 * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
6fc6879b
JM
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * Alternatively, this software may be distributed under the terms of BSD
10 * license.
11 *
12 * See README and COPYING for more details.
13 */
14
15#include "includes.h"
16
17#ifdef CONFIG_CTRL_IFACE
18
19#ifdef CONFIG_CTRL_IFACE_UNIX
20#include <dirent.h>
21#endif /* CONFIG_CTRL_IFACE_UNIX */
22#ifdef CONFIG_READLINE
23#include <readline/readline.h>
24#include <readline/history.h>
25#endif /* CONFIG_READLINE */
26
27#include "wpa_ctrl.h"
28#include "common.h"
29#include "version.h"
30
31
32static const char *wpa_cli_version =
33"wpa_cli v" VERSION_STR "\n"
6f78f2fb 34"Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> and contributors";
6fc6879b
JM
35
36
37static const char *wpa_cli_license =
38"This program is free software. You can distribute it and/or modify it\n"
39"under the terms of the GNU General Public License version 2.\n"
40"\n"
41"Alternatively, this software may be distributed under the terms of the\n"
42"BSD license. See README and COPYING for more details.\n";
43
44static const char *wpa_cli_full_license =
45"This program is free software; you can redistribute it and/or modify\n"
46"it under the terms of the GNU General Public License version 2 as\n"
47"published by the Free Software Foundation.\n"
48"\n"
49"This program is distributed in the hope that it will be useful,\n"
50"but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
51"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
52"GNU General Public License for more details.\n"
53"\n"
54"You should have received a copy of the GNU General Public License\n"
55"along with this program; if not, write to the Free Software\n"
56"Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
57"\n"
58"Alternatively, this software may be distributed under the terms of the\n"
59"BSD license.\n"
60"\n"
61"Redistribution and use in source and binary forms, with or without\n"
62"modification, are permitted provided that the following conditions are\n"
63"met:\n"
64"\n"
65"1. Redistributions of source code must retain the above copyright\n"
66" notice, this list of conditions and the following disclaimer.\n"
67"\n"
68"2. Redistributions in binary form must reproduce the above copyright\n"
69" notice, this list of conditions and the following disclaimer in the\n"
70" documentation and/or other materials provided with the distribution.\n"
71"\n"
72"3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
73" names of its contributors may be used to endorse or promote products\n"
74" derived from this software without specific prior written permission.\n"
75"\n"
76"THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
77"\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
78"LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
79"A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
80"OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
81"SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
82"LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
83"DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
84"THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
85"(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
86"OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
87"\n";
88
6fc6879b
JM
89static struct wpa_ctrl *ctrl_conn;
90static int wpa_cli_quit = 0;
91static int wpa_cli_attached = 0;
92static int wpa_cli_connected = 0;
93static int wpa_cli_last_id = 0;
94static const char *ctrl_iface_dir = "/var/run/wpa_supplicant";
95static char *ctrl_ifname = NULL;
96static const char *pid_file = NULL;
97static const char *action_file = NULL;
98
99
dfa141b1
ER
100static void print_help();
101
102
6fc6879b
JM
103static void usage(void)
104{
105 printf("wpa_cli [-p<path to ctrl sockets>] [-i<ifname>] [-hvB] "
106 "[-a<action file>] \\\n"
107 " [-P<pid file>] [-g<global ctrl>] [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: /var/run/wpa_supplicant\n"
dfa141b1
ER
115 " default interface: first interface found in socket path\n");
116 print_help();
6fc6879b
JM
117}
118
119
120static struct wpa_ctrl * wpa_cli_open_connection(const char *ifname)
121{
122#if defined(CONFIG_CTRL_IFACE_UDP) || defined(CONFIG_CTRL_IFACE_NAMED_PIPE)
123 ctrl_conn = wpa_ctrl_open(ifname);
124 return ctrl_conn;
125#else /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
126 char *cfile;
127 int flen, res;
128
129 if (ifname == NULL)
130 return NULL;
131
132 flen = os_strlen(ctrl_iface_dir) + os_strlen(ifname) + 2;
133 cfile = os_malloc(flen);
134 if (cfile == NULL)
135 return NULL;
136 res = os_snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
137 if (res < 0 || res >= flen) {
138 os_free(cfile);
139 return NULL;
140 }
141
142 ctrl_conn = wpa_ctrl_open(cfile);
143 os_free(cfile);
144 return ctrl_conn;
145#endif /* CONFIG_CTRL_IFACE_UDP || CONFIG_CTRL_IFACE_NAMED_PIPE */
146}
147
148
149static void wpa_cli_close_connection(void)
150{
151 if (ctrl_conn == NULL)
152 return;
153
154 if (wpa_cli_attached) {
155 wpa_ctrl_detach(ctrl_conn);
156 wpa_cli_attached = 0;
157 }
158 wpa_ctrl_close(ctrl_conn);
159 ctrl_conn = NULL;
160}
161
162
163static void wpa_cli_msg_cb(char *msg, size_t len)
164{
165 printf("%s\n", msg);
166}
167
168
169static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
170{
171 char buf[2048];
172 size_t len;
173 int ret;
174
175 if (ctrl_conn == NULL) {
176 printf("Not connected to wpa_supplicant - command dropped.\n");
177 return -1;
178 }
179 len = sizeof(buf) - 1;
180 ret = wpa_ctrl_request(ctrl, cmd, os_strlen(cmd), buf, &len,
181 wpa_cli_msg_cb);
182 if (ret == -2) {
183 printf("'%s' command timed out.\n", cmd);
184 return -2;
185 } else if (ret < 0) {
186 printf("'%s' command failed.\n", cmd);
187 return -1;
188 }
189 if (print) {
190 buf[len] = '\0';
191 printf("%s", buf);
192 }
193 return 0;
194}
195
196
197static int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
198{
199 return _wpa_ctrl_command(ctrl, cmd, 1);
200}
201
202
203static int wpa_cli_cmd_status(struct wpa_ctrl *ctrl, int argc, char *argv[])
204{
205 int verbose = argc > 0 && os_strcmp(argv[0], "verbose") == 0;
206 return wpa_ctrl_command(ctrl, verbose ? "STATUS-VERBOSE" : "STATUS");
207}
208
209
210static int wpa_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
211{
212 return wpa_ctrl_command(ctrl, "PING");
213}
214
215
216static int wpa_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
217{
218 return wpa_ctrl_command(ctrl, "MIB");
219}
220
221
222static int wpa_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
223{
224 return wpa_ctrl_command(ctrl, "PMKSA");
225}
226
227
228static int wpa_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
229{
dfa141b1 230 print_help();
6fc6879b
JM
231 return 0;
232}
233
234
235static int wpa_cli_cmd_license(struct wpa_ctrl *ctrl, int argc, char *argv[])
236{
237 printf("%s\n\n%s\n", wpa_cli_version, wpa_cli_full_license);
238 return 0;
239}
240
241
242static int wpa_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
243{
244 wpa_cli_quit = 1;
245 return 0;
246}
247
248
249static void wpa_cli_show_variables(void)
250{
251 printf("set variables:\n"
252 " EAPOL::heldPeriod (EAPOL state machine held period, "
253 "in seconds)\n"
254 " EAPOL::authPeriod (EAPOL state machine authentication "
255 "period, in seconds)\n"
256 " EAPOL::startPeriod (EAPOL state machine start period, in "
257 "seconds)\n"
258 " EAPOL::maxStart (EAPOL state machine maximum start "
259 "attempts)\n");
260 printf(" dot11RSNAConfigPMKLifetime (WPA/WPA2 PMK lifetime in "
261 "seconds)\n"
262 " dot11RSNAConfigPMKReauthThreshold (WPA/WPA2 reauthentication"
263 " threshold\n\tpercentage)\n"
264 " dot11RSNAConfigSATimeout (WPA/WPA2 timeout for completing "
265 "security\n\tassociation in seconds)\n");
266}
267
268
269static int wpa_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
270{
271 char cmd[256];
272 int res;
273
274 if (argc == 0) {
275 wpa_cli_show_variables();
276 return 0;
277 }
278
279 if (argc != 2) {
280 printf("Invalid SET command: needs two arguments (variable "
281 "name and value)\n");
282 return -1;
283 }
284
285 res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
286 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
287 printf("Too long SET command.\n");
288 return -1;
289 }
290 return wpa_ctrl_command(ctrl, cmd);
291}
292
293
294static int wpa_cli_cmd_logoff(struct wpa_ctrl *ctrl, int argc, char *argv[])
295{
296 return wpa_ctrl_command(ctrl, "LOGOFF");
297}
298
299
300static int wpa_cli_cmd_logon(struct wpa_ctrl *ctrl, int argc, char *argv[])
301{
302 return wpa_ctrl_command(ctrl, "LOGON");
303}
304
305
306static int wpa_cli_cmd_reassociate(struct wpa_ctrl *ctrl, int argc,
307 char *argv[])
308{
309 return wpa_ctrl_command(ctrl, "REASSOCIATE");
310}
311
312
313static int wpa_cli_cmd_preauthenticate(struct wpa_ctrl *ctrl, int argc,
314 char *argv[])
315{
316 char cmd[256];
317 int res;
318
319 if (argc != 1) {
320 printf("Invalid PREAUTH command: needs one argument "
321 "(BSSID)\n");
322 return -1;
323 }
324
325 res = os_snprintf(cmd, sizeof(cmd), "PREAUTH %s", argv[0]);
326 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
327 printf("Too long PREAUTH command.\n");
328 return -1;
329 }
330 return wpa_ctrl_command(ctrl, cmd);
331}
332
333
334static int wpa_cli_cmd_ap_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
335{
336 char cmd[256];
337 int res;
338
339 if (argc != 1) {
340 printf("Invalid AP_SCAN command: needs one argument (ap_scan "
341 "value)\n");
342 return -1;
343 }
344 res = os_snprintf(cmd, sizeof(cmd), "AP_SCAN %s", argv[0]);
345 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
346 printf("Too long AP_SCAN command.\n");
347 return -1;
348 }
349 return wpa_ctrl_command(ctrl, cmd);
350}
351
352
353static int wpa_cli_cmd_stkstart(struct wpa_ctrl *ctrl, int argc,
354 char *argv[])
355{
356 char cmd[256];
357 int res;
358
359 if (argc != 1) {
360 printf("Invalid STKSTART command: needs one argument "
361 "(Peer STA MAC address)\n");
362 return -1;
363 }
364
365 res = os_snprintf(cmd, sizeof(cmd), "STKSTART %s", argv[0]);
366 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
367 printf("Too long STKSTART command.\n");
368 return -1;
369 }
370 return wpa_ctrl_command(ctrl, cmd);
371}
372
373
374static int wpa_cli_cmd_ft_ds(struct wpa_ctrl *ctrl, int argc, char *argv[])
375{
376 char cmd[256];
377 int res;
378
379 if (argc != 1) {
380 printf("Invalid FT_DS command: needs one argument "
381 "(Target AP MAC address)\n");
382 return -1;
383 }
384
385 res = os_snprintf(cmd, sizeof(cmd), "FT_DS %s", argv[0]);
386 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
387 printf("Too long FT_DS command.\n");
388 return -1;
389 }
390 return wpa_ctrl_command(ctrl, cmd);
391}
392
393
fcc60db4
JM
394static int wpa_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc, char *argv[])
395{
396 char cmd[256];
397 int res;
398
399 if (argc == 0) {
400 /* Any BSSID */
401 return wpa_ctrl_command(ctrl, "WPS_PBC");
402 }
403
404 /* Specific BSSID */
405 res = os_snprintf(cmd, sizeof(cmd), "WPS_PBC %s", argv[0]);
406 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
407 printf("Too long WPS_PBC command.\n");
408 return -1;
409 }
410 return wpa_ctrl_command(ctrl, cmd);
411}
412
413
414static int wpa_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
415{
416 char cmd[256];
417 int res;
418
419 if (argc == 0) {
420 printf("Invalid WPS_PIN command: need one or two arguments:\n"
421 "- BSSID: use 'any' to select any\n"
422 "- PIN: optional, used only with devices that have no "
423 "display\n");
424 return -1;
425 }
426
427 if (argc == 1) {
428 /* Use dynamically generated PIN (returned as reply) */
429 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s", argv[0]);
430 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
431 printf("Too long WPS_PIN command.\n");
432 return -1;
433 }
434 return wpa_ctrl_command(ctrl, cmd);
435 }
436
437 /* Use hardcoded PIN from a label */
438 res = os_snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s", argv[0], argv[1]);
439 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
440 printf("Too long WPS_PIN command.\n");
441 return -1;
442 }
443 return wpa_ctrl_command(ctrl, cmd);
444}
445
446
447static int wpa_cli_cmd_wps_reg(struct wpa_ctrl *ctrl, int argc, char *argv[])
448{
449 char cmd[256];
450 int res;
451
452 if (argc != 2) {
453 printf("Invalid WPS_REG command: need two arguments:\n"
454 "- BSSID: use 'any' to select any\n"
455 "- AP PIN\n");
456 return -1;
457 }
458
459 res = os_snprintf(cmd, sizeof(cmd), "WPS_REG %s %s", argv[0], argv[1]);
460 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
461 printf("Too long WPS_REG command.\n");
462 return -1;
463 }
464 return wpa_ctrl_command(ctrl, cmd);
465}
466
467
11ef8d35
JM
468static int wpa_cli_cmd_ibss_rsn(struct wpa_ctrl *ctrl, int argc, char *argv[])
469{
470 char cmd[256];
471 int res;
472
473 if (argc != 1) {
474 printf("Invalid IBSS_RSN command: needs one argument "
475 "(Peer STA MAC address)\n");
476 return -1;
477 }
478
479 res = os_snprintf(cmd, sizeof(cmd), "IBSS_RSN %s", argv[0]);
480 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
481 printf("Too long IBSS_RSN command.\n");
482 return -1;
483 }
484 return wpa_ctrl_command(ctrl, cmd);
485}
486
487
6fc6879b
JM
488static int wpa_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
489{
490 char cmd[256];
491 int res;
492
493 if (argc != 1) {
494 printf("Invalid LEVEL command: needs one argument (debug "
495 "level)\n");
496 return -1;
497 }
498 res = os_snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
499 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
500 printf("Too long LEVEL command.\n");
501 return -1;
502 }
503 return wpa_ctrl_command(ctrl, cmd);
504}
505
506
507static int wpa_cli_cmd_identity(struct wpa_ctrl *ctrl, int argc, char *argv[])
508{
509 char cmd[256], *pos, *end;
510 int i, ret;
511
512 if (argc < 2) {
513 printf("Invalid IDENTITY command: needs two arguments "
514 "(network id and identity)\n");
515 return -1;
516 }
517
518 end = cmd + sizeof(cmd);
519 pos = cmd;
520 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "IDENTITY-%s:%s",
521 argv[0], argv[1]);
522 if (ret < 0 || ret >= end - pos) {
523 printf("Too long IDENTITY command.\n");
524 return -1;
525 }
526 pos += ret;
527 for (i = 2; i < argc; i++) {
528 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
529 if (ret < 0 || ret >= end - pos) {
530 printf("Too long IDENTITY command.\n");
531 return -1;
532 }
533 pos += ret;
534 }
535
536 return wpa_ctrl_command(ctrl, cmd);
537}
538
539
540static int wpa_cli_cmd_password(struct wpa_ctrl *ctrl, int argc, char *argv[])
541{
542 char cmd[256], *pos, *end;
543 int i, ret;
544
545 if (argc < 2) {
546 printf("Invalid PASSWORD command: needs two arguments "
547 "(network id and password)\n");
548 return -1;
549 }
550
551 end = cmd + sizeof(cmd);
552 pos = cmd;
553 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSWORD-%s:%s",
554 argv[0], argv[1]);
555 if (ret < 0 || ret >= end - pos) {
556 printf("Too long PASSWORD command.\n");
557 return -1;
558 }
559 pos += ret;
560 for (i = 2; i < argc; i++) {
561 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
562 if (ret < 0 || ret >= end - pos) {
563 printf("Too long PASSWORD command.\n");
564 return -1;
565 }
566 pos += ret;
567 }
568
569 return wpa_ctrl_command(ctrl, cmd);
570}
571
572
573static int wpa_cli_cmd_new_password(struct wpa_ctrl *ctrl, int argc,
574 char *argv[])
575{
576 char cmd[256], *pos, *end;
577 int i, ret;
578
579 if (argc < 2) {
580 printf("Invalid NEW_PASSWORD command: needs two arguments "
581 "(network id and password)\n");
582 return -1;
583 }
584
585 end = cmd + sizeof(cmd);
586 pos = cmd;
587 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "NEW_PASSWORD-%s:%s",
588 argv[0], argv[1]);
589 if (ret < 0 || ret >= end - pos) {
590 printf("Too long NEW_PASSWORD command.\n");
591 return -1;
592 }
593 pos += ret;
594 for (i = 2; i < argc; i++) {
595 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
596 if (ret < 0 || ret >= end - pos) {
597 printf("Too long NEW_PASSWORD command.\n");
598 return -1;
599 }
600 pos += ret;
601 }
602
603 return wpa_ctrl_command(ctrl, cmd);
604}
605
606
607static int wpa_cli_cmd_pin(struct wpa_ctrl *ctrl, int argc, char *argv[])
608{
609 char cmd[256], *pos, *end;
610 int i, ret;
611
612 if (argc < 2) {
613 printf("Invalid PIN command: needs two arguments "
614 "(network id and pin)\n");
615 return -1;
616 }
617
618 end = cmd + sizeof(cmd);
619 pos = cmd;
620 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PIN-%s:%s",
621 argv[0], argv[1]);
622 if (ret < 0 || ret >= end - pos) {
623 printf("Too long PIN command.\n");
624 return -1;
625 }
626 pos += ret;
627 for (i = 2; i < argc; i++) {
628 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
629 if (ret < 0 || ret >= end - pos) {
630 printf("Too long PIN command.\n");
631 return -1;
632 }
633 pos += ret;
634 }
635 return wpa_ctrl_command(ctrl, cmd);
636}
637
638
639static int wpa_cli_cmd_otp(struct wpa_ctrl *ctrl, int argc, char *argv[])
640{
641 char cmd[256], *pos, *end;
642 int i, ret;
643
644 if (argc < 2) {
645 printf("Invalid OTP command: needs two arguments (network "
646 "id and password)\n");
647 return -1;
648 }
649
650 end = cmd + sizeof(cmd);
651 pos = cmd;
652 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "OTP-%s:%s",
653 argv[0], argv[1]);
654 if (ret < 0 || ret >= end - pos) {
655 printf("Too long OTP command.\n");
656 return -1;
657 }
658 pos += ret;
659 for (i = 2; i < argc; i++) {
660 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
661 if (ret < 0 || ret >= end - pos) {
662 printf("Too long OTP command.\n");
663 return -1;
664 }
665 pos += ret;
666 }
667
668 return wpa_ctrl_command(ctrl, cmd);
669}
670
671
672static int wpa_cli_cmd_passphrase(struct wpa_ctrl *ctrl, int argc,
673 char *argv[])
674{
675 char cmd[256], *pos, *end;
676 int i, ret;
677
678 if (argc < 2) {
679 printf("Invalid PASSPHRASE command: needs two arguments "
680 "(network id and passphrase)\n");
681 return -1;
682 }
683
684 end = cmd + sizeof(cmd);
685 pos = cmd;
686 ret = os_snprintf(pos, end - pos, WPA_CTRL_RSP "PASSPHRASE-%s:%s",
687 argv[0], argv[1]);
688 if (ret < 0 || ret >= end - pos) {
689 printf("Too long PASSPHRASE command.\n");
690 return -1;
691 }
692 pos += ret;
693 for (i = 2; i < argc; i++) {
694 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
695 if (ret < 0 || ret >= end - pos) {
696 printf("Too long PASSPHRASE command.\n");
697 return -1;
698 }
699 pos += ret;
700 }
701
702 return wpa_ctrl_command(ctrl, cmd);
703}
704
705
706static int wpa_cli_cmd_bssid(struct wpa_ctrl *ctrl, int argc, char *argv[])
707{
708 char cmd[256], *pos, *end;
709 int i, ret;
710
711 if (argc < 2) {
712 printf("Invalid BSSID command: needs two arguments (network "
713 "id and BSSID)\n");
714 return -1;
715 }
716
717 end = cmd + sizeof(cmd);
718 pos = cmd;
719 ret = os_snprintf(pos, end - pos, "BSSID");
720 if (ret < 0 || ret >= end - pos) {
721 printf("Too long BSSID command.\n");
722 return -1;
723 }
724 pos += ret;
725 for (i = 0; i < argc; i++) {
726 ret = os_snprintf(pos, end - pos, " %s", argv[i]);
727 if (ret < 0 || ret >= end - pos) {
728 printf("Too long BSSID command.\n");
729 return -1;
730 }
731 pos += ret;
732 }
733
734 return wpa_ctrl_command(ctrl, cmd);
735}
736
737
738static int wpa_cli_cmd_list_networks(struct wpa_ctrl *ctrl, int argc,
739 char *argv[])
740{
741 return wpa_ctrl_command(ctrl, "LIST_NETWORKS");
742}
743
744
745static int wpa_cli_cmd_select_network(struct wpa_ctrl *ctrl, int argc,
746 char *argv[])
747{
748 char cmd[32];
749 int res;
750
751 if (argc < 1) {
752 printf("Invalid SELECT_NETWORK command: needs one argument "
753 "(network id)\n");
754 return -1;
755 }
756
757 res = os_snprintf(cmd, sizeof(cmd), "SELECT_NETWORK %s", argv[0]);
758 if (res < 0 || (size_t) res >= sizeof(cmd))
759 return -1;
760 cmd[sizeof(cmd) - 1] = '\0';
761
762 return wpa_ctrl_command(ctrl, cmd);
763}
764
765
766static int wpa_cli_cmd_enable_network(struct wpa_ctrl *ctrl, int argc,
767 char *argv[])
768{
769 char cmd[32];
770 int res;
771
772 if (argc < 1) {
773 printf("Invalid ENABLE_NETWORK command: needs one argument "
774 "(network id)\n");
775 return -1;
776 }
777
778 res = os_snprintf(cmd, sizeof(cmd), "ENABLE_NETWORK %s", argv[0]);
779 if (res < 0 || (size_t) res >= sizeof(cmd))
780 return -1;
781 cmd[sizeof(cmd) - 1] = '\0';
782
783 return wpa_ctrl_command(ctrl, cmd);
784}
785
786
787static int wpa_cli_cmd_disable_network(struct wpa_ctrl *ctrl, int argc,
788 char *argv[])
789{
790 char cmd[32];
791 int res;
792
793 if (argc < 1) {
794 printf("Invalid DISABLE_NETWORK command: needs one argument "
795 "(network id)\n");
796 return -1;
797 }
798
799 res = os_snprintf(cmd, sizeof(cmd), "DISABLE_NETWORK %s", argv[0]);
800 if (res < 0 || (size_t) res >= sizeof(cmd))
801 return -1;
802 cmd[sizeof(cmd) - 1] = '\0';
803
804 return wpa_ctrl_command(ctrl, cmd);
805}
806
807
808static int wpa_cli_cmd_add_network(struct wpa_ctrl *ctrl, int argc,
809 char *argv[])
810{
811 return wpa_ctrl_command(ctrl, "ADD_NETWORK");
812}
813
814
815static int wpa_cli_cmd_remove_network(struct wpa_ctrl *ctrl, int argc,
816 char *argv[])
817{
818 char cmd[32];
819 int res;
820
821 if (argc < 1) {
822 printf("Invalid REMOVE_NETWORK command: needs one argument "
823 "(network id)\n");
824 return -1;
825 }
826
827 res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NETWORK %s", argv[0]);
828 if (res < 0 || (size_t) res >= sizeof(cmd))
829 return -1;
830 cmd[sizeof(cmd) - 1] = '\0';
831
832 return wpa_ctrl_command(ctrl, cmd);
833}
834
835
836static void wpa_cli_show_network_variables(void)
837{
838 printf("set_network variables:\n"
839 " ssid (network name, SSID)\n"
840 " psk (WPA passphrase or pre-shared key)\n"
841 " key_mgmt (key management protocol)\n"
842 " identity (EAP identity)\n"
843 " password (EAP password)\n"
844 " ...\n"
845 "\n"
846 "Note: Values are entered in the same format as the "
847 "configuration file is using,\n"
848 "i.e., strings values need to be inside double quotation "
849 "marks.\n"
850 "For example: set_network 1 ssid \"network name\"\n"
851 "\n"
852 "Please see wpa_supplicant.conf documentation for full list "
853 "of\navailable variables.\n");
854}
855
856
857static int wpa_cli_cmd_set_network(struct wpa_ctrl *ctrl, int argc,
858 char *argv[])
859{
860 char cmd[256];
861 int res;
862
863 if (argc == 0) {
864 wpa_cli_show_network_variables();
865 return 0;
866 }
867
868 if (argc != 3) {
869 printf("Invalid SET_NETWORK command: needs three arguments\n"
870 "(network id, variable name, and value)\n");
871 return -1;
872 }
873
874 res = os_snprintf(cmd, sizeof(cmd), "SET_NETWORK %s %s %s",
875 argv[0], argv[1], argv[2]);
876 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
877 printf("Too long SET_NETWORK command.\n");
878 return -1;
879 }
880 return wpa_ctrl_command(ctrl, cmd);
881}
882
883
884static int wpa_cli_cmd_get_network(struct wpa_ctrl *ctrl, int argc,
885 char *argv[])
886{
887 char cmd[256];
888 int res;
889
890 if (argc == 0) {
891 wpa_cli_show_network_variables();
892 return 0;
893 }
894
895 if (argc != 2) {
896 printf("Invalid GET_NETWORK command: needs two arguments\n"
897 "(network id and variable name)\n");
898 return -1;
899 }
900
901 res = os_snprintf(cmd, sizeof(cmd), "GET_NETWORK %s %s",
902 argv[0], argv[1]);
903 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
904 printf("Too long GET_NETWORK command.\n");
905 return -1;
906 }
907 return wpa_ctrl_command(ctrl, cmd);
908}
909
910
911static int wpa_cli_cmd_disconnect(struct wpa_ctrl *ctrl, int argc,
912 char *argv[])
913{
914 return wpa_ctrl_command(ctrl, "DISCONNECT");
915}
916
917
918static int wpa_cli_cmd_reconnect(struct wpa_ctrl *ctrl, int argc,
919 char *argv[])
920{
921 return wpa_ctrl_command(ctrl, "RECONNECT");
922}
923
924
925static int wpa_cli_cmd_save_config(struct wpa_ctrl *ctrl, int argc,
926 char *argv[])
927{
928 return wpa_ctrl_command(ctrl, "SAVE_CONFIG");
929}
930
931
932static int wpa_cli_cmd_scan(struct wpa_ctrl *ctrl, int argc, char *argv[])
933{
934 return wpa_ctrl_command(ctrl, "SCAN");
935}
936
937
938static int wpa_cli_cmd_scan_results(struct wpa_ctrl *ctrl, int argc,
939 char *argv[])
940{
941 return wpa_ctrl_command(ctrl, "SCAN_RESULTS");
942}
943
944
945static int wpa_cli_cmd_bss(struct wpa_ctrl *ctrl, int argc, char *argv[])
946{
947 char cmd[64];
948 int res;
949
950 if (argc != 1) {
951 printf("Invalid BSS command: need one argument (index or "
952 "BSSID)\n");
953 return -1;
954 }
955
956 res = os_snprintf(cmd, sizeof(cmd), "BSS %s", argv[0]);
957 if (res < 0 || (size_t) res >= sizeof(cmd))
958 return -1;
959 cmd[sizeof(cmd) - 1] = '\0';
960
961 return wpa_ctrl_command(ctrl, cmd);
962}
963
964
965static int wpa_cli_cmd_get_capability(struct wpa_ctrl *ctrl, int argc,
966 char *argv[])
967{
968 char cmd[64];
969 int res;
970
971 if (argc < 1 || argc > 2) {
972 printf("Invalid GET_CAPABILITY command: need either one or "
973 "two arguments\n");
974 return -1;
975 }
976
977 if ((argc == 2) && os_strcmp(argv[1], "strict") != 0) {
978 printf("Invalid GET_CAPABILITY command: second argument, "
979 "if any, must be 'strict'\n");
980 return -1;
981 }
982
983 res = os_snprintf(cmd, sizeof(cmd), "GET_CAPABILITY %s%s", argv[0],
984 (argc == 2) ? " strict" : "");
985 if (res < 0 || (size_t) res >= sizeof(cmd))
986 return -1;
987 cmd[sizeof(cmd) - 1] = '\0';
988
989 return wpa_ctrl_command(ctrl, cmd);
990}
991
992
993static int wpa_cli_list_interfaces(struct wpa_ctrl *ctrl)
994{
995 printf("Available interfaces:\n");
996 return wpa_ctrl_command(ctrl, "INTERFACES");
997}
998
999
1000static int wpa_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc, char *argv[])
1001{
1002 if (argc < 1) {
1003 wpa_cli_list_interfaces(ctrl);
1004 return 0;
1005 }
1006
1007 wpa_cli_close_connection();
1008 os_free(ctrl_ifname);
1009 ctrl_ifname = os_strdup(argv[0]);
1010
1011 if (wpa_cli_open_connection(ctrl_ifname)) {
1012 printf("Connected to interface '%s.\n", ctrl_ifname);
1013 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1014 wpa_cli_attached = 1;
1015 } else {
1016 printf("Warning: Failed to attach to "
1017 "wpa_supplicant.\n");
1018 }
1019 } else {
1020 printf("Could not connect to interface '%s' - re-trying\n",
1021 ctrl_ifname);
1022 }
1023 return 0;
1024}
1025
1026
1027static int wpa_cli_cmd_reconfigure(struct wpa_ctrl *ctrl, int argc,
1028 char *argv[])
1029{
1030 return wpa_ctrl_command(ctrl, "RECONFIGURE");
1031}
1032
1033
1034static int wpa_cli_cmd_terminate(struct wpa_ctrl *ctrl, int argc,
1035 char *argv[])
1036{
1037 return wpa_ctrl_command(ctrl, "TERMINATE");
1038}
1039
1040
1041static int wpa_cli_cmd_interface_add(struct wpa_ctrl *ctrl, int argc,
1042 char *argv[])
1043{
1044 char cmd[256];
1045 int res;
1046
1047 if (argc < 1) {
1048 printf("Invalid INTERFACE_ADD command: needs at least one "
1049 "argument (interface name)\n"
1050 "All arguments: ifname confname driver ctrl_interface "
1051 "driver_param bridge_name\n");
1052 return -1;
1053 }
1054
1055 /*
1056 * INTERFACE_ADD <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB
1057 * <driver_param>TAB<bridge_name>
1058 */
1059 res = os_snprintf(cmd, sizeof(cmd),
1060 "INTERFACE_ADD %s\t%s\t%s\t%s\t%s\t%s",
1061 argv[0],
1062 argc > 1 ? argv[1] : "", argc > 2 ? argv[2] : "",
1063 argc > 3 ? argv[3] : "", argc > 4 ? argv[4] : "",
1064 argc > 5 ? argv[5] : "");
1065 if (res < 0 || (size_t) res >= sizeof(cmd))
1066 return -1;
1067 cmd[sizeof(cmd) - 1] = '\0';
1068 return wpa_ctrl_command(ctrl, cmd);
1069}
1070
1071
1072static int wpa_cli_cmd_interface_remove(struct wpa_ctrl *ctrl, int argc,
1073 char *argv[])
1074{
1075 char cmd[128];
1076 int res;
1077
1078 if (argc != 1) {
1079 printf("Invalid INTERFACE_REMOVE command: needs one argument "
1080 "(interface name)\n");
1081 return -1;
1082 }
1083
1084 res = os_snprintf(cmd, sizeof(cmd), "INTERFACE_REMOVE %s", argv[0]);
1085 if (res < 0 || (size_t) res >= sizeof(cmd))
1086 return -1;
1087 cmd[sizeof(cmd) - 1] = '\0';
1088 return wpa_ctrl_command(ctrl, cmd);
1089}
1090
1091
4b4a8ae5
JM
1092static int wpa_cli_cmd_interface_list(struct wpa_ctrl *ctrl, int argc,
1093 char *argv[])
1094{
1095 return wpa_ctrl_command(ctrl, "INTERFACE_LIST");
1096}
1097
1098
40fd868c
ER
1099enum wpa_cli_cmd_flags {
1100 cli_cmd_flag_none = 0x00,
1101 cli_cmd_flag_sensitive = 0x01
1102};
1103
6fc6879b
JM
1104struct wpa_cli_cmd {
1105 const char *cmd;
1106 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
40fd868c 1107 enum wpa_cli_cmd_flags flags;
dfa141b1 1108 const char *usage;
6fc6879b
JM
1109};
1110
1111static struct wpa_cli_cmd wpa_cli_commands[] = {
40fd868c 1112 { "status", wpa_cli_cmd_status,
dfa141b1
ER
1113 cli_cmd_flag_none,
1114 "[verbose] = get current WPA/EAPOL/EAP status" },
40fd868c 1115 { "ping", wpa_cli_cmd_ping,
dfa141b1
ER
1116 cli_cmd_flag_none,
1117 "= pings wpa_supplicant" },
40fd868c 1118 { "mib", wpa_cli_cmd_mib,
dfa141b1
ER
1119 cli_cmd_flag_none,
1120 "= get MIB variables (dot1x, dot11)" },
40fd868c 1121 { "help", wpa_cli_cmd_help,
dfa141b1
ER
1122 cli_cmd_flag_none,
1123 "= show this usage help" },
40fd868c 1124 { "interface", wpa_cli_cmd_interface,
dfa141b1
ER
1125 cli_cmd_flag_none,
1126 "[ifname] = show interfaces/select interface" },
40fd868c 1127 { "level", wpa_cli_cmd_level,
dfa141b1
ER
1128 cli_cmd_flag_none,
1129 "<debug level> = change debug level" },
40fd868c 1130 { "license", wpa_cli_cmd_license,
dfa141b1
ER
1131 cli_cmd_flag_none,
1132 "= show full wpa_cli license" },
40fd868c 1133 { "quit", wpa_cli_cmd_quit,
dfa141b1
ER
1134 cli_cmd_flag_none,
1135 "= exit wpa_cli" },
40fd868c 1136 { "set", wpa_cli_cmd_set,
dfa141b1
ER
1137 cli_cmd_flag_none,
1138 "= set variables (shows list of variables when run without "
1139 "arguments)" },
40fd868c 1140 { "logon", wpa_cli_cmd_logon,
dfa141b1
ER
1141 cli_cmd_flag_none,
1142 "= IEEE 802.1X EAPOL state machine logon" },
40fd868c 1143 { "logoff", wpa_cli_cmd_logoff,
dfa141b1
ER
1144 cli_cmd_flag_none,
1145 "= IEEE 802.1X EAPOL state machine logoff" },
40fd868c 1146 { "pmksa", wpa_cli_cmd_pmksa,
dfa141b1
ER
1147 cli_cmd_flag_none,
1148 "= show PMKSA cache" },
40fd868c 1149 { "reassociate", wpa_cli_cmd_reassociate,
dfa141b1
ER
1150 cli_cmd_flag_none,
1151 "= force reassociation" },
40fd868c 1152 { "preauthenticate", wpa_cli_cmd_preauthenticate,
dfa141b1
ER
1153 cli_cmd_flag_none,
1154 "<BSSID> = force preauthentication" },
40fd868c 1155 { "identity", wpa_cli_cmd_identity,
dfa141b1
ER
1156 cli_cmd_flag_none,
1157 "<network id> <identity> = configure identity for an SSID" },
40fd868c 1158 { "password", wpa_cli_cmd_password,
dfa141b1
ER
1159 cli_cmd_flag_sensitive,
1160 "<network id> <password> = configure password for an SSID" },
40fd868c 1161 { "new_password", wpa_cli_cmd_new_password,
dfa141b1
ER
1162 cli_cmd_flag_sensitive,
1163 "<network id> <password> = change password for an SSID" },
40fd868c 1164 { "pin", wpa_cli_cmd_pin,
dfa141b1
ER
1165 cli_cmd_flag_sensitive,
1166 "<network id> <pin> = configure pin for an SSID" },
40fd868c 1167 { "otp", wpa_cli_cmd_otp,
dfa141b1
ER
1168 cli_cmd_flag_sensitive,
1169 "<network id> <password> = configure one-time-password for an SSID"
1170 },
40fd868c 1171 { "passphrase", wpa_cli_cmd_passphrase,
dfa141b1
ER
1172 cli_cmd_flag_sensitive,
1173 "<network id> <passphrase> = configure private key passphrase\n"
1174 " for an SSID" },
40fd868c 1175 { "bssid", wpa_cli_cmd_bssid,
dfa141b1
ER
1176 cli_cmd_flag_none,
1177 "<network id> <BSSID> = set preferred BSSID for an SSID" },
40fd868c 1178 { "list_networks", wpa_cli_cmd_list_networks,
dfa141b1
ER
1179 cli_cmd_flag_none,
1180 "= list configured networks" },
40fd868c 1181 { "select_network", wpa_cli_cmd_select_network,
dfa141b1
ER
1182 cli_cmd_flag_none,
1183 "<network id> = select a network (disable others)" },
40fd868c 1184 { "enable_network", wpa_cli_cmd_enable_network,
dfa141b1
ER
1185 cli_cmd_flag_none,
1186 "<network id> = enable a network" },
40fd868c 1187 { "disable_network", wpa_cli_cmd_disable_network,
dfa141b1
ER
1188 cli_cmd_flag_none,
1189 "<network id> = disable a network" },
40fd868c 1190 { "add_network", wpa_cli_cmd_add_network,
dfa141b1
ER
1191 cli_cmd_flag_none,
1192 "= add a network" },
40fd868c 1193 { "remove_network", wpa_cli_cmd_remove_network,
dfa141b1
ER
1194 cli_cmd_flag_none,
1195 "<network id> = remove a network" },
40fd868c 1196 { "set_network", wpa_cli_cmd_set_network,
dfa141b1
ER
1197 cli_cmd_flag_sensitive,
1198 "<network id> <variable> <value> = set network variables (shows\n"
1199 " list of variables when run without arguments)" },
40fd868c 1200 { "get_network", wpa_cli_cmd_get_network,
dfa141b1
ER
1201 cli_cmd_flag_none,
1202 "<network id> <variable> = get network variables" },
40fd868c 1203 { "save_config", wpa_cli_cmd_save_config,
dfa141b1
ER
1204 cli_cmd_flag_none,
1205 "= save the current configuration" },
40fd868c 1206 { "disconnect", wpa_cli_cmd_disconnect,
dfa141b1
ER
1207 cli_cmd_flag_none,
1208 "= disconnect and wait for reassociate/reconnect command before\n"
1209 " connecting" },
40fd868c 1210 { "reconnect", wpa_cli_cmd_reconnect,
dfa141b1
ER
1211 cli_cmd_flag_none,
1212 "= like reassociate, but only takes effect if already disconnected"
1213 },
40fd868c 1214 { "scan", wpa_cli_cmd_scan,
dfa141b1
ER
1215 cli_cmd_flag_none,
1216 "= request new BSS scan" },
40fd868c 1217 { "scan_results", wpa_cli_cmd_scan_results,
dfa141b1
ER
1218 cli_cmd_flag_none,
1219 "= get latest scan results" },
40fd868c 1220 { "bss", wpa_cli_cmd_bss,
dfa141b1
ER
1221 cli_cmd_flag_none,
1222 "<<idx> | <bssid>> = get detailed scan result info" },
40fd868c 1223 { "get_capability", wpa_cli_cmd_get_capability,
dfa141b1
ER
1224 cli_cmd_flag_none,
1225 "<eap/pairwise/group/key_mgmt/proto/auth_alg> = get capabilies" },
40fd868c 1226 { "reconfigure", wpa_cli_cmd_reconfigure,
dfa141b1
ER
1227 cli_cmd_flag_none,
1228 "= force wpa_supplicant to re-read its configuration file" },
40fd868c 1229 { "terminate", wpa_cli_cmd_terminate,
dfa141b1
ER
1230 cli_cmd_flag_none,
1231 "= terminate wpa_supplicant" },
40fd868c 1232 { "interface_add", wpa_cli_cmd_interface_add,
dfa141b1
ER
1233 cli_cmd_flag_none,
1234 "<ifname> <confname> <driver> <ctrl_interface> <driver_param>\n"
1235 " <bridge_name> = adds new interface, all parameters but <ifname>\n"
1236 " are optional" },
40fd868c 1237 { "interface_remove", wpa_cli_cmd_interface_remove,
dfa141b1
ER
1238 cli_cmd_flag_none,
1239 "<ifname> = removes the interface" },
40fd868c 1240 { "interface_list", wpa_cli_cmd_interface_list,
dfa141b1
ER
1241 cli_cmd_flag_none,
1242 "= list available interfaces" },
40fd868c 1243 { "ap_scan", wpa_cli_cmd_ap_scan,
dfa141b1
ER
1244 cli_cmd_flag_none,
1245 "<value> = set ap_scan parameter" },
40fd868c 1246 { "stkstart", wpa_cli_cmd_stkstart,
dfa141b1
ER
1247 cli_cmd_flag_none,
1248 "<addr> = request STK negotiation with <addr>" },
40fd868c 1249 { "ft_ds", wpa_cli_cmd_ft_ds,
dfa141b1
ER
1250 cli_cmd_flag_none,
1251 "<addr> = request over-the-DS FT with <addr>" },
40fd868c 1252 { "wps_pbc", wpa_cli_cmd_wps_pbc,
dfa141b1
ER
1253 cli_cmd_flag_none,
1254 "[BSSID] = start Wi-Fi Protected Setup: Push Button Configuration" },
40fd868c 1255 { "wps_pin", wpa_cli_cmd_wps_pin,
dfa141b1
ER
1256 cli_cmd_flag_sensitive,
1257 "<BSSID> [PIN] = start WPS PIN method (returns PIN, if not "
1258 "hardcoded)" },
40fd868c 1259 { "wps_reg", wpa_cli_cmd_wps_reg,
dfa141b1
ER
1260 cli_cmd_flag_sensitive,
1261 "<BSSID> <AP PIN> = start WPS Registrar to configure an AP" },
11ef8d35
JM
1262 { "ibss_rsn", wpa_cli_cmd_ibss_rsn,
1263 cli_cmd_flag_none,
1264 "<addr> = request RSN authentication with <addr> in IBSS" },
dfa141b1 1265 { NULL, NULL, cli_cmd_flag_none, NULL }
6fc6879b
JM
1266};
1267
1268
dfa141b1
ER
1269/*
1270 * Prints command usage, lines are padded with the specified string.
1271 */
1272static void print_cmd_help(struct wpa_cli_cmd *cmd, const char *pad)
1273{
1274 char c;
1275 size_t n;
1276
1277 printf("%s%s ", pad, cmd->cmd);
1278 for (n = 0; (c = cmd->usage[n]); n++) {
1279 printf("%c", c);
1280 if (c == '\n')
1281 printf("%s", pad);
1282 }
1283 printf("\n");
1284}
1285
1286
1287static void print_help(void)
1288{
1289 int n;
1290 printf("commands:\n");
1291 for (n = 0; wpa_cli_commands[n].cmd; n++)
1292 print_cmd_help(&wpa_cli_commands[n], " ");
1293}
1294
1295
40fd868c
ER
1296#ifdef CONFIG_READLINE
1297static int cmd_has_sensitive_data(const char *cmd)
1298{
1299 const char *c, *delim;
1300 int n;
1301 size_t len;
1302
1303 delim = os_strchr(cmd, ' ');
1304 if (delim)
1305 len = delim - cmd;
1306 else
1307 len = os_strlen(cmd);
1308
1309 for (n = 0; (c = wpa_cli_commands[n].cmd); n++) {
1310 if (os_strncasecmp(cmd, c, len) == 0 && len == os_strlen(c))
1311 return (wpa_cli_commands[n].flags &
1312 cli_cmd_flag_sensitive);
1313 }
1314 return 0;
1315}
1316#endif /* CONFIG_READLINE */
1317
1318
6fc6879b
JM
1319static int wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1320{
1321 struct wpa_cli_cmd *cmd, *match = NULL;
1322 int count;
1323 int ret = 0;
1324
1325 count = 0;
1326 cmd = wpa_cli_commands;
1327 while (cmd->cmd) {
1328 if (os_strncasecmp(cmd->cmd, argv[0], os_strlen(argv[0])) == 0)
1329 {
1330 match = cmd;
1331 if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1332 /* we have an exact match */
1333 count = 1;
1334 break;
1335 }
1336 count++;
1337 }
1338 cmd++;
1339 }
1340
1341 if (count > 1) {
1342 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1343 cmd = wpa_cli_commands;
1344 while (cmd->cmd) {
1345 if (os_strncasecmp(cmd->cmd, argv[0],
1346 os_strlen(argv[0])) == 0) {
1347 printf(" %s", cmd->cmd);
1348 }
1349 cmd++;
1350 }
1351 printf("\n");
1352 ret = 1;
1353 } else if (count == 0) {
1354 printf("Unknown command '%s'\n", argv[0]);
1355 ret = 1;
1356 } else {
1357 ret = match->handler(ctrl, argc - 1, &argv[1]);
1358 }
1359
1360 return ret;
1361}
1362
1363
1364static int str_match(const char *a, const char *b)
1365{
1366 return os_strncmp(a, b, os_strlen(b)) == 0;
1367}
1368
1369
1370static int wpa_cli_exec(const char *program, const char *arg1,
1371 const char *arg2)
1372{
1373 char *cmd;
1374 size_t len;
1375 int res;
308a4ec8 1376 int ret = 0;
6fc6879b
JM
1377
1378 len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
1379 cmd = os_malloc(len);
1380 if (cmd == NULL)
1381 return -1;
1382 res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
1383 if (res < 0 || (size_t) res >= len) {
1384 os_free(cmd);
1385 return -1;
1386 }
1387 cmd[len - 1] = '\0';
1388#ifndef _WIN32_WCE
308a4ec8
JM
1389 if (system(cmd) < 0)
1390 ret = -1;
6fc6879b
JM
1391#endif /* _WIN32_WCE */
1392 os_free(cmd);
1393
308a4ec8 1394 return ret;
6fc6879b
JM
1395}
1396
1397
1398static void wpa_cli_action_process(const char *msg)
1399{
1400 const char *pos;
1401 char *copy = NULL, *id, *pos2;
1402
1403 pos = msg;
1404 if (*pos == '<') {
1405 /* skip priority */
1406 pos = os_strchr(pos, '>');
1407 if (pos)
1408 pos++;
1409 else
1410 pos = msg;
1411 }
1412
1413 if (str_match(pos, WPA_EVENT_CONNECTED)) {
1414 int new_id = -1;
1415 os_unsetenv("WPA_ID");
1416 os_unsetenv("WPA_ID_STR");
1417 os_unsetenv("WPA_CTRL_DIR");
1418
1419 pos = os_strstr(pos, "[id=");
1420 if (pos)
1421 copy = os_strdup(pos + 4);
1422
1423 if (copy) {
1424 pos2 = id = copy;
1425 while (*pos2 && *pos2 != ' ')
1426 pos2++;
1427 *pos2++ = '\0';
1428 new_id = atoi(id);
1429 os_setenv("WPA_ID", id, 1);
1430 while (*pos2 && *pos2 != '=')
1431 pos2++;
1432 if (*pos2 == '=')
1433 pos2++;
1434 id = pos2;
1435 while (*pos2 && *pos2 != ']')
1436 pos2++;
1437 *pos2 = '\0';
1438 os_setenv("WPA_ID_STR", id, 1);
1439 os_free(copy);
1440 }
1441
1442 os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);
1443
1444 if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
1445 wpa_cli_connected = 1;
1446 wpa_cli_last_id = new_id;
1447 wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
1448 }
1449 } else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
1450 if (wpa_cli_connected) {
1451 wpa_cli_connected = 0;
1452 wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
1453 }
1454 } else if (str_match(pos, WPA_EVENT_TERMINATING)) {
1455 printf("wpa_supplicant is terminating - stop monitoring\n");
1456 wpa_cli_quit = 1;
1457 }
1458}
1459
1460
1461#ifndef CONFIG_ANSI_C_EXTRA
1462static void wpa_cli_action_cb(char *msg, size_t len)
1463{
1464 wpa_cli_action_process(msg);
1465}
1466#endif /* CONFIG_ANSI_C_EXTRA */
1467
1468
1469static void wpa_cli_reconnect(void)
1470{
1471 wpa_cli_close_connection();
1472 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1473 if (ctrl_conn) {
1474 printf("Connection to wpa_supplicant re-established\n");
1475 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1476 wpa_cli_attached = 1;
1477 } else {
1478 printf("Warning: Failed to attach to "
1479 "wpa_supplicant.\n");
1480 }
1481 }
1482}
1483
1484
1485static void wpa_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1486 int action_monitor)
1487{
1488 int first = 1;
1489 if (ctrl_conn == NULL) {
1490 wpa_cli_reconnect();
1491 return;
1492 }
1493 while (wpa_ctrl_pending(ctrl) > 0) {
1494 char buf[256];
1495 size_t len = sizeof(buf) - 1;
1496 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1497 buf[len] = '\0';
1498 if (action_monitor)
1499 wpa_cli_action_process(buf);
1500 else {
1501 if (in_read && first)
1502 printf("\n");
1503 first = 0;
1504 printf("%s\n", buf);
1505 }
1506 } else {
1507 printf("Could not read pending message.\n");
1508 break;
1509 }
1510 }
1511
1512 if (wpa_ctrl_pending(ctrl) < 0) {
1513 printf("Connection to wpa_supplicant lost - trying to "
1514 "reconnect\n");
1515 wpa_cli_reconnect();
1516 }
1517}
1518
1519
1520#ifdef CONFIG_READLINE
1521static char * wpa_cli_cmd_gen(const char *text, int state)
1522{
1523 static int i, len;
1524 const char *cmd;
1525
1526 if (state == 0) {
1527 i = 0;
1528 len = os_strlen(text);
1529 }
1530
1531 while ((cmd = wpa_cli_commands[i].cmd)) {
1532 i++;
1533 if (os_strncasecmp(cmd, text, len) == 0)
1534 return os_strdup(cmd);
1535 }
1536
1537 return NULL;
1538}
1539
1540
1541static char * wpa_cli_dummy_gen(const char *text, int state)
1542{
1543 return NULL;
1544}
1545
1546
1547static char ** wpa_cli_completion(const char *text, int start, int end)
1548{
1549 return rl_completion_matches(text, start == 0 ?
1550 wpa_cli_cmd_gen : wpa_cli_dummy_gen);
1551}
1552#endif /* CONFIG_READLINE */
1553
1554
1555static void wpa_cli_interactive(void)
1556{
1557#define max_args 10
1558 char cmdbuf[256], *cmd, *argv[max_args], *pos;
1559 int argc;
1560#ifdef CONFIG_READLINE
1561 char *home, *hfile = NULL;
1562#endif /* CONFIG_READLINE */
1563
1564 printf("\nInteractive mode\n\n");
1565
1566#ifdef CONFIG_READLINE
1567 rl_attempted_completion_function = wpa_cli_completion;
1568 home = getenv("HOME");
1569 if (home) {
1570 const char *fname = ".wpa_cli_history";
1571 int hfile_len = os_strlen(home) + 1 + os_strlen(fname) + 1;
1572 hfile = os_malloc(hfile_len);
1573 if (hfile) {
1574 int res;
1575 res = os_snprintf(hfile, hfile_len, "%s/%s", home,
1576 fname);
1577 if (res >= 0 && res < hfile_len) {
1578 hfile[hfile_len - 1] = '\0';
1579 read_history(hfile);
1580 stifle_history(100);
1581 }
1582 }
1583 }
1584#endif /* CONFIG_READLINE */
1585
1586 do {
1587 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1588#ifndef CONFIG_NATIVE_WINDOWS
1589 alarm(1);
1590#endif /* CONFIG_NATIVE_WINDOWS */
1591#ifdef CONFIG_READLINE
1592 cmd = readline("> ");
1593 if (cmd && *cmd) {
1594 HIST_ENTRY *h;
1595 while (next_history())
1596 ;
1597 h = previous_history();
1598 if (h == NULL || os_strcmp(cmd, h->line) != 0)
1599 add_history(cmd);
1600 next_history();
1601 }
1602#else /* CONFIG_READLINE */
1603 printf("> ");
1604 cmd = fgets(cmdbuf, sizeof(cmdbuf), stdin);
1605#endif /* CONFIG_READLINE */
1606#ifndef CONFIG_NATIVE_WINDOWS
1607 alarm(0);
1608#endif /* CONFIG_NATIVE_WINDOWS */
1609 if (cmd == NULL)
1610 break;
1611 wpa_cli_recv_pending(ctrl_conn, 0, 0);
1612 pos = cmd;
1613 while (*pos != '\0') {
1614 if (*pos == '\n') {
1615 *pos = '\0';
1616 break;
1617 }
1618 pos++;
1619 }
1620 argc = 0;
1621 pos = cmd;
1622 for (;;) {
1623 while (*pos == ' ')
1624 pos++;
1625 if (*pos == '\0')
1626 break;
1627 argv[argc] = pos;
1628 argc++;
1629 if (argc == max_args)
1630 break;
1631 if (*pos == '"') {
1632 char *pos2 = os_strrchr(pos, '"');
1633 if (pos2)
1634 pos = pos2 + 1;
1635 }
1636 while (*pos != '\0' && *pos != ' ')
1637 pos++;
1638 if (*pos == ' ')
1639 *pos++ = '\0';
1640 }
1641 if (argc)
1642 wpa_request(ctrl_conn, argc, argv);
1643
1644 if (cmd != cmdbuf)
1645 os_free(cmd);
1646 } while (!wpa_cli_quit);
1647
1648#ifdef CONFIG_READLINE
1649 if (hfile) {
1650 /* Save command history, excluding lines that may contain
1651 * passwords. */
1652 HIST_ENTRY *h;
1653 history_set_pos(0);
413653e8 1654 while ((h = current_history())) {
6fc6879b
JM
1655 char *p = h->line;
1656 while (*p == ' ' || *p == '\t')
1657 p++;
40fd868c 1658 if (cmd_has_sensitive_data(p)) {
6fc6879b
JM
1659 h = remove_history(where_history());
1660 if (h) {
1661 os_free(h->line);
1662 os_free(h->data);
1663 os_free(h);
413653e8
ER
1664 } else
1665 next_history();
1666 } else
1667 next_history();
6fc6879b
JM
1668 }
1669 write_history(hfile);
1670 os_free(hfile);
1671 }
1672#endif /* CONFIG_READLINE */
1673}
1674
1675
1676static void wpa_cli_action(struct wpa_ctrl *ctrl)
1677{
1678#ifdef CONFIG_ANSI_C_EXTRA
1679 /* TODO: ANSI C version(?) */
1680 printf("Action processing not supported in ANSI C build.\n");
1681#else /* CONFIG_ANSI_C_EXTRA */
1682 fd_set rfds;
1683 int fd, res;
1684 struct timeval tv;
1685 char buf[256]; /* note: large enough to fit in unsolicited messages */
1686 size_t len;
1687
1688 fd = wpa_ctrl_get_fd(ctrl);
1689
1690 while (!wpa_cli_quit) {
1691 FD_ZERO(&rfds);
1692 FD_SET(fd, &rfds);
1693 tv.tv_sec = 2;
1694 tv.tv_usec = 0;
1695 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1696 if (res < 0 && errno != EINTR) {
1697 perror("select");
1698 break;
1699 }
1700
1701 if (FD_ISSET(fd, &rfds))
1702 wpa_cli_recv_pending(ctrl, 0, 1);
1703 else {
1704 /* verify that connection is still working */
1705 len = sizeof(buf) - 1;
1706 if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1707 wpa_cli_action_cb) < 0 ||
1708 len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1709 printf("wpa_supplicant did not reply to PING "
1710 "command - exiting\n");
1711 break;
1712 }
1713 }
1714 }
1715#endif /* CONFIG_ANSI_C_EXTRA */
1716}
1717
1718
1719static void wpa_cli_cleanup(void)
1720{
1721 wpa_cli_close_connection();
1722 if (pid_file)
1723 os_daemonize_terminate(pid_file);
1724
1725 os_program_deinit();
1726}
1727
1728static void wpa_cli_terminate(int sig)
1729{
1730 wpa_cli_cleanup();
1731 exit(0);
1732}
1733
1734
1735#ifndef CONFIG_NATIVE_WINDOWS
1736static void wpa_cli_alarm(int sig)
1737{
1738 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1739 printf("Connection to wpa_supplicant lost - trying to "
1740 "reconnect\n");
1741 wpa_cli_close_connection();
1742 }
1743 if (!ctrl_conn)
1744 wpa_cli_reconnect();
1745 if (ctrl_conn)
1746 wpa_cli_recv_pending(ctrl_conn, 1, 0);
1747 alarm(1);
1748}
1749#endif /* CONFIG_NATIVE_WINDOWS */
1750
1751
1752static char * wpa_cli_get_default_ifname(void)
1753{
1754 char *ifname = NULL;
1755
1756#ifdef CONFIG_CTRL_IFACE_UNIX
1757 struct dirent *dent;
1758 DIR *dir = opendir(ctrl_iface_dir);
1759 if (!dir)
1760 return NULL;
1761 while ((dent = readdir(dir))) {
1762#ifdef _DIRENT_HAVE_D_TYPE
1763 /*
1764 * Skip the file if it is not a socket. Also accept
1765 * DT_UNKNOWN (0) in case the C library or underlying
1766 * file system does not support d_type.
1767 */
1768 if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
1769 continue;
1770#endif /* _DIRENT_HAVE_D_TYPE */
1771 if (os_strcmp(dent->d_name, ".") == 0 ||
1772 os_strcmp(dent->d_name, "..") == 0)
1773 continue;
1774 printf("Selected interface '%s'\n", dent->d_name);
1775 ifname = os_strdup(dent->d_name);
1776 break;
1777 }
1778 closedir(dir);
1779#endif /* CONFIG_CTRL_IFACE_UNIX */
1780
1781#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1782 char buf[2048], *pos;
1783 size_t len;
1784 struct wpa_ctrl *ctrl;
1785 int ret;
1786
1787 ctrl = wpa_ctrl_open(NULL);
1788 if (ctrl == NULL)
1789 return NULL;
1790
1791 len = sizeof(buf) - 1;
1792 ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
1793 if (ret >= 0) {
1794 buf[len] = '\0';
1795 pos = os_strchr(buf, '\n');
1796 if (pos)
1797 *pos = '\0';
1798 ifname = os_strdup(buf);
1799 }
1800 wpa_ctrl_close(ctrl);
1801#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1802
1803 return ifname;
1804}
1805
1806
1807int main(int argc, char *argv[])
1808{
1809 int interactive;
1810 int warning_displayed = 0;
1811 int c;
1812 int daemonize = 0;
1813 int ret = 0;
1814 const char *global = NULL;
1815
1816 if (os_program_init())
1817 return -1;
1818
1819 for (;;) {
1820 c = getopt(argc, argv, "a:Bg:hi:p:P:v");
1821 if (c < 0)
1822 break;
1823 switch (c) {
1824 case 'a':
1825 action_file = optarg;
1826 break;
1827 case 'B':
1828 daemonize = 1;
1829 break;
1830 case 'g':
1831 global = optarg;
1832 break;
1833 case 'h':
1834 usage();
1835 return 0;
1836 case 'v':
1837 printf("%s\n", wpa_cli_version);
1838 return 0;
1839 case 'i':
1840 os_free(ctrl_ifname);
1841 ctrl_ifname = os_strdup(optarg);
1842 break;
1843 case 'p':
1844 ctrl_iface_dir = optarg;
1845 break;
1846 case 'P':
1847 pid_file = optarg;
1848 break;
1849 default:
1850 usage();
1851 return -1;
1852 }
1853 }
1854
1855 interactive = (argc == optind) && (action_file == NULL);
1856
1857 if (interactive)
1858 printf("%s\n\n%s\n\n", wpa_cli_version, wpa_cli_license);
1859
1860 if (global) {
1861#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
1862 ctrl_conn = wpa_ctrl_open(NULL);
1863#else /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1864 ctrl_conn = wpa_ctrl_open(global);
1865#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */
1866 if (ctrl_conn == NULL) {
1867 perror("Failed to connect to wpa_supplicant - "
1868 "wpa_ctrl_open");
1869 return -1;
1870 }
1871 }
1872
1873 for (; !global;) {
1874 if (ctrl_ifname == NULL)
1875 ctrl_ifname = wpa_cli_get_default_ifname();
1876 ctrl_conn = wpa_cli_open_connection(ctrl_ifname);
1877 if (ctrl_conn) {
1878 if (warning_displayed)
1879 printf("Connection established.\n");
1880 break;
1881 }
1882
1883 if (!interactive) {
1884 perror("Failed to connect to wpa_supplicant - "
1885 "wpa_ctrl_open");
1886 return -1;
1887 }
1888
1889 if (!warning_displayed) {
1890 printf("Could not connect to wpa_supplicant - "
1891 "re-trying\n");
1892 warning_displayed = 1;
1893 }
1894 os_sleep(1, 0);
1895 continue;
1896 }
1897
1898#ifndef _WIN32_WCE
1899 signal(SIGINT, wpa_cli_terminate);
1900 signal(SIGTERM, wpa_cli_terminate);
1901#endif /* _WIN32_WCE */
1902#ifndef CONFIG_NATIVE_WINDOWS
1903 signal(SIGALRM, wpa_cli_alarm);
1904#endif /* CONFIG_NATIVE_WINDOWS */
1905
1906 if (interactive || action_file) {
1907 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1908 wpa_cli_attached = 1;
1909 } else {
1910 printf("Warning: Failed to attach to "
1911 "wpa_supplicant.\n");
1912 if (!interactive)
1913 return -1;
1914 }
1915 }
1916
1917 if (daemonize && os_daemonize(pid_file))
1918 return -1;
1919
1920 if (interactive)
1921 wpa_cli_interactive();
1922 else if (action_file)
1923 wpa_cli_action(ctrl_conn);
1924 else
1925 ret = wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1926
1927 os_free(ctrl_ifname);
1928 wpa_cli_cleanup();
1929
1930 return ret;
1931}
1932
1933#else /* CONFIG_CTRL_IFACE */
1934int main(int argc, char *argv[])
1935{
1936 printf("CONFIG_CTRL_IFACE not defined - wpa_cli disabled\n");
1937 return -1;
1938}
1939#endif /* CONFIG_CTRL_IFACE */