hostapd: Add LCI request
[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 struct hostapd_cli_cmd {
1210         const char *cmd;
1211         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1212 };
1213
1214 static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
1215         { "ping", hostapd_cli_cmd_ping },
1216         { "mib", hostapd_cli_cmd_mib },
1217         { "relog", hostapd_cli_cmd_relog },
1218         { "status", hostapd_cli_cmd_status },
1219         { "sta", hostapd_cli_cmd_sta },
1220         { "all_sta", hostapd_cli_cmd_all_sta },
1221         { "new_sta", hostapd_cli_cmd_new_sta },
1222         { "deauthenticate", hostapd_cli_cmd_deauthenticate },
1223         { "disassociate", hostapd_cli_cmd_disassociate },
1224 #ifdef CONFIG_IEEE80211W
1225         { "sa_query", hostapd_cli_cmd_sa_query },
1226 #endif /* CONFIG_IEEE80211W */
1227 #ifdef CONFIG_WPS
1228         { "wps_pin", hostapd_cli_cmd_wps_pin },
1229         { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
1230         { "wps_pbc", hostapd_cli_cmd_wps_pbc },
1231         { "wps_cancel", hostapd_cli_cmd_wps_cancel },
1232 #ifdef CONFIG_WPS_NFC
1233         { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
1234         { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
1235         { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
1236         { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
1237 #endif /* CONFIG_WPS_NFC */
1238         { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
1239         { "wps_config", hostapd_cli_cmd_wps_config },
1240         { "wps_get_status", hostapd_cli_cmd_wps_get_status },
1241 #endif /* CONFIG_WPS */
1242         { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
1243         { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
1244         { "bss_tm_req", hostapd_cli_cmd_bss_tm_req },
1245         { "get_config", hostapd_cli_cmd_get_config },
1246         { "help", hostapd_cli_cmd_help },
1247         { "interface", hostapd_cli_cmd_interface },
1248 #ifdef CONFIG_FST
1249         { "fst", hostapd_cli_cmd_fst },
1250 #endif /* CONFIG_FST */
1251         { "raw", hostapd_cli_cmd_raw },
1252         { "level", hostapd_cli_cmd_level },
1253         { "license", hostapd_cli_cmd_license },
1254         { "quit", hostapd_cli_cmd_quit },
1255         { "set", hostapd_cli_cmd_set },
1256         { "get", hostapd_cli_cmd_get },
1257         { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
1258         { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
1259         { "chan_switch", hostapd_cli_cmd_chan_switch },
1260         { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
1261         { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
1262         { "vendor", hostapd_cli_cmd_vendor },
1263         { "enable", hostapd_cli_cmd_enable },
1264         { "reload", hostapd_cli_cmd_reload },
1265         { "disable", hostapd_cli_cmd_disable },
1266         { "erp_flush", hostapd_cli_cmd_erp_flush },
1267         { "log_level", hostapd_cli_cmd_log_level },
1268         { "pmksa", hostapd_cli_cmd_pmksa },
1269         { "pmksa_flush", hostapd_cli_cmd_pmksa_flush },
1270         { "set_neighbor", hostapd_cli_cmd_set_neighbor },
1271         { "remove_neighbor", hostapd_cli_cmd_remove_neighbor },
1272         { "req_lci", hostapd_cli_cmd_req_lci },
1273         { NULL, NULL }
1274 };
1275
1276
1277 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1278 {
1279         const struct hostapd_cli_cmd *cmd, *match = NULL;
1280         int count;
1281
1282         count = 0;
1283         cmd = hostapd_cli_commands;
1284         while (cmd->cmd) {
1285                 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1286                         match = cmd;
1287                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1288                                 /* we have an exact match */
1289                                 count = 1;
1290                                 break;
1291                         }
1292                         count++;
1293                 }
1294                 cmd++;
1295         }
1296
1297         if (count > 1) {
1298                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1299                 cmd = hostapd_cli_commands;
1300                 while (cmd->cmd) {
1301                         if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1302                             0) {
1303                                 printf(" %s", cmd->cmd);
1304                         }
1305                         cmd++;
1306                 }
1307                 printf("\n");
1308         } else if (count == 0) {
1309                 printf("Unknown command '%s'\n", argv[0]);
1310         } else {
1311                 match->handler(ctrl, argc - 1, &argv[1]);
1312         }
1313 }
1314
1315
1316 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1317                                      int action_monitor)
1318 {
1319         int first = 1;
1320         if (ctrl_conn == NULL)
1321                 return;
1322         while (wpa_ctrl_pending(ctrl)) {
1323                 char buf[256];
1324                 size_t len = sizeof(buf) - 1;
1325                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1326                         buf[len] = '\0';
1327                         if (action_monitor)
1328                                 hostapd_cli_action_process(buf, len);
1329                         else {
1330                                 if (in_read && first)
1331                                         printf("\n");
1332                                 first = 0;
1333                                 printf("%s\n", buf);
1334                         }
1335                 } else {
1336                         printf("Could not read pending message.\n");
1337                         break;
1338                 }
1339         }
1340 }
1341
1342
1343 #define max_args 10
1344
1345 static int tokenize_cmd(char *cmd, char *argv[])
1346 {
1347         char *pos;
1348         int argc = 0;
1349
1350         pos = cmd;
1351         for (;;) {
1352                 while (*pos == ' ')
1353                         pos++;
1354                 if (*pos == '\0')
1355                         break;
1356                 argv[argc] = pos;
1357                 argc++;
1358                 if (argc == max_args)
1359                         break;
1360                 if (*pos == '"') {
1361                         char *pos2 = os_strrchr(pos, '"');
1362                         if (pos2)
1363                                 pos = pos2 + 1;
1364                 }
1365                 while (*pos != '\0' && *pos != ' ')
1366                         pos++;
1367                 if (*pos == ' ')
1368                         *pos++ = '\0';
1369         }
1370
1371         return argc;
1372 }
1373
1374
1375 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1376 {
1377         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1378                 printf("Connection to hostapd lost - trying to reconnect\n");
1379                 hostapd_cli_close_connection();
1380         }
1381         if (!ctrl_conn) {
1382                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1383                 if (ctrl_conn) {
1384                         printf("Connection to hostapd re-established\n");
1385                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
1386                                 hostapd_cli_attached = 1;
1387                         } else {
1388                                 printf("Warning: Failed to attach to "
1389                                        "hostapd.\n");
1390                         }
1391                 }
1392         }
1393         if (ctrl_conn)
1394                 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1395         eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1396 }
1397
1398
1399 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1400 {
1401         eloop_terminate();
1402 }
1403
1404
1405 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1406 {
1407         char *argv[max_args];
1408         int argc;
1409         argc = tokenize_cmd(cmd, argv);
1410         if (argc)
1411                 wpa_request(ctrl_conn, argc, argv);
1412 }
1413
1414
1415 static void hostapd_cli_edit_eof_cb(void *ctx)
1416 {
1417         eloop_terminate();
1418 }
1419
1420
1421 static void hostapd_cli_interactive(void)
1422 {
1423         printf("\nInteractive mode\n\n");
1424
1425         eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1426         edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1427                   NULL, NULL, NULL, NULL);
1428         eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1429
1430         eloop_run();
1431
1432         edit_deinit(NULL, NULL);
1433         eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1434 }
1435
1436
1437 static void hostapd_cli_cleanup(void)
1438 {
1439         hostapd_cli_close_connection();
1440         if (pid_file)
1441                 os_daemonize_terminate(pid_file);
1442
1443         os_program_deinit();
1444 }
1445
1446
1447 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1448 {
1449         fd_set rfds;
1450         int fd, res;
1451         struct timeval tv;
1452         char buf[256];
1453         size_t len;
1454
1455         fd = wpa_ctrl_get_fd(ctrl);
1456
1457         while (!hostapd_cli_quit) {
1458                 FD_ZERO(&rfds);
1459                 FD_SET(fd, &rfds);
1460                 tv.tv_sec = ping_interval;
1461                 tv.tv_usec = 0;
1462                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1463                 if (res < 0 && errno != EINTR) {
1464                         perror("select");
1465                         break;
1466                 }
1467
1468                 if (FD_ISSET(fd, &rfds))
1469                         hostapd_cli_recv_pending(ctrl, 0, 1);
1470                 else {
1471                         len = sizeof(buf) - 1;
1472                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1473                                              hostapd_cli_action_process) < 0 ||
1474                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1475                                 printf("hostapd did not reply to PING "
1476                                        "command - exiting\n");
1477                                 break;
1478                         }
1479                 }
1480         }
1481 }
1482
1483
1484 int main(int argc, char *argv[])
1485 {
1486         int warning_displayed = 0;
1487         int c;
1488         int daemonize = 0;
1489
1490         if (os_program_init())
1491                 return -1;
1492
1493         for (;;) {
1494                 c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
1495                 if (c < 0)
1496                         break;
1497                 switch (c) {
1498                 case 'a':
1499                         action_file = optarg;
1500                         break;
1501                 case 'B':
1502                         daemonize = 1;
1503                         break;
1504                 case 'G':
1505                         ping_interval = atoi(optarg);
1506                         break;
1507                 case 'h':
1508                         usage();
1509                         return 0;
1510                 case 'v':
1511                         printf("%s\n", hostapd_cli_version);
1512                         return 0;
1513                 case 'i':
1514                         os_free(ctrl_ifname);
1515                         ctrl_ifname = os_strdup(optarg);
1516                         break;
1517                 case 'p':
1518                         ctrl_iface_dir = optarg;
1519                         break;
1520                 case 'P':
1521                         pid_file = optarg;
1522                         break;
1523                 case 's':
1524                         client_socket_dir = optarg;
1525                         break;
1526                 default:
1527                         usage();
1528                         return -1;
1529                 }
1530         }
1531
1532         interactive = (argc == optind) && (action_file == NULL);
1533
1534         if (interactive) {
1535                 printf("%s\n\n%s\n\n", hostapd_cli_version,
1536                        hostapd_cli_license);
1537         }
1538
1539         if (eloop_init())
1540                 return -1;
1541
1542         for (;;) {
1543                 if (ctrl_ifname == NULL) {
1544                         struct dirent *dent;
1545                         DIR *dir = opendir(ctrl_iface_dir);
1546                         if (dir) {
1547                                 while ((dent = readdir(dir))) {
1548                                         if (os_strcmp(dent->d_name, ".") == 0
1549                                             ||
1550                                             os_strcmp(dent->d_name, "..") == 0)
1551                                                 continue;
1552                                         printf("Selected interface '%s'\n",
1553                                                dent->d_name);
1554                                         ctrl_ifname = os_strdup(dent->d_name);
1555                                         break;
1556                                 }
1557                                 closedir(dir);
1558                         }
1559                 }
1560                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1561                 if (ctrl_conn) {
1562                         if (warning_displayed)
1563                                 printf("Connection established.\n");
1564                         break;
1565                 }
1566
1567                 if (!interactive) {
1568                         perror("Failed to connect to hostapd - "
1569                                "wpa_ctrl_open");
1570                         return -1;
1571                 }
1572
1573                 if (!warning_displayed) {
1574                         printf("Could not connect to hostapd - re-trying\n");
1575                         warning_displayed = 1;
1576                 }
1577                 os_sleep(1, 0);
1578                 continue;
1579         }
1580
1581         if (interactive || action_file) {
1582                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1583                         hostapd_cli_attached = 1;
1584                 } else {
1585                         printf("Warning: Failed to attach to hostapd.\n");
1586                         if (action_file)
1587                                 return -1;
1588                 }
1589         }
1590
1591         if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
1592                 return -1;
1593
1594         if (interactive)
1595                 hostapd_cli_interactive();
1596         else if (action_file)
1597                 hostapd_cli_action(ctrl_conn);
1598         else
1599                 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1600
1601         os_free(ctrl_ifname);
1602         eloop_destroy();
1603         hostapd_cli_cleanup();
1604         return 0;
1605 }
1606
1607 #else /* CONFIG_NO_CTRL_IFACE */
1608
1609 int main(int argc, char *argv[])
1610 {
1611         return -1;
1612 }
1613
1614 #endif /* CONFIG_NO_CTRL_IFACE */