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