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