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