blob: d4d7a3fa9c03dfbc18eeda8fe96ed8ca1c8a284b [file] [log] [blame]
Jouni Malinen6fc68792008-02-27 17:34:43 -08001/*
2 * hostapd - command line interface for hostapd daemon
Jouni Malinen6f78f2f2009-01-06 20:11:15 +02003 * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
Jouni Malinen6fc68792008-02-27 17:34:43 -08004 *
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
23static const char *hostapd_cli_version =
24"hostapd_cli v" VERSION_STR "\n"
Jouni Malinen6f78f2f2009-01-06 20:11:15 +020025"Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> and contributors";
Jouni Malinen6fc68792008-02-27 17:34:43 -080026
27
28static 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
35static 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
80static 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"
Jouni Malinen88b4b422008-12-30 18:04:29 +020086#ifdef CONFIG_IEEE80211W
87" sa_query <addr> send SA Query to a station\n"
88#endif /* CONFIG_IEEE80211W */
Jouni Malinenad08c362008-11-23 19:34:26 +020089#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"
Masashi Honma46bdb832009-02-26 21:57:38 +020092" wps_oob <type> <path> <method> use WPS with out-of-band (UFD)\n"
Jouni Malinenad08c362008-11-23 19:34:26 +020093#endif /* CONFIG_WPS */
Jouni Malinen6fc68792008-02-27 17:34:43 -080094" help show this usage help\n"
95" interface [ifname] show interfaces/select interface\n"
96" level <debug level> change debug level\n"
97" license show full hostapd_cli license\n"
98" quit exit hostapd_cli\n";
99
100static struct wpa_ctrl *ctrl_conn;
101static int hostapd_cli_quit = 0;
102static int hostapd_cli_attached = 0;
103static const char *ctrl_iface_dir = "/var/run/hostapd";
104static char *ctrl_ifname = NULL;
Jouni Malinen1cc84c12009-01-20 21:12:00 +0200105static int ping_interval = 5;
Jouni Malinen6fc68792008-02-27 17:34:43 -0800106
107
108static void usage(void)
109{
110 fprintf(stderr, "%s\n", hostapd_cli_version);
111 fprintf(stderr,
112 "\n"
113 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hv] "
Jouni Malinen1cc84c12009-01-20 21:12:00 +0200114 "[-G<ping interval>] \\\n"
115 " [command..]\n"
Jouni Malinen6fc68792008-02-27 17:34:43 -0800116 "\n"
117 "Options:\n"
118 " -h help (show this usage text)\n"
119 " -v shown version information\n"
120 " -p<path> path to find control sockets (default: "
121 "/var/run/hostapd)\n"
122 " -i<ifname> Interface to listen on (default: first "
123 "interface found in the\n"
124 " socket path)\n\n"
125 "%s",
126 commands_help);
127}
128
129
130static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
131{
132 char *cfile;
133 int flen;
134
135 if (ifname == NULL)
136 return NULL;
137
138 flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
139 cfile = malloc(flen);
140 if (cfile == NULL)
141 return NULL;
142 snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
143
144 ctrl_conn = wpa_ctrl_open(cfile);
145 free(cfile);
146 return ctrl_conn;
147}
148
149
150static void hostapd_cli_close_connection(void)
151{
152 if (ctrl_conn == NULL)
153 return;
154
155 if (hostapd_cli_attached) {
156 wpa_ctrl_detach(ctrl_conn);
157 hostapd_cli_attached = 0;
158 }
159 wpa_ctrl_close(ctrl_conn);
160 ctrl_conn = NULL;
161}
162
163
164static void hostapd_cli_msg_cb(char *msg, size_t len)
165{
166 printf("%s\n", msg);
167}
168
169
170static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
171{
172 char buf[4096];
173 size_t len;
174 int ret;
175
176 if (ctrl_conn == NULL) {
177 printf("Not connected to hostapd - command dropped.\n");
178 return -1;
179 }
180 len = sizeof(buf) - 1;
181 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
182 hostapd_cli_msg_cb);
183 if (ret == -2) {
184 printf("'%s' command timed out.\n", cmd);
185 return -2;
186 } else if (ret < 0) {
187 printf("'%s' command failed.\n", cmd);
188 return -1;
189 }
190 if (print) {
191 buf[len] = '\0';
192 printf("%s", buf);
193 }
194 return 0;
195}
196
197
198static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
199{
200 return _wpa_ctrl_command(ctrl, cmd, 1);
201}
202
203
204static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
205{
206 return wpa_ctrl_command(ctrl, "PING");
207}
208
209
210static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
211{
212 return wpa_ctrl_command(ctrl, "MIB");
213}
214
215
216static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
217{
218 char buf[64];
219 if (argc != 1) {
220 printf("Invalid 'sta' command - exactly one argument, STA "
221 "address, is required.\n");
222 return -1;
223 }
224 snprintf(buf, sizeof(buf), "STA %s", argv[0]);
225 return wpa_ctrl_command(ctrl, buf);
226}
227
228
229static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
230 char *argv[])
231{
232 char buf[64];
233 if (argc != 1) {
234 printf("Invalid 'new_sta' command - exactly one argument, STA "
235 "address, is required.\n");
236 return -1;
237 }
238 snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
239 return wpa_ctrl_command(ctrl, buf);
240}
241
242
Jouni Malinen88b4b422008-12-30 18:04:29 +0200243#ifdef CONFIG_IEEE80211W
244static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
245 char *argv[])
246{
247 char buf[64];
248 if (argc != 1) {
249 printf("Invalid 'sa_query' command - exactly one argument, "
250 "STA address, is required.\n");
251 return -1;
252 }
253 snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
254 return wpa_ctrl_command(ctrl, buf);
255}
256#endif /* CONFIG_IEEE80211W */
257
258
Jouni Malinenad08c362008-11-23 19:34:26 +0200259#ifdef CONFIG_WPS
260static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
261 char *argv[])
262{
263 char buf[64];
264 if (argc != 2) {
265 printf("Invalid 'wps_pin' command - exactly two arguments, "
266 "UUID and PIN, are required.\n");
267 return -1;
268 }
269 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
270 return wpa_ctrl_command(ctrl, buf);
271}
272
273
274static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
275 char *argv[])
276{
277 return wpa_ctrl_command(ctrl, "WPS_PBC");
278}
Masashi Honma46bdb832009-02-26 21:57:38 +0200279
280
281static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc,
282 char *argv[])
283{
284 char cmd[256];
285 int res;
286
287 if (argc != 3) {
288 printf("Invalid WPS_OOB command: need three arguments:\n"
289 "- OOB_DEV_TYPE: use 'ufd'\n"
290 "- OOB_PATH: path of OOB device like '/mnt'\n"
291 "- OOB_METHOD: OOB method 'pin-e' or 'pin-r', "
292 "'cred'\n");
293 return -1;
294 }
295
296 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
297 argv[0], argv[1], argv[2]);
298 if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
299 printf("Too long WPS_OOB command.\n");
300 return -1;
301 }
302 return wpa_ctrl_command(ctrl, cmd);
303}
Jouni Malinenad08c362008-11-23 19:34:26 +0200304#endif /* CONFIG_WPS */
305
306
Jouni Malinen6fc68792008-02-27 17:34:43 -0800307static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
308 char *addr, size_t addr_len)
309{
310 char buf[4096], *pos;
311 size_t len;
312 int ret;
313
314 if (ctrl_conn == NULL) {
315 printf("Not connected to hostapd - command dropped.\n");
316 return -1;
317 }
318 len = sizeof(buf) - 1;
319 ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
320 hostapd_cli_msg_cb);
321 if (ret == -2) {
322 printf("'%s' command timed out.\n", cmd);
323 return -2;
324 } else if (ret < 0) {
325 printf("'%s' command failed.\n", cmd);
326 return -1;
327 }
328
329 buf[len] = '\0';
330 if (memcmp(buf, "FAIL", 4) == 0)
331 return -1;
332 printf("%s", buf);
333
334 pos = buf;
335 while (*pos != '\0' && *pos != '\n')
336 pos++;
337 *pos = '\0';
338 os_strlcpy(addr, buf, addr_len);
339 return 0;
340}
341
342
343static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
344 char *argv[])
345{
346 char addr[32], cmd[64];
347
348 if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
349 return 0;
350 do {
351 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
352 } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
353
354 return -1;
355}
356
357
358static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
359{
360 printf("%s", commands_help);
361 return 0;
362}
363
364
365static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
366 char *argv[])
367{
368 printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
369 return 0;
370}
371
372
373static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
374{
375 hostapd_cli_quit = 1;
376 return 0;
377}
378
379
380static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
381{
382 char cmd[256];
383 if (argc != 1) {
384 printf("Invalid LEVEL command: needs one argument (debug "
385 "level)\n");
386 return 0;
387 }
388 snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
389 return wpa_ctrl_command(ctrl, cmd);
390}
391
392
393static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
394{
395 struct dirent *dent;
396 DIR *dir;
397
398 dir = opendir(ctrl_iface_dir);
399 if (dir == NULL) {
400 printf("Control interface directory '%s' could not be "
401 "openned.\n", ctrl_iface_dir);
402 return;
403 }
404
405 printf("Available interfaces:\n");
406 while ((dent = readdir(dir))) {
407 if (strcmp(dent->d_name, ".") == 0 ||
408 strcmp(dent->d_name, "..") == 0)
409 continue;
410 printf("%s\n", dent->d_name);
411 }
412 closedir(dir);
413}
414
415
416static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
417 char *argv[])
418{
419 if (argc < 1) {
420 hostapd_cli_list_interfaces(ctrl);
421 return 0;
422 }
423
424 hostapd_cli_close_connection();
425 free(ctrl_ifname);
426 ctrl_ifname = strdup(argv[0]);
427
428 if (hostapd_cli_open_connection(ctrl_ifname)) {
429 printf("Connected to interface '%s.\n", ctrl_ifname);
430 if (wpa_ctrl_attach(ctrl_conn) == 0) {
431 hostapd_cli_attached = 1;
432 } else {
433 printf("Warning: Failed to attach to "
434 "hostapd.\n");
435 }
436 } else {
437 printf("Could not connect to interface '%s' - re-trying\n",
438 ctrl_ifname);
439 }
440 return 0;
441}
442
443
444struct hostapd_cli_cmd {
445 const char *cmd;
446 int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
447};
448
449static struct hostapd_cli_cmd hostapd_cli_commands[] = {
450 { "ping", hostapd_cli_cmd_ping },
451 { "mib", hostapd_cli_cmd_mib },
452 { "sta", hostapd_cli_cmd_sta },
453 { "all_sta", hostapd_cli_cmd_all_sta },
454 { "new_sta", hostapd_cli_cmd_new_sta },
Jouni Malinen88b4b422008-12-30 18:04:29 +0200455#ifdef CONFIG_IEEE80211W
456 { "sa_query", hostapd_cli_cmd_sa_query },
457#endif /* CONFIG_IEEE80211W */
Jouni Malinenad08c362008-11-23 19:34:26 +0200458#ifdef CONFIG_WPS
459 { "wps_pin", hostapd_cli_cmd_wps_pin },
460 { "wps_pbc", hostapd_cli_cmd_wps_pbc },
Masashi Honma46bdb832009-02-26 21:57:38 +0200461 { "wps_oob", hostapd_cli_cmd_wps_oob },
Jouni Malinenad08c362008-11-23 19:34:26 +0200462#endif /* CONFIG_WPS */
Jouni Malinen6fc68792008-02-27 17:34:43 -0800463 { "help", hostapd_cli_cmd_help },
464 { "interface", hostapd_cli_cmd_interface },
465 { "level", hostapd_cli_cmd_level },
466 { "license", hostapd_cli_cmd_license },
467 { "quit", hostapd_cli_cmd_quit },
468 { NULL, NULL }
469};
470
471
472static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
473{
474 struct hostapd_cli_cmd *cmd, *match = NULL;
475 int count;
476
477 count = 0;
478 cmd = hostapd_cli_commands;
479 while (cmd->cmd) {
480 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
481 match = cmd;
482 count++;
483 }
484 cmd++;
485 }
486
487 if (count > 1) {
488 printf("Ambiguous command '%s'; possible commands:", argv[0]);
489 cmd = hostapd_cli_commands;
490 while (cmd->cmd) {
491 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
492 0) {
493 printf(" %s", cmd->cmd);
494 }
495 cmd++;
496 }
497 printf("\n");
498 } else if (count == 0) {
499 printf("Unknown command '%s'\n", argv[0]);
500 } else {
501 match->handler(ctrl, argc - 1, &argv[1]);
502 }
503}
504
505
506static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read)
507{
508 int first = 1;
509 if (ctrl_conn == NULL)
510 return;
511 while (wpa_ctrl_pending(ctrl)) {
512 char buf[256];
513 size_t len = sizeof(buf) - 1;
514 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
515 buf[len] = '\0';
516 if (in_read && first)
517 printf("\n");
518 first = 0;
519 printf("%s\n", buf);
520 } else {
521 printf("Could not read pending message.\n");
522 break;
523 }
524 }
525}
526
527
528static void hostapd_cli_interactive(void)
529{
530 const int max_args = 10;
531 char cmd[256], *res, *argv[max_args], *pos;
532 int argc;
533
534 printf("\nInteractive mode\n\n");
535
536 do {
537 hostapd_cli_recv_pending(ctrl_conn, 0);
538 printf("> ");
Jouni Malinen1cc84c12009-01-20 21:12:00 +0200539 alarm(ping_interval);
Jouni Malinen6fc68792008-02-27 17:34:43 -0800540 res = fgets(cmd, sizeof(cmd), stdin);
541 alarm(0);
542 if (res == NULL)
543 break;
544 pos = cmd;
545 while (*pos != '\0') {
546 if (*pos == '\n') {
547 *pos = '\0';
548 break;
549 }
550 pos++;
551 }
552 argc = 0;
553 pos = cmd;
554 for (;;) {
555 while (*pos == ' ')
556 pos++;
557 if (*pos == '\0')
558 break;
559 argv[argc] = pos;
560 argc++;
561 if (argc == max_args)
562 break;
563 while (*pos != '\0' && *pos != ' ')
564 pos++;
565 if (*pos == ' ')
566 *pos++ = '\0';
567 }
568 if (argc)
569 wpa_request(ctrl_conn, argc, argv);
570 } while (!hostapd_cli_quit);
571}
572
573
574static void hostapd_cli_terminate(int sig)
575{
576 hostapd_cli_close_connection();
577 exit(0);
578}
579
580
581static void hostapd_cli_alarm(int sig)
582{
583 if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
584 printf("Connection to hostapd lost - trying to reconnect\n");
585 hostapd_cli_close_connection();
586 }
587 if (!ctrl_conn) {
588 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
589 if (ctrl_conn) {
590 printf("Connection to hostapd re-established\n");
591 if (wpa_ctrl_attach(ctrl_conn) == 0) {
592 hostapd_cli_attached = 1;
593 } else {
594 printf("Warning: Failed to attach to "
595 "hostapd.\n");
596 }
597 }
598 }
599 if (ctrl_conn)
600 hostapd_cli_recv_pending(ctrl_conn, 1);
Jouni Malinen1cc84c12009-01-20 21:12:00 +0200601 alarm(ping_interval);
Jouni Malinen6fc68792008-02-27 17:34:43 -0800602}
603
604
605int main(int argc, char *argv[])
606{
607 int interactive;
608 int warning_displayed = 0;
609 int c;
610
611 for (;;) {
Jouni Malinen1cc84c12009-01-20 21:12:00 +0200612 c = getopt(argc, argv, "hG:i:p:v");
Jouni Malinen6fc68792008-02-27 17:34:43 -0800613 if (c < 0)
614 break;
615 switch (c) {
Jouni Malinen1cc84c12009-01-20 21:12:00 +0200616 case 'G':
617 ping_interval = atoi(optarg);
618 break;
Jouni Malinen6fc68792008-02-27 17:34:43 -0800619 case 'h':
620 usage();
621 return 0;
622 case 'v':
623 printf("%s\n", hostapd_cli_version);
624 return 0;
625 case 'i':
626 free(ctrl_ifname);
627 ctrl_ifname = strdup(optarg);
628 break;
629 case 'p':
630 ctrl_iface_dir = optarg;
631 break;
632 default:
633 usage();
634 return -1;
635 }
636 }
637
638 interactive = argc == optind;
639
640 if (interactive) {
641 printf("%s\n\n%s\n\n", hostapd_cli_version,
642 hostapd_cli_license);
643 }
644
645 for (;;) {
646 if (ctrl_ifname == NULL) {
647 struct dirent *dent;
648 DIR *dir = opendir(ctrl_iface_dir);
649 if (dir) {
650 while ((dent = readdir(dir))) {
651 if (strcmp(dent->d_name, ".") == 0 ||
652 strcmp(dent->d_name, "..") == 0)
653 continue;
654 printf("Selected interface '%s'\n",
655 dent->d_name);
656 ctrl_ifname = strdup(dent->d_name);
657 break;
658 }
659 closedir(dir);
660 }
661 }
662 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
663 if (ctrl_conn) {
664 if (warning_displayed)
665 printf("Connection established.\n");
666 break;
667 }
668
669 if (!interactive) {
670 perror("Failed to connect to hostapd - "
671 "wpa_ctrl_open");
672 return -1;
673 }
674
675 if (!warning_displayed) {
676 printf("Could not connect to hostapd - re-trying\n");
677 warning_displayed = 1;
678 }
679 sleep(1);
680 continue;
681 }
682
683 signal(SIGINT, hostapd_cli_terminate);
684 signal(SIGTERM, hostapd_cli_terminate);
685 signal(SIGALRM, hostapd_cli_alarm);
686
687 if (interactive) {
688 if (wpa_ctrl_attach(ctrl_conn) == 0) {
689 hostapd_cli_attached = 1;
690 } else {
691 printf("Warning: Failed to attach to hostapd.\n");
692 }
693 hostapd_cli_interactive();
694 } else
695 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
696
697 free(ctrl_ifname);
698 hostapd_cli_close_connection();
699 return 0;
700}