Use SSID_MAX_LEN define instead of value 32 when comparing SSID length
[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 *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 *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 *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 *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                 "                   [-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 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
926                                        int argc, char *argv[])
927 {
928         char cmd[256];
929         int res;
930         int i;
931         char *tmp;
932         int total;
933
934         if (argc < 2) {
935                 printf("Invalid chan_switch command: needs at least two "
936                        "arguments (count and freq)\n"
937                        "usage: <cs_count> <freq> [sec_channel_offset=] "
938                        "[center_freq1=] [center_freq2=] [bandwidth=] "
939                        "[blocktx] [ht|vht]\n");
940                 return -1;
941         }
942
943         res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
944                           argv[0], argv[1]);
945         if (os_snprintf_error(sizeof(cmd), res)) {
946                 printf("Too long CHAN_SWITCH command.\n");
947                 return -1;
948         }
949
950         total = res;
951         for (i = 2; i < argc; i++) {
952                 tmp = cmd + total;
953                 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
954                 if (os_snprintf_error(sizeof(cmd) - total, res)) {
955                         printf("Too long CHAN_SWITCH command.\n");
956                         return -1;
957                 }
958                 total += res;
959         }
960         return wpa_ctrl_command(ctrl, cmd);
961 }
962
963
964 static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
965                                       char *argv[])
966 {
967         return wpa_ctrl_command(ctrl, "ENABLE");
968 }
969
970
971 static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
972                                       char *argv[])
973 {
974         return wpa_ctrl_command(ctrl, "RELOAD");
975 }
976
977
978 static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
979                                       char *argv[])
980 {
981         return wpa_ctrl_command(ctrl, "DISABLE");
982 }
983
984
985 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
986 {
987         char cmd[256];
988         int res;
989
990         if (argc < 2 || argc > 3) {
991                 printf("Invalid vendor command\n"
992                        "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
993                 return -1;
994         }
995
996         res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
997                           argc == 3 ? argv[2] : "");
998         if (os_snprintf_error(sizeof(cmd), res)) {
999                 printf("Too long VENDOR command.\n");
1000                 return -1;
1001         }
1002         return wpa_ctrl_command(ctrl, cmd);
1003 }
1004
1005
1006 static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
1007                                      char *argv[])
1008 {
1009         return wpa_ctrl_command(ctrl, "ERP_FLUSH");
1010 }
1011
1012
1013 struct hostapd_cli_cmd {
1014         const char *cmd;
1015         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1016 };
1017
1018 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
1019         { "ping", hostapd_cli_cmd_ping },
1020         { "mib", hostapd_cli_cmd_mib },
1021         { "relog", hostapd_cli_cmd_relog },
1022         { "status", hostapd_cli_cmd_status },
1023         { "sta", hostapd_cli_cmd_sta },
1024         { "all_sta", hostapd_cli_cmd_all_sta },
1025         { "new_sta", hostapd_cli_cmd_new_sta },
1026         { "deauthenticate", hostapd_cli_cmd_deauthenticate },
1027         { "disassociate", hostapd_cli_cmd_disassociate },
1028 #ifdef CONFIG_IEEE80211W
1029         { "sa_query", hostapd_cli_cmd_sa_query },
1030 #endif /* CONFIG_IEEE80211W */
1031 #ifdef CONFIG_WPS
1032         { "wps_pin", hostapd_cli_cmd_wps_pin },
1033         { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
1034         { "wps_pbc", hostapd_cli_cmd_wps_pbc },
1035         { "wps_cancel", hostapd_cli_cmd_wps_cancel },
1036 #ifdef CONFIG_WPS_NFC
1037         { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
1038         { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
1039         { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
1040         { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
1041 #endif /* CONFIG_WPS_NFC */
1042         { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
1043         { "wps_config", hostapd_cli_cmd_wps_config },
1044         { "wps_get_status", hostapd_cli_cmd_wps_get_status },
1045 #endif /* CONFIG_WPS */
1046         { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
1047         { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
1048         { "bss_tm_req", hostapd_cli_cmd_bss_tm_req },
1049         { "get_config", hostapd_cli_cmd_get_config },
1050         { "help", hostapd_cli_cmd_help },
1051         { "interface", hostapd_cli_cmd_interface },
1052         { "level", hostapd_cli_cmd_level },
1053         { "license", hostapd_cli_cmd_license },
1054         { "quit", hostapd_cli_cmd_quit },
1055         { "set", hostapd_cli_cmd_set },
1056         { "get", hostapd_cli_cmd_get },
1057         { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set },
1058         { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf },
1059         { "chan_switch", hostapd_cli_cmd_chan_switch },
1060         { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif },
1061         { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req },
1062         { "vendor", hostapd_cli_cmd_vendor },
1063         { "enable", hostapd_cli_cmd_enable },
1064         { "reload", hostapd_cli_cmd_reload },
1065         { "disable", hostapd_cli_cmd_disable },
1066         { "erp_flush", hostapd_cli_cmd_erp_flush },
1067         { NULL, NULL }
1068 };
1069
1070
1071 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1072 {
1073         struct hostapd_cli_cmd *cmd, *match = NULL;
1074         int count;
1075
1076         count = 0;
1077         cmd = hostapd_cli_commands;
1078         while (cmd->cmd) {
1079                 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1080                         match = cmd;
1081                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1082                                 /* we have an exact match */
1083                                 count = 1;
1084                                 break;
1085                         }
1086                         count++;
1087                 }
1088                 cmd++;
1089         }
1090
1091         if (count > 1) {
1092                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1093                 cmd = hostapd_cli_commands;
1094                 while (cmd->cmd) {
1095                         if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1096                             0) {
1097                                 printf(" %s", cmd->cmd);
1098                         }
1099                         cmd++;
1100                 }
1101                 printf("\n");
1102         } else if (count == 0) {
1103                 printf("Unknown command '%s'\n", argv[0]);
1104         } else {
1105                 match->handler(ctrl, argc - 1, &argv[1]);
1106         }
1107 }
1108
1109
1110 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1111                                      int action_monitor)
1112 {
1113         int first = 1;
1114         if (ctrl_conn == NULL)
1115                 return;
1116         while (wpa_ctrl_pending(ctrl)) {
1117                 char buf[256];
1118                 size_t len = sizeof(buf) - 1;
1119                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1120                         buf[len] = '\0';
1121                         if (action_monitor)
1122                                 hostapd_cli_action_process(buf, len);
1123                         else {
1124                                 if (in_read && first)
1125                                         printf("\n");
1126                                 first = 0;
1127                                 printf("%s\n", buf);
1128                         }
1129                 } else {
1130                         printf("Could not read pending message.\n");
1131                         break;
1132                 }
1133         }
1134 }
1135
1136
1137 #define max_args 10
1138
1139 static int tokenize_cmd(char *cmd, char *argv[])
1140 {
1141         char *pos;
1142         int argc = 0;
1143
1144         pos = cmd;
1145         for (;;) {
1146                 while (*pos == ' ')
1147                         pos++;
1148                 if (*pos == '\0')
1149                         break;
1150                 argv[argc] = pos;
1151                 argc++;
1152                 if (argc == max_args)
1153                         break;
1154                 if (*pos == '"') {
1155                         char *pos2 = os_strrchr(pos, '"');
1156                         if (pos2)
1157                                 pos = pos2 + 1;
1158                 }
1159                 while (*pos != '\0' && *pos != ' ')
1160                         pos++;
1161                 if (*pos == ' ')
1162                         *pos++ = '\0';
1163         }
1164
1165         return argc;
1166 }
1167
1168
1169 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1170 {
1171         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1172                 printf("Connection to hostapd lost - trying to reconnect\n");
1173                 hostapd_cli_close_connection();
1174         }
1175         if (!ctrl_conn) {
1176                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1177                 if (ctrl_conn) {
1178                         printf("Connection to hostapd re-established\n");
1179                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
1180                                 hostapd_cli_attached = 1;
1181                         } else {
1182                                 printf("Warning: Failed to attach to "
1183                                        "hostapd.\n");
1184                         }
1185                 }
1186         }
1187         if (ctrl_conn)
1188                 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1189         eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1190 }
1191
1192
1193 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1194 {
1195         eloop_terminate();
1196 }
1197
1198
1199 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1200 {
1201         char *argv[max_args];
1202         int argc;
1203         argc = tokenize_cmd(cmd, argv);
1204         if (argc)
1205                 wpa_request(ctrl_conn, argc, argv);
1206 }
1207
1208
1209 static void hostapd_cli_edit_eof_cb(void *ctx)
1210 {
1211         eloop_terminate();
1212 }
1213
1214
1215 static void hostapd_cli_interactive(void)
1216 {
1217         printf("\nInteractive mode\n\n");
1218
1219         eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1220         edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1221                   NULL, NULL, NULL, NULL);
1222         eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1223
1224         eloop_run();
1225
1226         edit_deinit(NULL, NULL);
1227         eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1228 }
1229
1230
1231 static void hostapd_cli_cleanup(void)
1232 {
1233         hostapd_cli_close_connection();
1234         if (pid_file)
1235                 os_daemonize_terminate(pid_file);
1236
1237         os_program_deinit();
1238 }
1239
1240
1241 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1242 {
1243         fd_set rfds;
1244         int fd, res;
1245         struct timeval tv;
1246         char buf[256];
1247         size_t len;
1248
1249         fd = wpa_ctrl_get_fd(ctrl);
1250
1251         while (!hostapd_cli_quit) {
1252                 FD_ZERO(&rfds);
1253                 FD_SET(fd, &rfds);
1254                 tv.tv_sec = ping_interval;
1255                 tv.tv_usec = 0;
1256                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1257                 if (res < 0 && errno != EINTR) {
1258                         perror("select");
1259                         break;
1260                 }
1261
1262                 if (FD_ISSET(fd, &rfds))
1263                         hostapd_cli_recv_pending(ctrl, 0, 1);
1264                 else {
1265                         len = sizeof(buf) - 1;
1266                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1267                                              hostapd_cli_action_process) < 0 ||
1268                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1269                                 printf("hostapd did not reply to PING "
1270                                        "command - exiting\n");
1271                                 break;
1272                         }
1273                 }
1274         }
1275 }
1276
1277
1278 int main(int argc, char *argv[])
1279 {
1280         int warning_displayed = 0;
1281         int c;
1282         int daemonize = 0;
1283
1284         if (os_program_init())
1285                 return -1;
1286
1287         for (;;) {
1288                 c = getopt(argc, argv, "a:BhG:i:p:v");
1289                 if (c < 0)
1290                         break;
1291                 switch (c) {
1292                 case 'a':
1293                         action_file = optarg;
1294                         break;
1295                 case 'B':
1296                         daemonize = 1;
1297                         break;
1298                 case 'G':
1299                         ping_interval = atoi(optarg);
1300                         break;
1301                 case 'h':
1302                         usage();
1303                         return 0;
1304                 case 'v':
1305                         printf("%s\n", hostapd_cli_version);
1306                         return 0;
1307                 case 'i':
1308                         os_free(ctrl_ifname);
1309                         ctrl_ifname = os_strdup(optarg);
1310                         break;
1311                 case 'p':
1312                         ctrl_iface_dir = optarg;
1313                         break;
1314                 default:
1315                         usage();
1316                         return -1;
1317                 }
1318         }
1319
1320         interactive = (argc == optind) && (action_file == NULL);
1321
1322         if (interactive) {
1323                 printf("%s\n\n%s\n\n", hostapd_cli_version,
1324                        hostapd_cli_license);
1325         }
1326
1327         if (eloop_init())
1328                 return -1;
1329
1330         for (;;) {
1331                 if (ctrl_ifname == NULL) {
1332                         struct dirent *dent;
1333                         DIR *dir = opendir(ctrl_iface_dir);
1334                         if (dir) {
1335                                 while ((dent = readdir(dir))) {
1336                                         if (os_strcmp(dent->d_name, ".") == 0
1337                                             ||
1338                                             os_strcmp(dent->d_name, "..") == 0)
1339                                                 continue;
1340                                         printf("Selected interface '%s'\n",
1341                                                dent->d_name);
1342                                         ctrl_ifname = os_strdup(dent->d_name);
1343                                         break;
1344                                 }
1345                                 closedir(dir);
1346                         }
1347                 }
1348                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1349                 if (ctrl_conn) {
1350                         if (warning_displayed)
1351                                 printf("Connection established.\n");
1352                         break;
1353                 }
1354
1355                 if (!interactive) {
1356                         perror("Failed to connect to hostapd - "
1357                                "wpa_ctrl_open");
1358                         return -1;
1359                 }
1360
1361                 if (!warning_displayed) {
1362                         printf("Could not connect to hostapd - re-trying\n");
1363                         warning_displayed = 1;
1364                 }
1365                 os_sleep(1, 0);
1366                 continue;
1367         }
1368
1369         if (interactive || action_file) {
1370                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1371                         hostapd_cli_attached = 1;
1372                 } else {
1373                         printf("Warning: Failed to attach to hostapd.\n");
1374                         if (action_file)
1375                                 return -1;
1376                 }
1377         }
1378
1379         if (daemonize && os_daemonize(pid_file))
1380                 return -1;
1381
1382         if (interactive)
1383                 hostapd_cli_interactive();
1384         else if (action_file)
1385                 hostapd_cli_action(ctrl_conn);
1386         else
1387                 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1388
1389         os_free(ctrl_ifname);
1390         eloop_destroy();
1391         hostapd_cli_cleanup();
1392         return 0;
1393 }