OSDN Git Service

Accumulative patch from commit b618a469c42120e984ab1c85ed6058504d1fca78
[android-x86/external-wpa_supplicant_8.git] / hostapd / hostapd_cli.c
1 /*
2  * hostapd - command line interface for hostapd daemon
3  * Copyright (c) 2004-2012, 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 "utils/common.h"
14 #include "utils/eloop.h"
15 #include "utils/edit.h"
16 #include "common/version.h"
17
18
19 static const char *hostapd_cli_version =
20 "hostapd_cli v" VERSION_STR "\n"
21 "Copyright (c) 2004-2013, Jouni Malinen <j@w1.fi> and contributors";
22
23
24 static const char *hostapd_cli_license =
25 "This software may be distributed under the terms of the BSD license.\n"
26 "See README for more details.\n";
27
28 static const char *hostapd_cli_full_license =
29 "This software may be distributed under the terms of the BSD license.\n"
30 "\n"
31 "Redistribution and use in source and binary forms, with or without\n"
32 "modification, are permitted provided that the following conditions are\n"
33 "met:\n"
34 "\n"
35 "1. Redistributions of source code must retain the above copyright\n"
36 "   notice, this list of conditions and the following disclaimer.\n"
37 "\n"
38 "2. Redistributions in binary form must reproduce the above copyright\n"
39 "   notice, this list of conditions and the following disclaimer in the\n"
40 "   documentation and/or other materials provided with the distribution.\n"
41 "\n"
42 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
43 "   names of its contributors may be used to endorse or promote products\n"
44 "   derived from this software without specific prior written permission.\n"
45 "\n"
46 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
47 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
48 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
49 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
50 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
51 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
52 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
53 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
54 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
55 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
56 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
57 "\n";
58
59 static const char *commands_help =
60 "Commands:\n"
61 "   mib                  get MIB variables (dot1x, dot11, radius)\n"
62 "   sta <addr>           get MIB variables for one station\n"
63 "   all_sta              get MIB variables for all stations\n"
64 "   new_sta <addr>       add a new station\n"
65 "   deauthenticate <addr>  deauthenticate a station\n"
66 "   disassociate <addr>  disassociate a station\n"
67 #ifdef CONFIG_IEEE80211W
68 "   sa_query <addr>      send SA Query to a station\n"
69 #endif /* CONFIG_IEEE80211W */
70 #ifdef CONFIG_WPS
71 "   wps_pin <uuid> <pin> [timeout] [addr]  add WPS Enrollee PIN\n"
72 "   wps_check_pin <PIN>  verify PIN checksum\n"
73 "   wps_pbc              indicate button pushed to initiate PBC\n"
74 "   wps_cancel           cancel the pending WPS operation\n"
75 #ifdef CONFIG_WPS_NFC
76 "   wps_nfc_tag_read <hexdump>  report read NFC tag with WPS data\n"
77 "   wps_nfc_config_token <WPS/NDEF>  build NFC configuration token\n"
78 "   wps_nfc_token <WPS/NDEF/enable/disable>  manager NFC password token\n"
79 #endif /* CONFIG_WPS_NFC */
80 "   wps_ap_pin <cmd> [params..]  enable/disable AP PIN\n"
81 "   wps_config <SSID> <auth> <encr> <key>  configure AP\n"
82 #endif /* CONFIG_WPS */
83 "   get_config           show current configuration\n"
84 "   help                 show this usage help\n"
85 "   interface [ifname]   show interfaces/select interface\n"
86 "   level <debug level>  change debug level\n"
87 "   license              show full hostapd_cli license\n"
88 "   quit                 exit hostapd_cli\n";
89
90 static struct wpa_ctrl *ctrl_conn;
91 static int hostapd_cli_quit = 0;
92 static int hostapd_cli_attached = 0;
93
94 #ifndef CONFIG_CTRL_IFACE_DIR
95 #define CONFIG_CTRL_IFACE_DIR "/var/run/hostapd"
96 #endif /* CONFIG_CTRL_IFACE_DIR */
97 static const char *ctrl_iface_dir = CONFIG_CTRL_IFACE_DIR;
98
99 static char *ctrl_ifname = NULL;
100 static const char *pid_file = NULL;
101 static const char *action_file = NULL;
102 static int ping_interval = 5;
103 static int interactive = 0;
104
105
106 static void usage(void)
107 {
108         fprintf(stderr, "%s\n", hostapd_cli_version);
109         fprintf(stderr,
110                 "\n"
111                 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
112                 "[-a<path>] \\\n"
113                 "                   [-G<ping interval>] [command..]\n"
114                 "\n"
115                 "Options:\n"
116                 "   -h           help (show this usage text)\n"
117                 "   -v           shown version information\n"
118                 "   -p<path>     path to find control sockets (default: "
119                 "/var/run/hostapd)\n"
120                 "   -a<file>     run in daemon mode executing the action file "
121                 "based on events\n"
122                 "                from hostapd\n"
123                 "   -B           run a daemon in the background\n"
124                 "   -i<ifname>   Interface to listen on (default: first "
125                 "interface found in the\n"
126                 "                socket path)\n\n"
127                 "%s",
128                 commands_help);
129 }
130
131
132 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
133 {
134         char *cfile;
135         int flen;
136
137         if (ifname == NULL)
138                 return NULL;
139
140         flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
141         cfile = malloc(flen);
142         if (cfile == NULL)
143                 return NULL;
144         snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
145
146         ctrl_conn = wpa_ctrl_open(cfile);
147         free(cfile);
148         return ctrl_conn;
149 }
150
151
152 static void hostapd_cli_close_connection(void)
153 {
154         if (ctrl_conn == NULL)
155                 return;
156
157         if (hostapd_cli_attached) {
158                 wpa_ctrl_detach(ctrl_conn);
159                 hostapd_cli_attached = 0;
160         }
161         wpa_ctrl_close(ctrl_conn);
162         ctrl_conn = NULL;
163 }
164
165
166 static void hostapd_cli_msg_cb(char *msg, size_t len)
167 {
168         printf("%s\n", msg);
169 }
170
171
172 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
173 {
174         char buf[4096];
175         size_t len;
176         int ret;
177
178         if (ctrl_conn == NULL) {
179                 printf("Not connected to hostapd - command dropped.\n");
180                 return -1;
181         }
182         len = sizeof(buf) - 1;
183         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
184                                hostapd_cli_msg_cb);
185         if (ret == -2) {
186                 printf("'%s' command timed out.\n", cmd);
187                 return -2;
188         } else if (ret < 0) {
189                 printf("'%s' command failed.\n", cmd);
190                 return -1;
191         }
192         if (print) {
193                 buf[len] = '\0';
194                 printf("%s", buf);
195         }
196         return 0;
197 }
198
199
200 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
201 {
202         return _wpa_ctrl_command(ctrl, cmd, 1);
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_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
219 {
220         return wpa_ctrl_command(ctrl, "MIB");
221 }
222
223
224 static int hostapd_cli_exec(const char *program, const char *arg1,
225                             const char *arg2)
226 {
227         char *cmd;
228         size_t len;
229         int res;
230         int ret = 0;
231
232         len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
233         cmd = os_malloc(len);
234         if (cmd == NULL)
235                 return -1;
236         res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
237         if (res < 0 || (size_t) res >= len) {
238                 os_free(cmd);
239                 return -1;
240         }
241         cmd[len - 1] = '\0';
242 #ifndef _WIN32_WCE
243         if (system(cmd) < 0)
244                 ret = -1;
245 #endif /* _WIN32_WCE */
246         os_free(cmd);
247
248         return ret;
249 }
250
251
252 static void hostapd_cli_action_process(char *msg, size_t len)
253 {
254         const char *pos;
255
256         pos = msg;
257         if (*pos == '<') {
258                 pos = os_strchr(pos, '>');
259                 if (pos)
260                         pos++;
261                 else
262                         pos = msg;
263         }
264
265         hostapd_cli_exec(action_file, ctrl_ifname, pos);
266 }
267
268
269 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
270 {
271         char buf[64];
272         if (argc != 1) {
273                 printf("Invalid 'sta' command - exactly one argument, STA "
274                        "address, is required.\n");
275                 return -1;
276         }
277         snprintf(buf, sizeof(buf), "STA %s", argv[0]);
278         return wpa_ctrl_command(ctrl, buf);
279 }
280
281
282 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
283                                    char *argv[])
284 {
285         char buf[64];
286         if (argc != 1) {
287                 printf("Invalid 'new_sta' command - exactly one argument, STA "
288                        "address, is required.\n");
289                 return -1;
290         }
291         snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
292         return wpa_ctrl_command(ctrl, buf);
293 }
294
295
296 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
297                                           char *argv[])
298 {
299         char buf[64];
300         if (argc < 1) {
301                 printf("Invalid 'deauthenticate' command - exactly one "
302                        "argument, STA address, is required.\n");
303                 return -1;
304         }
305         if (argc > 1)
306                 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
307                             argv[0], argv[1]);
308         else
309                 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
310         return wpa_ctrl_command(ctrl, buf);
311 }
312
313
314 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
315                                         char *argv[])
316 {
317         char buf[64];
318         if (argc < 1) {
319                 printf("Invalid 'disassociate' command - exactly one "
320                        "argument, STA address, is required.\n");
321                 return -1;
322         }
323         if (argc > 1)
324                 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
325                             argv[0], argv[1]);
326         else
327                 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
328         return wpa_ctrl_command(ctrl, buf);
329 }
330
331
332 #ifdef CONFIG_IEEE80211W
333 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
334                                     char *argv[])
335 {
336         char buf[64];
337         if (argc != 1) {
338                 printf("Invalid 'sa_query' command - exactly one argument, "
339                        "STA address, is required.\n");
340                 return -1;
341         }
342         snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
343         return wpa_ctrl_command(ctrl, buf);
344 }
345 #endif /* CONFIG_IEEE80211W */
346
347
348 #ifdef CONFIG_WPS
349 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
350                                    char *argv[])
351 {
352         char buf[256];
353         if (argc < 2) {
354                 printf("Invalid 'wps_pin' command - at least two arguments, "
355                        "UUID and PIN, are required.\n");
356                 return -1;
357         }
358         if (argc > 3)
359                 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
360                          argv[0], argv[1], argv[2], argv[3]);
361         else if (argc > 2)
362                 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
363                          argv[0], argv[1], argv[2]);
364         else
365                 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
366         return wpa_ctrl_command(ctrl, buf);
367 }
368
369
370 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
371                                          char *argv[])
372 {
373         char cmd[256];
374         int res;
375
376         if (argc != 1 && argc != 2) {
377                 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
378                        "- PIN to be verified\n");
379                 return -1;
380         }
381
382         if (argc == 2)
383                 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
384                                   argv[0], argv[1]);
385         else
386                 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
387                                   argv[0]);
388         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
389                 printf("Too long WPS_CHECK_PIN command.\n");
390                 return -1;
391         }
392         return wpa_ctrl_command(ctrl, cmd);
393 }
394
395
396 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
397                                    char *argv[])
398 {
399         return wpa_ctrl_command(ctrl, "WPS_PBC");
400 }
401
402
403 static int hostapd_cli_cmd_wps_cancel(struct wpa_ctrl *ctrl, int argc,
404                                       char *argv[])
405 {
406         return wpa_ctrl_command(ctrl, "WPS_CANCEL");
407 }
408
409
410 #ifdef CONFIG_WPS_NFC
411 static int hostapd_cli_cmd_wps_nfc_tag_read(struct wpa_ctrl *ctrl, int argc,
412                                             char *argv[])
413 {
414         int ret;
415         char *buf;
416         size_t buflen;
417
418         if (argc != 1) {
419                 printf("Invalid 'wps_nfc_tag_read' command - one argument "
420                        "is required.\n");
421                 return -1;
422         }
423
424         buflen = 18 + os_strlen(argv[0]);
425         buf = os_malloc(buflen);
426         if (buf == NULL)
427                 return -1;
428         os_snprintf(buf, buflen, "WPS_NFC_TAG_READ %s", argv[0]);
429
430         ret = wpa_ctrl_command(ctrl, buf);
431         os_free(buf);
432
433         return ret;
434 }
435
436
437 static int hostapd_cli_cmd_wps_nfc_config_token(struct wpa_ctrl *ctrl,
438                                                 int argc, char *argv[])
439 {
440         char cmd[64];
441         int res;
442
443         if (argc != 1) {
444                 printf("Invalid 'wps_nfc_config_token' command - one argument "
445                        "is required.\n");
446                 return -1;
447         }
448
449         res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_CONFIG_TOKEN %s",
450                           argv[0]);
451         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
452                 printf("Too long WPS_NFC_CONFIG_TOKEN command.\n");
453                 return -1;
454         }
455         return wpa_ctrl_command(ctrl, cmd);
456 }
457
458
459 static int hostapd_cli_cmd_wps_nfc_token(struct wpa_ctrl *ctrl,
460                                          int argc, char *argv[])
461 {
462         char cmd[64];
463         int res;
464
465         if (argc != 1) {
466                 printf("Invalid 'wps_nfc_token' command - one argument is "
467                        "required.\n");
468                 return -1;
469         }
470
471         res = os_snprintf(cmd, sizeof(cmd), "WPS_NFC_TOKEN %s", argv[0]);
472         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
473                 printf("Too long WPS_NFC_TOKEN command.\n");
474                 return -1;
475         }
476         return wpa_ctrl_command(ctrl, cmd);
477 }
478
479
480 static int hostapd_cli_cmd_nfc_get_handover_sel(struct wpa_ctrl *ctrl,
481                                                 int argc, char *argv[])
482 {
483         char cmd[64];
484         int res;
485
486         if (argc != 2) {
487                 printf("Invalid 'nfc_get_handover_sel' command - two arguments "
488                        "are required.\n");
489                 return -1;
490         }
491
492         res = os_snprintf(cmd, sizeof(cmd), "NFC_GET_HANDOVER_SEL %s %s",
493                           argv[0], argv[1]);
494         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
495                 printf("Too long NFC_GET_HANDOVER_SEL command.\n");
496                 return -1;
497         }
498         return wpa_ctrl_command(ctrl, cmd);
499 }
500
501 #endif /* CONFIG_WPS_NFC */
502
503
504 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
505                                       char *argv[])
506 {
507         char buf[64];
508         if (argc < 1) {
509                 printf("Invalid 'wps_ap_pin' command - at least one argument "
510                        "is required.\n");
511                 return -1;
512         }
513         if (argc > 2)
514                 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
515                          argv[0], argv[1], argv[2]);
516         else if (argc > 1)
517                 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
518                          argv[0], argv[1]);
519         else
520                 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
521         return wpa_ctrl_command(ctrl, buf);
522 }
523
524
525 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
526                                       char *argv[])
527 {
528         char buf[256];
529         char ssid_hex[2 * 32 + 1];
530         char key_hex[2 * 64 + 1];
531         int i;
532
533         if (argc < 1) {
534                 printf("Invalid 'wps_config' command - at least two arguments "
535                        "are required.\n");
536                 return -1;
537         }
538
539         ssid_hex[0] = '\0';
540         for (i = 0; i < 32; i++) {
541                 if (argv[0][i] == '\0')
542                         break;
543                 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
544         }
545
546         key_hex[0] = '\0';
547         if (argc > 3) {
548                 for (i = 0; i < 64; i++) {
549                         if (argv[3][i] == '\0')
550                                 break;
551                         os_snprintf(&key_hex[i * 2], 3, "%02x",
552                                     argv[3][i]);
553                 }
554         }
555
556         if (argc > 3)
557                 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
558                          ssid_hex, argv[1], argv[2], key_hex);
559         else if (argc > 2)
560                 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
561                          ssid_hex, argv[1], argv[2]);
562         else
563                 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
564                          ssid_hex, argv[1]);
565         return wpa_ctrl_command(ctrl, buf);
566 }
567 #endif /* CONFIG_WPS */
568
569
570 static int hostapd_cli_cmd_disassoc_imminent(struct wpa_ctrl *ctrl, int argc,
571                                              char *argv[])
572 {
573         char buf[300];
574         int res;
575
576         if (argc < 2) {
577                 printf("Invalid 'disassoc_imminent' command - two arguments "
578                        "(STA addr and Disassociation Timer) are needed\n");
579                 return -1;
580         }
581
582         res = os_snprintf(buf, sizeof(buf), "DISASSOC_IMMINENT %s %s",
583                           argv[0], argv[1]);
584         if (res < 0 || res >= (int) sizeof(buf))
585                 return -1;
586         return wpa_ctrl_command(ctrl, buf);
587 }
588
589
590 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
591                                         char *argv[])
592 {
593         char buf[300];
594         int res;
595
596         if (argc < 2) {
597                 printf("Invalid 'ess_disassoc' command - two arguments (STA "
598                        "addr and URL) are needed\n");
599                 return -1;
600         }
601
602         res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s",
603                           argv[0], argv[1]);
604         if (res < 0 || res >= (int) sizeof(buf))
605                 return -1;
606         return wpa_ctrl_command(ctrl, buf);
607 }
608
609
610 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
611                                       char *argv[])
612 {
613         return wpa_ctrl_command(ctrl, "GET_CONFIG");
614 }
615
616
617 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
618                                 char *addr, size_t addr_len)
619 {
620         char buf[4096], *pos;
621         size_t len;
622         int ret;
623
624         if (ctrl_conn == NULL) {
625                 printf("Not connected to hostapd - command dropped.\n");
626                 return -1;
627         }
628         len = sizeof(buf) - 1;
629         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
630                                hostapd_cli_msg_cb);
631         if (ret == -2) {
632                 printf("'%s' command timed out.\n", cmd);
633                 return -2;
634         } else if (ret < 0) {
635                 printf("'%s' command failed.\n", cmd);
636                 return -1;
637         }
638
639         buf[len] = '\0';
640         if (memcmp(buf, "FAIL", 4) == 0)
641                 return -1;
642         printf("%s", buf);
643
644         pos = buf;
645         while (*pos != '\0' && *pos != '\n')
646                 pos++;
647         *pos = '\0';
648         os_strlcpy(addr, buf, addr_len);
649         return 0;
650 }
651
652
653 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
654                                    char *argv[])
655 {
656         char addr[32], cmd[64];
657
658         if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
659                 return 0;
660         do {
661                 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
662         } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
663
664         return -1;
665 }
666
667
668 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
669 {
670         printf("%s", commands_help);
671         return 0;
672 }
673
674
675 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
676                                    char *argv[])
677 {
678         printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
679         return 0;
680 }
681
682
683 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
684 {
685         hostapd_cli_quit = 1;
686         if (interactive)
687                 eloop_terminate();
688         return 0;
689 }
690
691
692 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
693 {
694         char cmd[256];
695         if (argc != 1) {
696                 printf("Invalid LEVEL command: needs one argument (debug "
697                        "level)\n");
698                 return 0;
699         }
700         snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
701         return wpa_ctrl_command(ctrl, cmd);
702 }
703
704
705 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
706 {
707         struct dirent *dent;
708         DIR *dir;
709
710         dir = opendir(ctrl_iface_dir);
711         if (dir == NULL) {
712                 printf("Control interface directory '%s' could not be "
713                        "openned.\n", ctrl_iface_dir);
714                 return;
715         }
716
717         printf("Available interfaces:\n");
718         while ((dent = readdir(dir))) {
719                 if (strcmp(dent->d_name, ".") == 0 ||
720                     strcmp(dent->d_name, "..") == 0)
721                         continue;
722                 printf("%s\n", dent->d_name);
723         }
724         closedir(dir);
725 }
726
727
728 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
729                                      char *argv[])
730 {
731         if (argc < 1) {
732                 hostapd_cli_list_interfaces(ctrl);
733                 return 0;
734         }
735
736         hostapd_cli_close_connection();
737         free(ctrl_ifname);
738         ctrl_ifname = strdup(argv[0]);
739
740         if (hostapd_cli_open_connection(ctrl_ifname)) {
741                 printf("Connected to interface '%s.\n", ctrl_ifname);
742                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
743                         hostapd_cli_attached = 1;
744                 } else {
745                         printf("Warning: Failed to attach to "
746                                "hostapd.\n");
747                 }
748         } else {
749                 printf("Could not connect to interface '%s' - re-trying\n",
750                         ctrl_ifname);
751         }
752         return 0;
753 }
754
755
756 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
757 {
758         char cmd[256];
759         int res;
760
761         if (argc != 2) {
762                 printf("Invalid SET command: needs two arguments (variable "
763                        "name and value)\n");
764                 return -1;
765         }
766
767         res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
768         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
769                 printf("Too long SET command.\n");
770                 return -1;
771         }
772         return wpa_ctrl_command(ctrl, cmd);
773 }
774
775
776 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
777 {
778         char cmd[256];
779         int res;
780
781         if (argc != 1) {
782                 printf("Invalid GET command: needs one argument (variable "
783                        "name)\n");
784                 return -1;
785         }
786
787         res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
788         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
789                 printf("Too long GET command.\n");
790                 return -1;
791         }
792         return wpa_ctrl_command(ctrl, cmd);
793 }
794
795
796 struct hostapd_cli_cmd {
797         const char *cmd;
798         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
799 };
800
801 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
802         { "ping", hostapd_cli_cmd_ping },
803         { "mib", hostapd_cli_cmd_mib },
804         { "relog", hostapd_cli_cmd_relog },
805         { "sta", hostapd_cli_cmd_sta },
806         { "all_sta", hostapd_cli_cmd_all_sta },
807         { "new_sta", hostapd_cli_cmd_new_sta },
808         { "deauthenticate", hostapd_cli_cmd_deauthenticate },
809         { "disassociate", hostapd_cli_cmd_disassociate },
810 #ifdef CONFIG_IEEE80211W
811         { "sa_query", hostapd_cli_cmd_sa_query },
812 #endif /* CONFIG_IEEE80211W */
813 #ifdef CONFIG_WPS
814         { "wps_pin", hostapd_cli_cmd_wps_pin },
815         { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
816         { "wps_pbc", hostapd_cli_cmd_wps_pbc },
817         { "wps_cancel", hostapd_cli_cmd_wps_cancel },
818 #ifdef CONFIG_WPS_NFC
819         { "wps_nfc_tag_read", hostapd_cli_cmd_wps_nfc_tag_read },
820         { "wps_nfc_config_token", hostapd_cli_cmd_wps_nfc_config_token },
821         { "wps_nfc_token", hostapd_cli_cmd_wps_nfc_token },
822         { "nfc_get_handover_sel", hostapd_cli_cmd_nfc_get_handover_sel },
823 #endif /* CONFIG_WPS_NFC */
824         { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
825         { "wps_config", hostapd_cli_cmd_wps_config },
826 #endif /* CONFIG_WPS */
827         { "disassoc_imminent", hostapd_cli_cmd_disassoc_imminent },
828         { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
829         { "get_config", hostapd_cli_cmd_get_config },
830         { "help", hostapd_cli_cmd_help },
831         { "interface", hostapd_cli_cmd_interface },
832         { "level", hostapd_cli_cmd_level },
833         { "license", hostapd_cli_cmd_license },
834         { "quit", hostapd_cli_cmd_quit },
835         { "set", hostapd_cli_cmd_set },
836         { "get", hostapd_cli_cmd_get },
837         { NULL, NULL }
838 };
839
840
841 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
842 {
843         struct hostapd_cli_cmd *cmd, *match = NULL;
844         int count;
845
846         count = 0;
847         cmd = hostapd_cli_commands;
848         while (cmd->cmd) {
849                 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
850                         match = cmd;
851                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
852                                 /* we have an exact match */
853                                 count = 1;
854                                 break;
855                         }
856                         count++;
857                 }
858                 cmd++;
859         }
860
861         if (count > 1) {
862                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
863                 cmd = hostapd_cli_commands;
864                 while (cmd->cmd) {
865                         if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
866                             0) {
867                                 printf(" %s", cmd->cmd);
868                         }
869                         cmd++;
870                 }
871                 printf("\n");
872         } else if (count == 0) {
873                 printf("Unknown command '%s'\n", argv[0]);
874         } else {
875                 match->handler(ctrl, argc - 1, &argv[1]);
876         }
877 }
878
879
880 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
881                                      int action_monitor)
882 {
883         int first = 1;
884         if (ctrl_conn == NULL)
885                 return;
886         while (wpa_ctrl_pending(ctrl)) {
887                 char buf[256];
888                 size_t len = sizeof(buf) - 1;
889                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
890                         buf[len] = '\0';
891                         if (action_monitor)
892                                 hostapd_cli_action_process(buf, len);
893                         else {
894                                 if (in_read && first)
895                                         printf("\n");
896                                 first = 0;
897                                 printf("%s\n", buf);
898                         }
899                 } else {
900                         printf("Could not read pending message.\n");
901                         break;
902                 }
903         }
904 }
905
906
907 #define max_args 10
908
909 static int tokenize_cmd(char *cmd, char *argv[])
910 {
911         char *pos;
912         int argc = 0;
913
914         pos = cmd;
915         for (;;) {
916                 while (*pos == ' ')
917                         pos++;
918                 if (*pos == '\0')
919                         break;
920                 argv[argc] = pos;
921                 argc++;
922                 if (argc == max_args)
923                         break;
924                 if (*pos == '"') {
925                         char *pos2 = os_strrchr(pos, '"');
926                         if (pos2)
927                                 pos = pos2 + 1;
928                 }
929                 while (*pos != '\0' && *pos != ' ')
930                         pos++;
931                 if (*pos == ' ')
932                         *pos++ = '\0';
933         }
934
935         return argc;
936 }
937
938
939 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
940 {
941         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
942                 printf("Connection to hostapd lost - trying to reconnect\n");
943                 hostapd_cli_close_connection();
944         }
945         if (!ctrl_conn) {
946                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
947                 if (ctrl_conn) {
948                         printf("Connection to hostapd re-established\n");
949                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
950                                 hostapd_cli_attached = 1;
951                         } else {
952                                 printf("Warning: Failed to attach to "
953                                        "hostapd.\n");
954                         }
955                 }
956         }
957         if (ctrl_conn)
958                 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
959         eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
960 }
961
962
963 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
964 {
965         eloop_terminate();
966 }
967
968
969 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
970 {
971         char *argv[max_args];
972         int argc;
973         argc = tokenize_cmd(cmd, argv);
974         if (argc)
975                 wpa_request(ctrl_conn, argc, argv);
976 }
977
978
979 static void hostapd_cli_edit_eof_cb(void *ctx)
980 {
981         eloop_terminate();
982 }
983
984
985 static void hostapd_cli_interactive(void)
986 {
987         printf("\nInteractive mode\n\n");
988
989         eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
990         edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
991                   NULL, NULL, NULL, NULL);
992         eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
993
994         eloop_run();
995
996         edit_deinit(NULL, NULL);
997         eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
998 }
999
1000
1001 static void hostapd_cli_cleanup(void)
1002 {
1003         hostapd_cli_close_connection();
1004         if (pid_file)
1005                 os_daemonize_terminate(pid_file);
1006
1007         os_program_deinit();
1008 }
1009
1010
1011 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
1012 {
1013         fd_set rfds;
1014         int fd, res;
1015         struct timeval tv;
1016         char buf[256];
1017         size_t len;
1018
1019         fd = wpa_ctrl_get_fd(ctrl);
1020
1021         while (!hostapd_cli_quit) {
1022                 FD_ZERO(&rfds);
1023                 FD_SET(fd, &rfds);
1024                 tv.tv_sec = ping_interval;
1025                 tv.tv_usec = 0;
1026                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
1027                 if (res < 0 && errno != EINTR) {
1028                         perror("select");
1029                         break;
1030                 }
1031
1032                 if (FD_ISSET(fd, &rfds))
1033                         hostapd_cli_recv_pending(ctrl, 0, 1);
1034                 else {
1035                         len = sizeof(buf) - 1;
1036                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
1037                                              hostapd_cli_action_process) < 0 ||
1038                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
1039                                 printf("hostapd did not reply to PING "
1040                                        "command - exiting\n");
1041                                 break;
1042                         }
1043                 }
1044         }
1045 }
1046
1047
1048 int main(int argc, char *argv[])
1049 {
1050         int warning_displayed = 0;
1051         int c;
1052         int daemonize = 0;
1053
1054         if (os_program_init())
1055                 return -1;
1056
1057         for (;;) {
1058                 c = getopt(argc, argv, "a:BhG:i:p:v");
1059                 if (c < 0)
1060                         break;
1061                 switch (c) {
1062                 case 'a':
1063                         action_file = optarg;
1064                         break;
1065                 case 'B':
1066                         daemonize = 1;
1067                         break;
1068                 case 'G':
1069                         ping_interval = atoi(optarg);
1070                         break;
1071                 case 'h':
1072                         usage();
1073                         return 0;
1074                 case 'v':
1075                         printf("%s\n", hostapd_cli_version);
1076                         return 0;
1077                 case 'i':
1078                         os_free(ctrl_ifname);
1079                         ctrl_ifname = os_strdup(optarg);
1080                         break;
1081                 case 'p':
1082                         ctrl_iface_dir = optarg;
1083                         break;
1084                 default:
1085                         usage();
1086                         return -1;
1087                 }
1088         }
1089
1090         interactive = (argc == optind) && (action_file == NULL);
1091
1092         if (interactive) {
1093                 printf("%s\n\n%s\n\n", hostapd_cli_version,
1094                        hostapd_cli_license);
1095         }
1096
1097         if (eloop_init())
1098                 return -1;
1099
1100         for (;;) {
1101                 if (ctrl_ifname == NULL) {
1102                         struct dirent *dent;
1103                         DIR *dir = opendir(ctrl_iface_dir);
1104                         if (dir) {
1105                                 while ((dent = readdir(dir))) {
1106                                         if (os_strcmp(dent->d_name, ".") == 0
1107                                             ||
1108                                             os_strcmp(dent->d_name, "..") == 0)
1109                                                 continue;
1110                                         printf("Selected interface '%s'\n",
1111                                                dent->d_name);
1112                                         ctrl_ifname = os_strdup(dent->d_name);
1113                                         break;
1114                                 }
1115                                 closedir(dir);
1116                         }
1117                 }
1118                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1119                 if (ctrl_conn) {
1120                         if (warning_displayed)
1121                                 printf("Connection established.\n");
1122                         break;
1123                 }
1124
1125                 if (!interactive) {
1126                         perror("Failed to connect to hostapd - "
1127                                "wpa_ctrl_open");
1128                         return -1;
1129                 }
1130
1131                 if (!warning_displayed) {
1132                         printf("Could not connect to hostapd - re-trying\n");
1133                         warning_displayed = 1;
1134                 }
1135                 os_sleep(1, 0);
1136                 continue;
1137         }
1138
1139         if (interactive || action_file) {
1140                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1141                         hostapd_cli_attached = 1;
1142                 } else {
1143                         printf("Warning: Failed to attach to hostapd.\n");
1144                         if (action_file)
1145                                 return -1;
1146                 }
1147         }
1148
1149         if (daemonize && os_daemonize(pid_file))
1150                 return -1;
1151
1152         if (interactive)
1153                 hostapd_cli_interactive();
1154         else if (action_file)
1155                 hostapd_cli_action(ctrl_conn);
1156         else
1157                 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1158
1159         os_free(ctrl_ifname);
1160         eloop_destroy();
1161         hostapd_cli_cleanup();
1162         return 0;
1163 }