1e4125fb9b9fa646c1e2c3583ccf606ab57e66f7
[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_get_interfaces(struct wpa_ctrl *ctrl,
966                                        struct dl_list *interfaces)
967 {
968         struct dirent *dent;
969         DIR *dir;
970
971         if (!ctrl || !interfaces)
972                 return;
973         dir = opendir(ctrl_iface_dir);
974         if (dir == NULL)
975                 return;
976
977         while ((dent = readdir(dir))) {
978                 if (strcmp(dent->d_name, ".") == 0 ||
979                     strcmp(dent->d_name, "..") == 0)
980                         continue;
981                 cli_txt_list_add(interfaces, dent->d_name);
982         }
983         closedir(dir);
984 }
985
986
987 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
988 {
989         struct dirent *dent;
990         DIR *dir;
991
992         dir = opendir(ctrl_iface_dir);
993         if (dir == NULL) {
994                 printf("Control interface directory '%s' could not be "
995                        "openned.\n", ctrl_iface_dir);
996                 return;
997         }
998
999         printf("Available interfaces:\n");
1000         while ((dent = readdir(dir))) {
1001                 if (strcmp(dent->d_name, ".") == 0 ||
1002                     strcmp(dent->d_name, "..") == 0)
1003                         continue;
1004                 printf("%s\n", dent->d_name);
1005         }
1006         closedir(dir);
1007 }
1008
1009
1010 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
1011                                      char *argv[])
1012 {
1013         if (argc < 1) {
1014                 hostapd_cli_list_interfaces(ctrl);
1015                 return 0;
1016         }
1017
1018         hostapd_cli_close_connection();
1019         os_free(ctrl_ifname);
1020         ctrl_ifname = os_strdup(argv[0]);
1021         if (ctrl_ifname == NULL)
1022                 return -1;
1023
1024         if (hostapd_cli_open_connection(ctrl_ifname)) {
1025                 printf("Connected to interface '%s.\n", ctrl_ifname);
1026                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1027                         hostapd_cli_attached = 1;
1028                         register_event_handler(ctrl_conn);
1029                 } else {
1030                         printf("Warning: Failed to attach to "
1031                                "hostapd.\n");
1032                 }
1033         } else {
1034                 printf("Could not connect to interface '%s' - re-trying\n",
1035                         ctrl_ifname);
1036         }
1037         return 0;
1038 }
1039
1040
1041 static char ** hostapd_complete_interface(const char *str, int pos)
1042 {
1043         int arg = get_cmd_arg_num(str, pos);
1044         char **res = NULL;
1045         DEFINE_DL_LIST(interfaces);
1046
1047         switch (arg) {
1048         case 1:
1049                 hostapd_cli_get_interfaces(ctrl_conn, &interfaces);
1050                 res = cli_txt_list_array(&interfaces);
1051                 cli_txt_list_flush(&interfaces);
1052                 break;
1053         }
1054
1055         return res;
1056 }
1057
1058
1059 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
1060 {
1061         char cmd[256];
1062         int res;
1063
1064         if (argc != 2) {
1065                 printf("Invalid SET command: needs two arguments (variable "
1066                        "name and value)\n");
1067                 return -1;
1068         }
1069
1070         res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
1071         if (os_snprintf_error(sizeof(cmd), res)) {
1072                 printf("Too long SET command.\n");
1073                 return -1;
1074         }
1075         return wpa_ctrl_command(ctrl, cmd);
1076 }
1077
1078
1079 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
1080 {
1081         char cmd[256];
1082         int res;
1083
1084         if (argc != 1) {
1085                 printf("Invalid GET command: needs one argument (variable "
1086                        "name)\n");
1087                 return -1;
1088         }
1089
1090         res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
1091         if (os_snprintf_error(sizeof(cmd), res)) {
1092                 printf("Too long GET command.\n");
1093                 return -1;
1094         }
1095         return wpa_ctrl_command(ctrl, cmd);
1096 }
1097
1098
1099 #ifdef CONFIG_FST
1100 static int hostapd_cli_cmd_fst(struct wpa_ctrl *ctrl, int argc, char *argv[])
1101 {
1102         char cmd[256];
1103         int res;
1104         int i;
1105         int total;
1106
1107         if (argc <= 0) {
1108                 printf("FST command: parameters are required.\n");
1109                 return -1;
1110         }
1111
1112         total = os_snprintf(cmd, sizeof(cmd), "FST-MANAGER");
1113
1114         for (i = 0; i < argc; i++) {
1115                 res = os_snprintf(cmd + total, sizeof(cmd) - total, " %s",
1116                                   argv[i]);
1117                 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1118                         printf("Too long fst command.\n");
1119                         return -1;
1120                 }
1121                 total += res;
1122         }
1123         return wpa_ctrl_command(ctrl, cmd);
1124 }
1125 #endif /* CONFIG_FST */
1126
1127
1128 static int hostapd_cli_cmd_chan_switch(struct wpa_ctrl *ctrl,
1129                                        int argc, char *argv[])
1130 {
1131         char cmd[256];
1132         int res;
1133         int i;
1134         char *tmp;
1135         int total;
1136
1137         if (argc < 2) {
1138                 printf("Invalid chan_switch command: needs at least two "
1139                        "arguments (count and freq)\n"
1140                        "usage: <cs_count> <freq> [sec_channel_offset=] "
1141                        "[center_freq1=] [center_freq2=] [bandwidth=] "
1142                        "[blocktx] [ht|vht]\n");
1143                 return -1;
1144         }
1145
1146         res = os_snprintf(cmd, sizeof(cmd), "CHAN_SWITCH %s %s",
1147                           argv[0], argv[1]);
1148         if (os_snprintf_error(sizeof(cmd), res)) {
1149                 printf("Too long CHAN_SWITCH command.\n");
1150                 return -1;
1151         }
1152
1153         total = res;
1154         for (i = 2; i < argc; i++) {
1155                 tmp = cmd + total;
1156                 res = os_snprintf(tmp, sizeof(cmd) - total, " %s", argv[i]);
1157                 if (os_snprintf_error(sizeof(cmd) - total, res)) {
1158                         printf("Too long CHAN_SWITCH command.\n");
1159                         return -1;
1160                 }
1161                 total += res;
1162         }
1163         return wpa_ctrl_command(ctrl, cmd);
1164 }
1165
1166
1167 static int hostapd_cli_cmd_enable(struct wpa_ctrl *ctrl, int argc,
1168                                       char *argv[])
1169 {
1170         return wpa_ctrl_command(ctrl, "ENABLE");
1171 }
1172
1173
1174 static int hostapd_cli_cmd_reload(struct wpa_ctrl *ctrl, int argc,
1175                                       char *argv[])
1176 {
1177         return wpa_ctrl_command(ctrl, "RELOAD");
1178 }
1179
1180
1181 static int hostapd_cli_cmd_disable(struct wpa_ctrl *ctrl, int argc,
1182                                       char *argv[])
1183 {
1184         return wpa_ctrl_command(ctrl, "DISABLE");
1185 }
1186
1187
1188 static int hostapd_cli_cmd_vendor(struct wpa_ctrl *ctrl, int argc, char *argv[])
1189 {
1190         char cmd[256];
1191         int res;
1192
1193         if (argc < 2 || argc > 3) {
1194                 printf("Invalid vendor command\n"
1195                        "usage: <vendor id> <command id> [<hex formatted command argument>]\n");
1196                 return -1;
1197         }
1198
1199         res = os_snprintf(cmd, sizeof(cmd), "VENDOR %s %s %s", argv[0], argv[1],
1200                           argc == 3 ? argv[2] : "");
1201         if (os_snprintf_error(sizeof(cmd), res)) {
1202                 printf("Too long VENDOR command.\n");
1203                 return -1;
1204         }
1205         return wpa_ctrl_command(ctrl, cmd);
1206 }
1207
1208
1209 static int hostapd_cli_cmd_erp_flush(struct wpa_ctrl *ctrl, int argc,
1210                                      char *argv[])
1211 {
1212         return wpa_ctrl_command(ctrl, "ERP_FLUSH");
1213 }
1214
1215
1216 static int hostapd_cli_cmd_log_level(struct wpa_ctrl *ctrl, int argc,
1217                                      char *argv[])
1218 {
1219         char cmd[256];
1220         int res;
1221
1222         res = os_snprintf(cmd, sizeof(cmd), "LOG_LEVEL%s%s%s%s",
1223                           argc >= 1 ? " " : "",
1224                           argc >= 1 ? argv[0] : "",
1225                           argc == 2 ? " " : "",
1226                           argc == 2 ? argv[1] : "");
1227         if (os_snprintf_error(sizeof(cmd), res)) {
1228                 printf("Too long option\n");
1229                 return -1;
1230         }
1231         return wpa_ctrl_command(ctrl, cmd);
1232 }
1233
1234
1235 static int hostapd_cli_cmd_raw(struct wpa_ctrl *ctrl, int argc, char *argv[])
1236 {
1237         if (argc == 0)
1238                 return -1;
1239         return hostapd_cli_cmd(ctrl, argv[0], 0, argc - 1, &argv[1]);
1240 }
1241
1242
1243 static int hostapd_cli_cmd_pmksa(struct wpa_ctrl *ctrl, int argc, char *argv[])
1244 {
1245         return wpa_ctrl_command(ctrl, "PMKSA");
1246 }
1247
1248
1249 static int hostapd_cli_cmd_pmksa_flush(struct wpa_ctrl *ctrl, int argc,
1250                                        char *argv[])
1251 {
1252         return wpa_ctrl_command(ctrl, "PMKSA_FLUSH");
1253 }
1254
1255
1256 static int hostapd_cli_cmd_set_neighbor(struct wpa_ctrl *ctrl, int argc,
1257                                         char *argv[])
1258 {
1259         char cmd[2048];
1260         int res;
1261
1262         if (argc < 3 || argc > 5) {
1263                 printf("Invalid set_neighbor command: needs 3-5 arguments\n");
1264                 return -1;
1265         }
1266
1267         res = os_snprintf(cmd, sizeof(cmd), "SET_NEIGHBOR %s %s %s %s %s",
1268                           argv[0], argv[1], argv[2], argc >= 4 ? argv[3] : "",
1269                           argc == 5 ? argv[4] : "");
1270         if (os_snprintf_error(sizeof(cmd), res)) {
1271                 printf("Too long SET_NEIGHBOR command.\n");
1272                 return -1;
1273         }
1274         return wpa_ctrl_command(ctrl, cmd);
1275 }
1276
1277
1278 static int hostapd_cli_cmd_remove_neighbor(struct wpa_ctrl *ctrl, int argc,
1279                                            char *argv[])
1280 {
1281         char cmd[400];
1282         int res;
1283
1284         if (argc != 2) {
1285                 printf("Invalid remove_neighbor command: needs 2 arguments\n");
1286                 return -1;
1287         }
1288
1289         res = os_snprintf(cmd, sizeof(cmd), "REMOVE_NEIGHBOR %s %s",
1290                           argv[0], argv[1]);
1291         if (os_snprintf_error(sizeof(cmd), res)) {
1292                 printf("Too long REMOVE_NEIGHBOR command.\n");
1293                 return -1;
1294         }
1295         return wpa_ctrl_command(ctrl, cmd);
1296 }
1297
1298
1299 static int hostapd_cli_cmd_req_lci(struct wpa_ctrl *ctrl, int argc,
1300                                    char *argv[])
1301 {
1302         char cmd[256];
1303         int res;
1304
1305         if (argc != 1) {
1306                 printf("Invalid req_lci command - requires destination address\n");
1307                 return -1;
1308         }
1309
1310         res = os_snprintf(cmd, sizeof(cmd), "REQ_LCI %s", argv[0]);
1311         if (os_snprintf_error(sizeof(cmd), res)) {
1312                 printf("Too long REQ_LCI command.\n");
1313                 return -1;
1314         }
1315         return wpa_ctrl_command(ctrl, cmd);
1316 }
1317
1318
1319 static int hostapd_cli_cmd_req_range(struct wpa_ctrl *ctrl, int argc,
1320                                      char *argv[])
1321 {
1322         if (argc < 4) {
1323                 printf("Invalid req_range command: needs at least 4 arguments - dest address, randomization interval, min AP count, and 1 to 16 AP addresses\n");
1324                 return -1;
1325         }
1326
1327         return hostapd_cli_cmd(ctrl, "REQ_RANGE", 4, argc, argv);
1328 }
1329
1330
1331 static int hostapd_cli_cmd_driver_flags(struct wpa_ctrl *ctrl, int argc,
1332                                         char *argv[])
1333 {
1334         return wpa_ctrl_command(ctrl, "DRIVER_FLAGS");
1335 }
1336
1337
1338 struct hostapd_cli_cmd {
1339         const char *cmd;
1340         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
1341         char ** (*completion)(const char *str, int pos);
1342         const char *usage;
1343 };
1344
1345 static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
1346         { "ping", hostapd_cli_cmd_ping, NULL,
1347           "= pings hostapd" },
1348         { "mib", hostapd_cli_cmd_mib, NULL,
1349           "= get MIB variables (dot1x, dot11, radius)" },
1350         { "relog", hostapd_cli_cmd_relog, NULL, NULL },
1351         { "status", hostapd_cli_cmd_status, NULL, NULL },
1352         { "sta", hostapd_cli_cmd_sta, NULL,
1353           "<addr> = get MIB variables for one station" },
1354         { "all_sta", hostapd_cli_cmd_all_sta, NULL,
1355            "= get MIB variables for all stations" },
1356         { "new_sta", hostapd_cli_cmd_new_sta, NULL,
1357           "<addr> = add a new station" },
1358         { "deauthenticate", hostapd_cli_cmd_deauthenticate,
1359           hostapd_complete_deauthenticate,
1360           "<addr> = deauthenticate a station" },
1361         { "disassociate", hostapd_cli_cmd_disassociate,
1362           hostapd_complete_disassociate,
1363           "<addr> = disassociate a station" },
1364 #ifdef CONFIG_IEEE80211W
1365         { "sa_query", hostapd_cli_cmd_sa_query, NULL,
1366           "<addr> = send SA Query to a station" },
1367 #endif /* CONFIG_IEEE80211W */
1368 #ifdef CONFIG_WPS
1369         { "wps_pin", hostapd_cli_cmd_wps_pin, NULL,
1370           "<uuid> <pin> [timeout] [addr] = add WPS Enrollee PIN" },
1371         { "wps_check_pin", hostapd_cli_cmd_wps_check_pin, NULL,
1372           "<PIN> = verify PIN checksum" },
1373         { "wps_pbc", hostapd_cli_cmd_wps_pbc, NULL,
1374           "= indicate button pushed to initiate PBC" },
1375         { "wps_cancel", hostapd_cli_cmd_wps_cancel, NULL,
1376           "= cancel the pending WPS operation" },
1377 #ifdef CONFIG_WPS_NFC
1378         { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read, NULL,
1379           "<hexdump> = report read NFC tag with WPS data" },
1380         { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token, NULL,
1381           "<WPS/NDEF> = build NFC configuration token" },
1382         { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token, NULL,
1383           "<WPS/NDEF/enable/disable> = manager NFC password token" },
1384         { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel, NULL,
1385           NULL },
1386 #endif /* CONFIG_WPS_NFC */
1387         { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin, NULL,
1388           "<cmd> [params..] = enable/disable AP PIN" },
1389         { "wps_config", hostapd_cli_cmd_wps_config, NULL,
1390           "<SSID> <auth> <encr> <key> = configure AP" },
1391         { "wps_get_status", hostapd_cli_cmd_wps_get_status, NULL,
1392           "= show current WPS status" },
1393 #endif /* CONFIG_WPS */
1394         { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent, NULL, NULL },
1395         { "ess_disassoc", hostapd_cli_cmd_ess_disassoc, NULL, NULL },
1396         { "bss_tm_req", hostapd_cli_cmd_bss_tm_req, NULL, NULL },
1397         { "get_config", hostapd_cli_cmd_get_config, NULL,
1398           "= show current configuration" },
1399         { "help", hostapd_cli_cmd_help, hostapd_cli_complete_help,
1400           "= show this usage help" },
1401         { "interface", hostapd_cli_cmd_interface, hostapd_complete_interface,
1402           "[ifname] = show interfaces/select interface" },
1403 #ifdef CONFIG_FST
1404         { "fst", hostapd_cli_cmd_fst, NULL, NULL },
1405 #endif /* CONFIG_FST */
1406         { "raw", hostapd_cli_cmd_raw, NULL, NULL },
1407         { "level", hostapd_cli_cmd_level, NULL,
1408           "<debug level> = change debug level" },
1409         { "license", hostapd_cli_cmd_license, NULL,
1410           "= show full hostapd_cli license" },
1411         { "quit", hostapd_cli_cmd_quit, NULL,
1412           "= exit hostapd_cli" },
1413         { "set", hostapd_cli_cmd_set, NULL, NULL },
1414         { "get", hostapd_cli_cmd_get, NULL, NULL },
1415         { "set_qos_map_set", hostapd_cli_cmd_set_qos_map_set, NULL, NULL },
1416         { "send_qos_map_conf", hostapd_cli_cmd_send_qos_map_conf, NULL, NULL },
1417         { "chan_switch", hostapd_cli_cmd_chan_switch, NULL, NULL },
1418         { "hs20_wnm_notif", hostapd_cli_cmd_hs20_wnm_notif, NULL, NULL },
1419         { "hs20_deauth_req", hostapd_cli_cmd_hs20_deauth_req, NULL, NULL },
1420         { "vendor", hostapd_cli_cmd_vendor, NULL, NULL },
1421         { "enable", hostapd_cli_cmd_enable, NULL, NULL },
1422         { "reload", hostapd_cli_cmd_reload, NULL, NULL },
1423         { "disable", hostapd_cli_cmd_disable, NULL, NULL },
1424         { "erp_flush", hostapd_cli_cmd_erp_flush, NULL, NULL },
1425         { "log_level", hostapd_cli_cmd_log_level, NULL, NULL },
1426         { "pmksa", hostapd_cli_cmd_pmksa, NULL, NULL },
1427         { "pmksa_flush", hostapd_cli_cmd_pmksa_flush, NULL, NULL },
1428         { "set_neighbor", hostapd_cli_cmd_set_neighbor, NULL, NULL },
1429         { "remove_neighbor", hostapd_cli_cmd_remove_neighbor, NULL, NULL },
1430         { "req_lci", hostapd_cli_cmd_req_lci, NULL, NULL },
1431         { "req_range", hostapd_cli_cmd_req_range, NULL, NULL },
1432         { "driver_flags", hostapd_cli_cmd_driver_flags, NULL, NULL },
1433         { NULL, NULL, NULL, NULL }
1434 };
1435
1436
1437 /*
1438  * Prints command usage, lines are padded with the specified string.
1439  */
1440 static void print_cmd_help(FILE *stream, const struct hostapd_cli_cmd *cmd,
1441                            const char *pad)
1442 {
1443         char c;
1444         size_t n;
1445
1446         if (cmd->usage == NULL)
1447                 return;
1448         fprintf(stream, "%s%s ", pad, cmd->cmd);
1449         for (n = 0; (c = cmd->usage[n]); n++) {
1450                 fprintf(stream, "%c", c);
1451                 if (c == '\n')
1452                         fprintf(stream, "%s", pad);
1453         }
1454         fprintf(stream, "\n");
1455 }
1456
1457
1458 static void print_help(FILE *stream, const char *cmd)
1459 {
1460         int n;
1461
1462         fprintf(stream, "commands:\n");
1463         for (n = 0; hostapd_cli_commands[n].cmd; n++) {
1464                 if (cmd == NULL || str_starts(hostapd_cli_commands[n].cmd, cmd))
1465                         print_cmd_help(stream, &hostapd_cli_commands[n], "  ");
1466         }
1467 }
1468
1469
1470 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
1471 {
1472         const struct hostapd_cli_cmd *cmd, *match = NULL;
1473         int count;
1474
1475         count = 0;
1476         cmd = hostapd_cli_commands;
1477         while (cmd->cmd) {
1478                 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
1479                         match = cmd;
1480                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
1481                                 /* we have an exact match */
1482                                 count = 1;
1483                                 break;
1484                         }
1485                         count++;
1486                 }
1487                 cmd++;
1488         }
1489
1490         if (count > 1) {
1491                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
1492                 cmd = hostapd_cli_commands;
1493                 while (cmd->cmd) {
1494                         if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
1495                             0) {
1496                                 printf(" %s", cmd->cmd);
1497                         }
1498                         cmd++;
1499                 }
1500                 printf("\n");
1501         } else if (count == 0) {
1502                 printf("Unknown command '%s'\n", argv[0]);
1503         } else {
1504                 match->handler(ctrl, argc - 1, &argv[1]);
1505         }
1506 }
1507
1508
1509 static void cli_event(const char *str)
1510 {
1511         const char *start, *s;
1512
1513         start = os_strchr(str, '>');
1514         if (start == NULL)
1515                 return;
1516
1517         start++;
1518
1519         if (str_starts(start, AP_STA_CONNECTED)) {
1520                 s = os_strchr(start, ' ');
1521                 if (s == NULL)
1522                         return;
1523                 cli_txt_list_add(&stations, s + 1);
1524                 return;
1525         }
1526
1527         if (str_starts(start, AP_STA_DISCONNECTED)) {
1528                 s = os_strchr(start, ' ');
1529                 if (s == NULL)
1530                         return;
1531                 cli_txt_list_del_addr(&stations, s + 1);
1532                 return;
1533         }
1534 }
1535
1536
1537 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
1538                                      int action_monitor)
1539 {
1540         int first = 1;
1541         if (ctrl_conn == NULL)
1542                 return;
1543         while (wpa_ctrl_pending(ctrl)) {
1544                 char buf[256];
1545                 size_t len = sizeof(buf) - 1;
1546                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
1547                         buf[len] = '\0';
1548                         if (action_monitor)
1549                                 hostapd_cli_action_process(buf, len);
1550                         else {
1551                                 cli_event(buf);
1552                                 if (in_read && first)
1553                                         printf("\n");
1554                                 first = 0;
1555                                 printf("%s\n", buf);
1556                         }
1557                 } else {
1558                         printf("Could not read pending message.\n");
1559                         break;
1560                 }
1561         }
1562 }
1563
1564
1565 static void hostapd_cli_receive(int sock, void *eloop_ctx, void *sock_ctx)
1566 {
1567         hostapd_cli_recv_pending(ctrl_conn, 0, 0);
1568 }
1569
1570
1571 #define max_args 10
1572
1573 static int tokenize_cmd(char *cmd, char *argv[])
1574 {
1575         char *pos;
1576         int argc = 0;
1577
1578         pos = cmd;
1579         for (;;) {
1580                 while (*pos == ' ')
1581                         pos++;
1582                 if (*pos == '\0')
1583                         break;
1584                 argv[argc] = pos;
1585                 argc++;
1586                 if (argc == max_args)
1587                         break;
1588                 if (*pos == '"') {
1589                         char *pos2 = os_strrchr(pos, '"');
1590                         if (pos2)
1591                                 pos = pos2 + 1;
1592                 }
1593                 while (*pos != '\0' && *pos != ' ')
1594                         pos++;
1595                 if (*pos == ' ')
1596                         *pos++ = '\0';
1597         }
1598
1599         return argc;
1600 }
1601
1602
1603 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
1604 {
1605         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
1606                 printf("Connection to hostapd lost - trying to reconnect\n");
1607                 hostapd_cli_close_connection();
1608         }
1609         if (!ctrl_conn) {
1610                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1611                 if (ctrl_conn) {
1612                         printf("Connection to hostapd re-established\n");
1613                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
1614                                 hostapd_cli_attached = 1;
1615                                 register_event_handler(ctrl_conn);
1616                         } else {
1617                                 printf("Warning: Failed to attach to "
1618                                        "hostapd.\n");
1619                         }
1620                 }
1621         }
1622         if (ctrl_conn)
1623                 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
1624         eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1625 }
1626
1627
1628 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
1629 {
1630         eloop_terminate();
1631 }
1632
1633
1634 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
1635 {
1636         char *argv[max_args];
1637         int argc;
1638         argc = tokenize_cmd(cmd, argv);
1639         if (argc)
1640                 wpa_request(ctrl_conn, argc, argv);
1641 }
1642
1643
1644 static void hostapd_cli_edit_eof_cb(void *ctx)
1645 {
1646         eloop_terminate();
1647 }
1648
1649
1650 static char ** list_cmd_list(void)
1651 {
1652         char **res;
1653         int i, count;
1654
1655         count = ARRAY_SIZE(hostapd_cli_commands);
1656         res = os_calloc(count + 1, sizeof(char *));
1657         if (res == NULL)
1658                 return NULL;
1659
1660         for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1661                 res[i] = os_strdup(hostapd_cli_commands[i].cmd);
1662                 if (res[i] == NULL)
1663                         break;
1664         }
1665
1666         return res;
1667 }
1668
1669
1670 static char ** hostapd_cli_cmd_completion(const char *cmd, const char *str,
1671                                       int pos)
1672 {
1673         int i;
1674
1675         for (i = 0; hostapd_cli_commands[i].cmd; i++) {
1676                 if (os_strcasecmp(hostapd_cli_commands[i].cmd, cmd) != 0)
1677                         continue;
1678                 if (hostapd_cli_commands[i].completion)
1679                         return hostapd_cli_commands[i].completion(str, pos);
1680                 if (!hostapd_cli_commands[i].usage)
1681                         return NULL;
1682                 edit_clear_line();
1683                 printf("\r%s\n", hostapd_cli_commands[i].usage);
1684                 edit_redraw();
1685                 break;
1686         }
1687
1688         return NULL;
1689 }
1690
1691
1692 static char ** hostapd_cli_edit_completion_cb(void *ctx, const char *str,
1693                                               int pos)
1694 {
1695         char **res;
1696         const char *end;
1697         char *cmd;
1698
1699         end = os_strchr(str, ' ');
1700         if (end == NULL || str + pos < end)
1701                 return list_cmd_list();
1702
1703         cmd = os_malloc(pos + 1);
1704         if (cmd == NULL)
1705                 return NULL;
1706         os_memcpy(cmd, str, pos);
1707         cmd[end - str] = '\0';
1708         res = hostapd_cli_cmd_completion(cmd, str, pos);
1709         os_free(cmd);
1710         return res;
1711 }
1712
1713
1714 static void hostapd_cli_interactive(void)
1715 {
1716         printf("\nInteractive mode\n\n");
1717
1718         eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
1719         edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
1720                   hostapd_cli_edit_completion_cb, NULL, NULL, NULL);
1721         eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
1722
1723         eloop_run();
1724
1725         cli_txt_list_flush(&stations);
1726         edit_deinit(NULL, NULL);
1727         eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
1728 }
1729
1730
1731 static void hostapd_cli_cleanup(void)
1732 {
1733         hostapd_cli_close_connection();
1734         if (pid_file)
1735                 os_daemonize_terminate(pid_file);
1736
1737         os_program_deinit();
1738 }
1739
1740
1741 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1742 {
1743         fd_set rfds;
1744         int fd, res;
1745         struct timeval tv;
1746         char buf[256];
1747         size_t len;
1748
1749         fd = wpa_ctrl_get_fd(ctrl);
1750
1751         while (!hostapd_cli_quit) {
1752                 FD_ZERO(&rfds);
1753                 FD_SET(fd, &rfds);
1754                 tv.tv_sec = ping_interval;
1755                 tv.tv_usec = 0;
1756                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1757                 if (res < 0 && errno != EINTR) {
1758                         perror("select");
1759                         break;
1760                 }
1761
1762                 if (FD_ISSET(fd, &rfds))
1763                         hostapd_cli_recv_pending(ctrl, 0, 1);
1764                 else {
1765                         len = sizeof(buf) - 1;
1766                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1767                                              hostapd_cli_action_process) < 0 ||
1768                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1769                                 printf("hostapd did not reply to PING "
1770                                        "command - exiting\n");
1771                                 break;
1772                         }
1773                 }
1774         }
1775 }
1776
1777
1778 int main(int argc, char *argv[])
1779 {
1780         int warning_displayed = 0;
1781         int c;
1782         int daemonize = 0;
1783
1784         if (os_program_init())
1785                 return -1;
1786
1787         for (;;) {
1788                 c = getopt(argc, argv, "a:BhG:i:p:P:s:v");
1789                 if (c < 0)
1790                         break;
1791                 switch (c) {
1792                 case 'a':
1793                         action_file = optarg;
1794                         break;
1795                 case 'B':
1796                         daemonize = 1;
1797                         break;
1798                 case 'G':
1799                         ping_interval = atoi(optarg);
1800                         break;
1801                 case 'h':
1802                         usage();
1803                         return 0;
1804                 case 'v':
1805                         printf("%s\n", hostapd_cli_version);
1806                         return 0;
1807                 case 'i':
1808                         os_free(ctrl_ifname);
1809                         ctrl_ifname = os_strdup(optarg);
1810                         break;
1811                 case 'p':
1812                         ctrl_iface_dir = optarg;
1813                         break;
1814                 case 'P':
1815                         pid_file = optarg;
1816                         break;
1817                 case 's':
1818                         client_socket_dir = optarg;
1819                         break;
1820                 default:
1821                         usage();
1822                         return -1;
1823                 }
1824         }
1825
1826         interactive = (argc == optind) && (action_file == NULL);
1827
1828         if (interactive) {
1829                 printf("%s\n\n%s\n\n", hostapd_cli_version,
1830                        hostapd_cli_license);
1831         }
1832
1833         if (eloop_init())
1834                 return -1;
1835
1836         for (;;) {
1837                 if (ctrl_ifname == NULL) {
1838                         struct dirent *dent;
1839                         DIR *dir = opendir(ctrl_iface_dir);
1840                         if (dir) {
1841                                 while ((dent = readdir(dir))) {
1842                                         if (os_strcmp(dent->d_name, ".") == 0
1843                                             ||
1844                                             os_strcmp(dent->d_name, "..") == 0)
1845                                                 continue;
1846                                         printf("Selected interface '%s'\n",
1847                                                dent->d_name);
1848                                         ctrl_ifname = os_strdup(dent->d_name);
1849                                         break;
1850                                 }
1851                                 closedir(dir);
1852                         }
1853                 }
1854                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1855                 if (ctrl_conn) {
1856                         if (warning_displayed)
1857                                 printf("Connection established.\n");
1858                         break;
1859                 }
1860
1861                 if (!interactive) {
1862                         perror("Failed to connect to hostapd - "
1863                                "wpa_ctrl_open");
1864                         return -1;
1865                 }
1866
1867                 if (!warning_displayed) {
1868                         printf("Could not connect to hostapd - re-trying\n");
1869                         warning_displayed = 1;
1870                 }
1871                 os_sleep(1, 0);
1872                 continue;
1873         }
1874
1875         if (interactive || action_file) {
1876                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1877                         hostapd_cli_attached = 1;
1878                         register_event_handler(ctrl_conn);
1879                 } else {
1880                         printf("Warning: Failed to attach to hostapd.\n");
1881                         if (action_file)
1882                                 return -1;
1883                 }
1884         }
1885
1886         if (daemonize && os_daemonize(pid_file) && eloop_sock_requeue())
1887                 return -1;
1888
1889         if (interactive)
1890                 hostapd_cli_interactive();
1891         else if (action_file)
1892                 hostapd_cli_action(ctrl_conn);
1893         else
1894                 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1895
1896         unregister_event_handler(ctrl_conn);
1897         os_free(ctrl_ifname);
1898         eloop_destroy();
1899         hostapd_cli_cleanup();
1900         return 0;
1901 }
1902
1903 #else /* CONFIG_NO_CTRL_IFACE */
1904
1905 int main(int argc, char *argv[])
1906 {
1907         return -1;
1908 }
1909
1910 #endif /* CONFIG_NO_CTRL_IFACE */