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