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