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