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