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