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