WPS UFD: Build OOB functionality only if UFD is enabled
[wpasupplicant] / hostapd / hostapd_cli.c
1 /*
2  * hostapd - command line interface for hostapd daemon
3  * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16 #include <dirent.h>
17
18 #include "wpa_ctrl.h"
19 #include "common.h"
20 #include "version.h"
21
22
23 static const char *hostapd_cli_version =
24 "hostapd_cli v" VERSION_STR "\n"
25 "Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> and contributors";
26
27
28 static const char *hostapd_cli_license =
29 "This program is free software. You can distribute it and/or modify it\n"
30 "under the terms of the GNU General Public License version 2.\n"
31 "\n"
32 "Alternatively, this software may be distributed under the terms of the\n"
33 "BSD license. See README and COPYING for more details.\n";
34
35 static const char *hostapd_cli_full_license =
36 "This program is free software; you can redistribute it and/or modify\n"
37 "it under the terms of the GNU General Public License version 2 as\n"
38 "published by the Free Software Foundation.\n"
39 "\n"
40 "This program is distributed in the hope that it will be useful,\n"
41 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
42 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
43 "GNU General Public License for more details.\n"
44 "\n"
45 "You should have received a copy of the GNU General Public License\n"
46 "along with this program; if not, write to the Free Software\n"
47 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n"
48 "\n"
49 "Alternatively, this software may be distributed under the terms of the\n"
50 "BSD license.\n"
51 "\n"
52 "Redistribution and use in source and binary forms, with or without\n"
53 "modification, are permitted provided that the following conditions are\n"
54 "met:\n"
55 "\n"
56 "1. Redistributions of source code must retain the above copyright\n"
57 "   notice, this list of conditions and the following disclaimer.\n"
58 "\n"
59 "2. Redistributions in binary form must reproduce the above copyright\n"
60 "   notice, this list of conditions and the following disclaimer in the\n"
61 "   documentation and/or other materials provided with the distribution.\n"
62 "\n"
63 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
64 "   names of its contributors may be used to endorse or promote products\n"
65 "   derived from this software without specific prior written permission.\n"
66 "\n"
67 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
68 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
69 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
70 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
71 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
72 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
73 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
74 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
75 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
76 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
77 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
78 "\n";
79
80 static const char *commands_help =
81 "Commands:\n"
82 "   mib                  get MIB variables (dot1x, dot11, radius)\n"
83 "   sta <addr>           get MIB variables for one station\n"
84 "   all_sta              get MIB variables for all stations\n"
85 "   new_sta <addr>       add a new station\n"
86 #ifdef CONFIG_IEEE80211W
87 "   sa_query <addr>      send SA Query to a station\n"
88 #endif /* CONFIG_IEEE80211W */
89 #ifdef CONFIG_WPS
90 "   wps_pin <uuid> <pin> add WPS Enrollee PIN (Device Password)\n"
91 "   wps_pbc              indicate button pushed to initiate PBC\n"
92 #ifdef CONFIG_WPS_OOB
93 "   wps_oob <type> <path> <method>  use WPS with out-of-band (UFD)\n"
94 #endif /* CONFIG_WPS_OOB */
95 #endif /* CONFIG_WPS */
96 "   help                 show this usage help\n"
97 "   interface [ifname]   show interfaces/select interface\n"
98 "   level <debug level>  change debug level\n"
99 "   license              show full hostapd_cli license\n"
100 "   quit                 exit hostapd_cli\n";
101
102 static struct wpa_ctrl *ctrl_conn;
103 static int hostapd_cli_quit = 0;
104 static int hostapd_cli_attached = 0;
105 static const char *ctrl_iface_dir = "/var/run/hostapd";
106 static char *ctrl_ifname = NULL;
107 static int ping_interval = 5;
108
109
110 static void usage(void)
111 {
112         fprintf(stderr, "%s\n", hostapd_cli_version);
113         fprintf(stderr, 
114                 "\n"    
115                 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hv] "
116                 "[-G<ping interval>] \\\n"
117                 "        [command..]\n"
118                 "\n"
119                 "Options:\n"
120                 "   -h           help (show this usage text)\n"
121                 "   -v           shown version information\n"
122                 "   -p<path>     path to find control sockets (default: "
123                 "/var/run/hostapd)\n"
124                 "   -i<ifname>   Interface to listen on (default: first "
125                 "interface found in the\n"
126                 "                socket path)\n\n"
127                 "%s",
128                 commands_help);
129 }
130
131
132 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
133 {
134         char *cfile;
135         int flen;
136
137         if (ifname == NULL)
138                 return NULL;
139
140         flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
141         cfile = malloc(flen);
142         if (cfile == NULL)
143                 return NULL;
144         snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
145
146         ctrl_conn = wpa_ctrl_open(cfile);
147         free(cfile);
148         return ctrl_conn;
149 }
150
151
152 static void hostapd_cli_close_connection(void)
153 {
154         if (ctrl_conn == NULL)
155                 return;
156
157         if (hostapd_cli_attached) {
158                 wpa_ctrl_detach(ctrl_conn);
159                 hostapd_cli_attached = 0;
160         }
161         wpa_ctrl_close(ctrl_conn);
162         ctrl_conn = NULL;
163 }
164
165
166 static void hostapd_cli_msg_cb(char *msg, size_t len)
167 {
168         printf("%s\n", msg);
169 }
170
171
172 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
173 {
174         char buf[4096];
175         size_t len;
176         int ret;
177
178         if (ctrl_conn == NULL) {
179                 printf("Not connected to hostapd - command dropped.\n");
180                 return -1;
181         }
182         len = sizeof(buf) - 1;
183         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
184                                hostapd_cli_msg_cb);
185         if (ret == -2) {
186                 printf("'%s' command timed out.\n", cmd);
187                 return -2;
188         } else if (ret < 0) {
189                 printf("'%s' command failed.\n", cmd);
190                 return -1;
191         }
192         if (print) {
193                 buf[len] = '\0';
194                 printf("%s", buf);
195         }
196         return 0;
197 }
198
199
200 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
201 {
202         return _wpa_ctrl_command(ctrl, cmd, 1);
203 }
204
205
206 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
207 {
208         return wpa_ctrl_command(ctrl, "PING");
209 }
210
211
212 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
213 {
214         return wpa_ctrl_command(ctrl, "MIB");
215 }
216
217
218 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
219 {
220         char buf[64];
221         if (argc != 1) {
222                 printf("Invalid 'sta' command - exactly one argument, STA "
223                        "address, is required.\n");
224                 return -1;
225         }
226         snprintf(buf, sizeof(buf), "STA %s", argv[0]);
227         return wpa_ctrl_command(ctrl, buf);
228 }
229
230
231 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
232                                    char *argv[])
233 {
234         char buf[64];
235         if (argc != 1) {
236                 printf("Invalid 'new_sta' command - exactly one argument, STA "
237                        "address, is required.\n");
238                 return -1;
239         }
240         snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
241         return wpa_ctrl_command(ctrl, buf);
242 }
243
244
245 #ifdef CONFIG_IEEE80211W
246 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
247                                     char *argv[])
248 {
249         char buf[64];
250         if (argc != 1) {
251                 printf("Invalid 'sa_query' command - exactly one argument, "
252                        "STA address, is required.\n");
253                 return -1;
254         }
255         snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
256         return wpa_ctrl_command(ctrl, buf);
257 }
258 #endif /* CONFIG_IEEE80211W */
259
260
261 #ifdef CONFIG_WPS
262 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
263                                    char *argv[])
264 {
265         char buf[64];
266         if (argc != 2) {
267                 printf("Invalid 'wps_pin' command - exactly two arguments, "
268                        "UUID and PIN, are required.\n");
269                 return -1;
270         }
271         snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
272         return wpa_ctrl_command(ctrl, buf);
273 }
274
275
276 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
277                                    char *argv[])
278 {
279         return wpa_ctrl_command(ctrl, "WPS_PBC");
280 }
281
282
283 #ifdef CONFIG_WPS_OOB
284 static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc,
285                                    char *argv[])
286 {
287         char cmd[256];
288         int res;
289
290         if (argc != 3) {
291                 printf("Invalid WPS_OOB command: need three arguments:\n"
292                        "- OOB_DEV_TYPE: use 'ufd'\n"
293                        "- OOB_PATH: path of OOB device like '/mnt'\n"
294                        "- OOB_METHOD: OOB method 'pin-e' or 'pin-r', "
295                        "'cred'\n");
296                 return -1;
297         }
298
299         res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
300                           argv[0], argv[1], argv[2]);
301         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
302                 printf("Too long WPS_OOB command.\n");
303                 return -1;
304         }
305         return wpa_ctrl_command(ctrl, cmd);
306 }
307 #endif /* CONFIG_WPS_OOB */
308 #endif /* CONFIG_WPS */
309
310
311 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
312                                 char *addr, size_t addr_len)
313 {
314         char buf[4096], *pos;
315         size_t len;
316         int ret;
317
318         if (ctrl_conn == NULL) {
319                 printf("Not connected to hostapd - command dropped.\n");
320                 return -1;
321         }
322         len = sizeof(buf) - 1;
323         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
324                                hostapd_cli_msg_cb);
325         if (ret == -2) {
326                 printf("'%s' command timed out.\n", cmd);
327                 return -2;
328         } else if (ret < 0) {
329                 printf("'%s' command failed.\n", cmd);
330                 return -1;
331         }
332
333         buf[len] = '\0';
334         if (memcmp(buf, "FAIL", 4) == 0)
335                 return -1;
336         printf("%s", buf);
337
338         pos = buf;
339         while (*pos != '\0' && *pos != '\n')
340                 pos++;
341         *pos = '\0';
342         os_strlcpy(addr, buf, addr_len);
343         return 0;
344 }
345
346
347 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
348                                    char *argv[])
349 {
350         char addr[32], cmd[64];
351
352         if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
353                 return 0;
354         do {
355                 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
356         } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
357
358         return -1;
359 }
360
361
362 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
363 {
364         printf("%s", commands_help);
365         return 0;
366 }
367
368
369 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
370                                    char *argv[])
371 {
372         printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
373         return 0;
374 }
375
376
377 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
378 {
379         hostapd_cli_quit = 1;
380         return 0;
381 }
382
383
384 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
385 {
386         char cmd[256];
387         if (argc != 1) {
388                 printf("Invalid LEVEL command: needs one argument (debug "
389                        "level)\n");
390                 return 0;
391         }
392         snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
393         return wpa_ctrl_command(ctrl, cmd);
394 }
395
396
397 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
398 {
399         struct dirent *dent;
400         DIR *dir;
401
402         dir = opendir(ctrl_iface_dir);
403         if (dir == NULL) {
404                 printf("Control interface directory '%s' could not be "
405                        "openned.\n", ctrl_iface_dir);
406                 return;
407         }
408
409         printf("Available interfaces:\n");
410         while ((dent = readdir(dir))) {
411                 if (strcmp(dent->d_name, ".") == 0 ||
412                     strcmp(dent->d_name, "..") == 0)
413                         continue;
414                 printf("%s\n", dent->d_name);
415         }
416         closedir(dir);
417 }
418
419
420 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
421                                      char *argv[])
422 {
423         if (argc < 1) {
424                 hostapd_cli_list_interfaces(ctrl);
425                 return 0;
426         }
427
428         hostapd_cli_close_connection();
429         free(ctrl_ifname);
430         ctrl_ifname = strdup(argv[0]);
431
432         if (hostapd_cli_open_connection(ctrl_ifname)) {
433                 printf("Connected to interface '%s.\n", ctrl_ifname);
434                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
435                         hostapd_cli_attached = 1;
436                 } else {
437                         printf("Warning: Failed to attach to "
438                                "hostapd.\n");
439                 }
440         } else {
441                 printf("Could not connect to interface '%s' - re-trying\n",
442                         ctrl_ifname);
443         }
444         return 0;
445 }
446
447
448 struct hostapd_cli_cmd {
449         const char *cmd;
450         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
451 };
452
453 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
454         { "ping", hostapd_cli_cmd_ping },
455         { "mib", hostapd_cli_cmd_mib },
456         { "sta", hostapd_cli_cmd_sta },
457         { "all_sta", hostapd_cli_cmd_all_sta },
458         { "new_sta", hostapd_cli_cmd_new_sta },
459 #ifdef CONFIG_IEEE80211W
460         { "sa_query", hostapd_cli_cmd_sa_query },
461 #endif /* CONFIG_IEEE80211W */
462 #ifdef CONFIG_WPS
463         { "wps_pin", hostapd_cli_cmd_wps_pin },
464         { "wps_pbc", hostapd_cli_cmd_wps_pbc },
465 #ifdef CONFIG_WPS_OOB
466         { "wps_oob", hostapd_cli_cmd_wps_oob },
467 #endif /* CONFIG_WPS_OOB */
468 #endif /* CONFIG_WPS */
469         { "help", hostapd_cli_cmd_help },
470         { "interface", hostapd_cli_cmd_interface },
471         { "level", hostapd_cli_cmd_level },
472         { "license", hostapd_cli_cmd_license },
473         { "quit", hostapd_cli_cmd_quit },
474         { NULL, NULL }
475 };
476
477
478 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
479 {
480         struct hostapd_cli_cmd *cmd, *match = NULL;
481         int count;
482
483         count = 0;
484         cmd = hostapd_cli_commands;
485         while (cmd->cmd) {
486                 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
487                         match = cmd;
488                         count++;
489                 }
490                 cmd++;
491         }
492
493         if (count > 1) {
494                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
495                 cmd = hostapd_cli_commands;
496                 while (cmd->cmd) {
497                         if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
498                             0) {
499                                 printf(" %s", cmd->cmd);
500                         }
501                         cmd++;
502                 }
503                 printf("\n");
504         } else if (count == 0) {
505                 printf("Unknown command '%s'\n", argv[0]);
506         } else {
507                 match->handler(ctrl, argc - 1, &argv[1]);
508         }
509 }
510
511
512 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read)
513 {
514         int first = 1;
515         if (ctrl_conn == NULL)
516                 return;
517         while (wpa_ctrl_pending(ctrl)) {
518                 char buf[256];
519                 size_t len = sizeof(buf) - 1;
520                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
521                         buf[len] = '\0';
522                         if (in_read && first)
523                                 printf("\n");
524                         first = 0;
525                         printf("%s\n", buf);
526                 } else {
527                         printf("Could not read pending message.\n");
528                         break;
529                 }
530         }
531 }
532
533
534 static void hostapd_cli_interactive(void)
535 {
536         const int max_args = 10;
537         char cmd[256], *res, *argv[max_args], *pos;
538         int argc;
539
540         printf("\nInteractive mode\n\n");
541
542         do {
543                 hostapd_cli_recv_pending(ctrl_conn, 0);
544                 printf("> ");
545                 alarm(ping_interval);
546                 res = fgets(cmd, sizeof(cmd), stdin);
547                 alarm(0);
548                 if (res == NULL)
549                         break;
550                 pos = cmd;
551                 while (*pos != '\0') {
552                         if (*pos == '\n') {
553                                 *pos = '\0';
554                                 break;
555                         }
556                         pos++;
557                 }
558                 argc = 0;
559                 pos = cmd;
560                 for (;;) {
561                         while (*pos == ' ')
562                                 pos++;
563                         if (*pos == '\0')
564                                 break;
565                         argv[argc] = pos;
566                         argc++;
567                         if (argc == max_args)
568                                 break;
569                         while (*pos != '\0' && *pos != ' ')
570                                 pos++;
571                         if (*pos == ' ')
572                                 *pos++ = '\0';
573                 }
574                 if (argc)
575                         wpa_request(ctrl_conn, argc, argv);
576         } while (!hostapd_cli_quit);
577 }
578
579
580 static void hostapd_cli_terminate(int sig)
581 {
582         hostapd_cli_close_connection();
583         exit(0);
584 }
585
586
587 static void hostapd_cli_alarm(int sig)
588 {
589         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
590                 printf("Connection to hostapd lost - trying to reconnect\n");
591                 hostapd_cli_close_connection();
592         }
593         if (!ctrl_conn) {
594                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
595                 if (ctrl_conn) {
596                         printf("Connection to hostapd re-established\n");
597                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
598                                 hostapd_cli_attached = 1;
599                         } else {
600                                 printf("Warning: Failed to attach to "
601                                        "hostapd.\n");
602                         }
603                 }
604         }
605         if (ctrl_conn)
606                 hostapd_cli_recv_pending(ctrl_conn, 1);
607         alarm(ping_interval);
608 }
609
610
611 int main(int argc, char *argv[])
612 {
613         int interactive;
614         int warning_displayed = 0;
615         int c;
616
617         for (;;) {
618                 c = getopt(argc, argv, "hG:i:p:v");
619                 if (c < 0)
620                         break;
621                 switch (c) {
622                 case 'G':
623                         ping_interval = atoi(optarg);
624                         break;
625                 case 'h':
626                         usage();
627                         return 0;
628                 case 'v':
629                         printf("%s\n", hostapd_cli_version);
630                         return 0;
631                 case 'i':
632                         free(ctrl_ifname);
633                         ctrl_ifname = strdup(optarg);
634                         break;
635                 case 'p':
636                         ctrl_iface_dir = optarg;
637                         break;
638                 default:
639                         usage();
640                         return -1;
641                 }
642         }
643
644         interactive = argc == optind;
645
646         if (interactive) {
647                 printf("%s\n\n%s\n\n", hostapd_cli_version,
648                        hostapd_cli_license);
649         }
650
651         for (;;) {
652                 if (ctrl_ifname == NULL) {
653                         struct dirent *dent;
654                         DIR *dir = opendir(ctrl_iface_dir);
655                         if (dir) {
656                                 while ((dent = readdir(dir))) {
657                                         if (strcmp(dent->d_name, ".") == 0 ||
658                                             strcmp(dent->d_name, "..") == 0)
659                                                 continue;
660                                         printf("Selected interface '%s'\n",
661                                                dent->d_name);
662                                         ctrl_ifname = strdup(dent->d_name);
663                                         break;
664                                 }
665                                 closedir(dir);
666                         }
667                 }
668                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
669                 if (ctrl_conn) {
670                         if (warning_displayed)
671                                 printf("Connection established.\n");
672                         break;
673                 }
674
675                 if (!interactive) {
676                         perror("Failed to connect to hostapd - "
677                                "wpa_ctrl_open");
678                         return -1;
679                 }
680
681                 if (!warning_displayed) {
682                         printf("Could not connect to hostapd - re-trying\n");
683                         warning_displayed = 1;
684                 }
685                 sleep(1);
686                 continue;
687         }
688
689         signal(SIGINT, hostapd_cli_terminate);
690         signal(SIGTERM, hostapd_cli_terminate);
691         signal(SIGALRM, hostapd_cli_alarm);
692
693         if (interactive) {
694                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
695                         hostapd_cli_attached = 1;
696                 } else {
697                         printf("Warning: Failed to attach to hostapd.\n");
698                 }
699                 hostapd_cli_interactive();
700         } else
701                 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
702
703         free(ctrl_ifname);
704         hostapd_cli_close_connection();
705         return 0;
706 }