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