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