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