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