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