OSDN Git Service

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