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