Select the BSD license terms as the only license alternative
[build-utilities/hostap.git] / hostapd / hostapd_cli.c
1 /*
2  * hostapd - command line interface for hostapd daemon
3  * Copyright (c) 2004-2011, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
15 #include "includes.h"
16 #include <dirent.h>
18 #include "common/wpa_ctrl.h"
19 #include "utils/common.h"
20 #include "utils/eloop.h"
21 #include "utils/edit.h"
22 #include "common/version.h"
25 static const char *hostapd_cli_version =
26 "hostapd_cli v" VERSION_STR "\n"
27 "Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi> and contributors";
30 static const char *hostapd_cli_license =
31 "This software may be distributed under the terms of the BSD license.\n"
32 "See README for more details.\n";
34 static const char *hostapd_cli_full_license =
35 "This software may be distributed under the terms of the BSD license.\n"
36 "\n"
37 "Redistribution and use in source and binary forms, with or without\n"
38 "modification, are permitted provided that the following conditions are\n"
39 "met:\n"
40 "\n"
41 "1. Redistributions of source code must retain the above copyright\n"
42 "   notice, this list of conditions and the following disclaimer.\n"
43 "\n"
44 "2. Redistributions in binary form must reproduce the above copyright\n"
45 "   notice, this list of conditions and the following disclaimer in the\n"
46 "   documentation and/or other materials provided with the distribution.\n"
47 "\n"
48 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
49 "   names of its contributors may be used to endorse or promote products\n"
50 "   derived from this software without specific prior written permission.\n"
51 "\n"
52 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
53 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
54 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
55 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
56 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
57 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
58 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
59 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
60 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
61 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
62 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
63 "\n";
65 static const char *commands_help =
66 "Commands:\n"
67 "   mib                  get MIB variables (dot1x, dot11, radius)\n"
68 "   sta <addr>           get MIB variables for one station\n"
69 "   all_sta              get MIB variables for all stations\n"
70 "   new_sta <addr>       add a new station\n"
71 "   deauthenticate <addr>  deauthenticate a station\n"
72 "   disassociate <addr>  disassociate a station\n"
73 #ifdef CONFIG_IEEE80211W
74 "   sa_query <addr>      send SA Query to a station\n"
75 #endif /* CONFIG_IEEE80211W */
76 #ifdef CONFIG_WPS
77 "   wps_pin <uuid> <pin> [timeout] [addr]  add WPS Enrollee PIN\n"
78 "   wps_check_pin <PIN>  verify PIN checksum\n"
79 "   wps_pbc              indicate button pushed to initiate PBC\n"
80 #ifdef CONFIG_WPS_OOB
81 "   wps_oob <type> <path> <method>  use WPS with out-of-band (UFD)\n"
82 #endif /* CONFIG_WPS_OOB */
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";
93 static struct wpa_ctrl *ctrl_conn;
94 static int hostapd_cli_quit = 0;
95 static int hostapd_cli_attached = 0;
96 static const char *ctrl_iface_dir = "/var/run/hostapd";
97 static char *ctrl_ifname = NULL;
98 static const char *pid_file = NULL;
99 static const char *action_file = NULL;
100 static int ping_interval = 5;
101 static int interactive = 0;
104 static void usage(void)
106         fprintf(stderr, "%s\n", hostapd_cli_version);
107         fprintf(stderr,
108                 "\n"
109                 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
110                 "[-a<path>] \\\n"
111                 "                   [-G<ping interval>] [command..]\n"
112                 "\n"
113                 "Options:\n"
114                 "   -h           help (show this usage text)\n"
115                 "   -v           shown version information\n"
116                 "   -p<path>     path to find control sockets (default: "
117                 "/var/run/hostapd)\n"
118                 "   -a<file>     run in daemon mode executing the action file "
119                 "based on events\n"
120                 "                from hostapd\n"
121                 "   -B           run a daemon in the background\n"
122                 "   -i<ifname>   Interface to listen on (default: first "
123                 "interface found in the\n"
124                 "                socket path)\n\n"
125                 "%s",
126                 commands_help);
130 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
132         char *cfile;
133         int flen;
135         if (ifname == NULL)
136                 return NULL;
138         flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
139         cfile = malloc(flen);
140         if (cfile == NULL)
141                 return NULL;
142         snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
144         ctrl_conn = wpa_ctrl_open(cfile);
145         free(cfile);
146         return ctrl_conn;
150 static void hostapd_cli_close_connection(void)
152         if (ctrl_conn == NULL)
153                 return;
155         if (hostapd_cli_attached) {
156                 wpa_ctrl_detach(ctrl_conn);
157                 hostapd_cli_attached = 0;
158         }
159         wpa_ctrl_close(ctrl_conn);
160         ctrl_conn = NULL;
164 static void hostapd_cli_msg_cb(char *msg, size_t len)
166         printf("%s\n", msg);
170 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
172         char buf[4096];
173         size_t len;
174         int ret;
176         if (ctrl_conn == NULL) {
177                 printf("Not connected to hostapd - command dropped.\n");
178                 return -1;
179         }
180         len = sizeof(buf) - 1;
181         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
182                                hostapd_cli_msg_cb);
183         if (ret == -2) {
184                 printf("'%s' command timed out.\n", cmd);
185                 return -2;
186         } else if (ret < 0) {
187                 printf("'%s' command failed.\n", cmd);
188                 return -1;
189         }
190         if (print) {
191                 buf[len] = '\0';
192                 printf("%s", buf);
193         }
194         return 0;
198 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
200         return _wpa_ctrl_command(ctrl, cmd, 1);
204 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
206         return wpa_ctrl_command(ctrl, "PING");
210 static int hostapd_cli_cmd_relog(struct wpa_ctrl *ctrl, int argc, char *argv[])
212         return wpa_ctrl_command(ctrl, "RELOG");
216 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
218         return wpa_ctrl_command(ctrl, "MIB");
222 static int hostapd_cli_exec(const char *program, const char *arg1,
223                             const char *arg2)
225         char *cmd;
226         size_t len;
227         int res;
228         int ret = 0;
230         len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
231         cmd = os_malloc(len);
232         if (cmd == NULL)
233                 return -1;
234         res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
235         if (res < 0 || (size_t) res >= len) {
236                 os_free(cmd);
237                 return -1;
238         }
239         cmd[len - 1] = '\0';
240 #ifndef _WIN32_WCE
241         if (system(cmd) < 0)
242                 ret = -1;
243 #endif /* _WIN32_WCE */
244         os_free(cmd);
246         return ret;
250 static void hostapd_cli_action_process(char *msg, size_t len)
252         const char *pos;
254         pos = msg;
255         if (*pos == '<') {
256                 pos = os_strchr(pos, '>');
257                 if (pos)
258                         pos++;
259                 else
260                         pos = msg;
261         }
263         hostapd_cli_exec(action_file, ctrl_ifname, pos);
267 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
269         char buf[64];
270         if (argc != 1) {
271                 printf("Invalid 'sta' command - exactly one argument, STA "
272                        "address, is required.\n");
273                 return -1;
274         }
275         snprintf(buf, sizeof(buf), "STA %s", argv[0]);
276         return wpa_ctrl_command(ctrl, buf);
280 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
281                                    char *argv[])
283         char buf[64];
284         if (argc != 1) {
285                 printf("Invalid 'new_sta' command - exactly one argument, STA "
286                        "address, is required.\n");
287                 return -1;
288         }
289         snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
290         return wpa_ctrl_command(ctrl, buf);
294 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
295                                           char *argv[])
297         char buf[64];
298         if (argc < 1) {
299                 printf("Invalid 'deauthenticate' command - exactly one "
300                        "argument, STA address, is required.\n");
301                 return -1;
302         }
303         if (argc > 1)
304                 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
305                             argv[0], argv[1]);
306         else
307                 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
308         return wpa_ctrl_command(ctrl, buf);
312 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
313                                         char *argv[])
315         char buf[64];
316         if (argc < 1) {
317                 printf("Invalid 'disassociate' command - exactly one "
318                        "argument, STA address, is required.\n");
319                 return -1;
320         }
321         if (argc > 1)
322                 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
323                             argv[0], argv[1]);
324         else
325                 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
326         return wpa_ctrl_command(ctrl, buf);
330 #ifdef CONFIG_IEEE80211W
331 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
332                                     char *argv[])
334         char buf[64];
335         if (argc != 1) {
336                 printf("Invalid 'sa_query' command - exactly one argument, "
337                        "STA address, is required.\n");
338                 return -1;
339         }
340         snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
341         return wpa_ctrl_command(ctrl, buf);
343 #endif /* CONFIG_IEEE80211W */
346 #ifdef CONFIG_WPS
347 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
348                                    char *argv[])
350         char buf[256];
351         if (argc < 2) {
352                 printf("Invalid 'wps_pin' command - at least two arguments, "
353                        "UUID and PIN, are required.\n");
354                 return -1;
355         }
356         if (argc > 3)
357                 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s %s",
358                          argv[0], argv[1], argv[2], argv[3]);
359         else if (argc > 2)
360                 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
361                          argv[0], argv[1], argv[2]);
362         else
363                 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
364         return wpa_ctrl_command(ctrl, buf);
368 static int hostapd_cli_cmd_wps_check_pin(struct wpa_ctrl *ctrl, int argc,
369                                          char *argv[])
371         char cmd[256];
372         int res;
374         if (argc != 1 && argc != 2) {
375                 printf("Invalid WPS_CHECK_PIN command: needs one argument:\n"
376                        "- PIN to be verified\n");
377                 return -1;
378         }
380         if (argc == 2)
381                 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s %s",
382                                   argv[0], argv[1]);
383         else
384                 res = os_snprintf(cmd, sizeof(cmd), "WPS_CHECK_PIN %s",
385                                   argv[0]);
386         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
387                 printf("Too long WPS_CHECK_PIN command.\n");
388                 return -1;
389         }
390         return wpa_ctrl_command(ctrl, cmd);
394 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
395                                    char *argv[])
397         return wpa_ctrl_command(ctrl, "WPS_PBC");
401 #ifdef CONFIG_WPS_OOB
402 static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc,
403                                    char *argv[])
405         char cmd[256];
406         int res;
408         if (argc != 3 && argc != 4) {
409                 printf("Invalid WPS_OOB command: need three or four "
410                        "arguments:\n"
411                        "- DEV_TYPE: use 'ufd' or 'nfc'\n"
412                        "- PATH: path of OOB device like '/mnt'\n"
413                        "- METHOD: OOB method 'pin-e' or 'pin-r', "
414                        "'cred'\n"
415                        "- DEV_NAME: (only for NFC) device name like "
416                        "'pn531'\n");
417                 return -1;
418         }
420         if (argc == 3)
421                 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
422                                   argv[0], argv[1], argv[2]);
423         else
424                 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
425                                   argv[0], argv[1], argv[2], argv[3]);
426         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
427                 printf("Too long WPS_OOB command.\n");
428                 return -1;
429         }
430         return wpa_ctrl_command(ctrl, cmd);
432 #endif /* CONFIG_WPS_OOB */
435 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
436                                       char *argv[])
438         char buf[64];
439         if (argc < 1) {
440                 printf("Invalid 'wps_ap_pin' command - at least one argument "
441                        "is required.\n");
442                 return -1;
443         }
444         if (argc > 2)
445                 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
446                          argv[0], argv[1], argv[2]);
447         else if (argc > 1)
448                 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
449                          argv[0], argv[1]);
450         else
451                 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
452         return wpa_ctrl_command(ctrl, buf);
456 static int hostapd_cli_cmd_wps_config(struct wpa_ctrl *ctrl, int argc,
457                                       char *argv[])
459         char buf[256];
460         char ssid_hex[2 * 32 + 1];
461         char key_hex[2 * 64 + 1];
462         int i;
464         if (argc < 1) {
465                 printf("Invalid 'wps_config' command - at least two arguments "
466                        "are required.\n");
467                 return -1;
468         }
470         ssid_hex[0] = '\0';
471         for (i = 0; i < 32; i++) {
472                 if (argv[0][i] == '\0')
473                         break;
474                 os_snprintf(&ssid_hex[i * 2], 3, "%02x", argv[0][i]);
475         }
477         key_hex[0] = '\0';
478         if (argc > 3) {
479                 for (i = 0; i < 64; i++) {
480                         if (argv[3][i] == '\0')
481                                 break;
482                         os_snprintf(&key_hex[i * 2], 3, "%02x",
483                                     argv[3][i]);
484                 }
485         }
487         if (argc > 3)
488                 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s %s",
489                          ssid_hex, argv[1], argv[2], key_hex);
490         else if (argc > 2)
491                 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s %s",
492                          ssid_hex, argv[1], argv[2]);
493         else
494                 snprintf(buf, sizeof(buf), "WPS_CONFIG %s %s",
495                          ssid_hex, argv[1]);
496         return wpa_ctrl_command(ctrl, buf);
498 #endif /* CONFIG_WPS */
501 static int hostapd_cli_cmd_ess_disassoc(struct wpa_ctrl *ctrl, int argc,
502                                         char *argv[])
504         char buf[300];
505         int res;
507         if (argc < 2) {
508                 printf("Invalid 'ess_disassoc' command - two arguments (STA "
509                        "addr and URL) are needed\n");
510                 return -1;
511         }
513         res = os_snprintf(buf, sizeof(buf), "ESS_DISASSOC %s %s",
514                           argv[0], argv[1]);
515         if (res < 0 || res >= (int) sizeof(buf))
516                 return -1;
517         return wpa_ctrl_command(ctrl, buf);
521 static int hostapd_cli_cmd_get_config(struct wpa_ctrl *ctrl, int argc,
522                                       char *argv[])
524         return wpa_ctrl_command(ctrl, "GET_CONFIG");
528 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
529                                 char *addr, size_t addr_len)
531         char buf[4096], *pos;
532         size_t len;
533         int ret;
535         if (ctrl_conn == NULL) {
536                 printf("Not connected to hostapd - command dropped.\n");
537                 return -1;
538         }
539         len = sizeof(buf) - 1;
540         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
541                                hostapd_cli_msg_cb);
542         if (ret == -2) {
543                 printf("'%s' command timed out.\n", cmd);
544                 return -2;
545         } else if (ret < 0) {
546                 printf("'%s' command failed.\n", cmd);
547                 return -1;
548         }
550         buf[len] = '\0';
551         if (memcmp(buf, "FAIL", 4) == 0)
552                 return -1;
553         printf("%s", buf);
555         pos = buf;
556         while (*pos != '\0' && *pos != '\n')
557                 pos++;
558         *pos = '\0';
559         os_strlcpy(addr, buf, addr_len);
560         return 0;
564 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
565                                    char *argv[])
567         char addr[32], cmd[64];
569         if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
570                 return 0;
571         do {
572                 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
573         } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
575         return -1;
579 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
581         printf("%s", commands_help);
582         return 0;
586 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
587                                    char *argv[])
589         printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
590         return 0;
594 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
596         hostapd_cli_quit = 1;
597         if (interactive)
598                 eloop_terminate();
599         return 0;
603 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
605         char cmd[256];
606         if (argc != 1) {
607                 printf("Invalid LEVEL command: needs one argument (debug "
608                        "level)\n");
609                 return 0;
610         }
611         snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
612         return wpa_ctrl_command(ctrl, cmd);
616 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
618         struct dirent *dent;
619         DIR *dir;
621         dir = opendir(ctrl_iface_dir);
622         if (dir == NULL) {
623                 printf("Control interface directory '%s' could not be "
624                        "openned.\n", ctrl_iface_dir);
625                 return;
626         }
628         printf("Available interfaces:\n");
629         while ((dent = readdir(dir))) {
630                 if (strcmp(dent->d_name, ".") == 0 ||
631                     strcmp(dent->d_name, "..") == 0)
632                         continue;
633                 printf("%s\n", dent->d_name);
634         }
635         closedir(dir);
639 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
640                                      char *argv[])
642         if (argc < 1) {
643                 hostapd_cli_list_interfaces(ctrl);
644                 return 0;
645         }
647         hostapd_cli_close_connection();
648         free(ctrl_ifname);
649         ctrl_ifname = strdup(argv[0]);
651         if (hostapd_cli_open_connection(ctrl_ifname)) {
652                 printf("Connected to interface '%s.\n", ctrl_ifname);
653                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
654                         hostapd_cli_attached = 1;
655                 } else {
656                         printf("Warning: Failed to attach to "
657                                "hostapd.\n");
658                 }
659         } else {
660                 printf("Could not connect to interface '%s' - re-trying\n",
661                         ctrl_ifname);
662         }
663         return 0;
667 static int hostapd_cli_cmd_set(struct wpa_ctrl *ctrl, int argc, char *argv[])
669         char cmd[256];
670         int res;
672         if (argc != 2) {
673                 printf("Invalid SET command: needs two arguments (variable "
674                        "name and value)\n");
675                 return -1;
676         }
678         res = os_snprintf(cmd, sizeof(cmd), "SET %s %s", argv[0], argv[1]);
679         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
680                 printf("Too long SET command.\n");
681                 return -1;
682         }
683         return wpa_ctrl_command(ctrl, cmd);
687 static int hostapd_cli_cmd_get(struct wpa_ctrl *ctrl, int argc, char *argv[])
689         char cmd[256];
690         int res;
692         if (argc != 1) {
693                 printf("Invalid GET command: needs one argument (variable "
694                        "name)\n");
695                 return -1;
696         }
698         res = os_snprintf(cmd, sizeof(cmd), "GET %s", argv[0]);
699         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
700                 printf("Too long GET command.\n");
701                 return -1;
702         }
703         return wpa_ctrl_command(ctrl, cmd);
707 struct hostapd_cli_cmd {
708         const char *cmd;
709         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
710 };
712 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
713         { "ping", hostapd_cli_cmd_ping },
714         { "mib", hostapd_cli_cmd_mib },
715         { "relog", hostapd_cli_cmd_relog },
716         { "sta", hostapd_cli_cmd_sta },
717         { "all_sta", hostapd_cli_cmd_all_sta },
718         { "new_sta", hostapd_cli_cmd_new_sta },
719         { "deauthenticate", hostapd_cli_cmd_deauthenticate },
720         { "disassociate", hostapd_cli_cmd_disassociate },
721 #ifdef CONFIG_IEEE80211W
722         { "sa_query", hostapd_cli_cmd_sa_query },
723 #endif /* CONFIG_IEEE80211W */
724 #ifdef CONFIG_WPS
725         { "wps_pin", hostapd_cli_cmd_wps_pin },
726         { "wps_check_pin", hostapd_cli_cmd_wps_check_pin },
727         { "wps_pbc", hostapd_cli_cmd_wps_pbc },
728 #ifdef CONFIG_WPS_OOB
729         { "wps_oob", hostapd_cli_cmd_wps_oob },
730 #endif /* CONFIG_WPS_OOB */
731         { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
732         { "wps_config", hostapd_cli_cmd_wps_config },
733 #endif /* CONFIG_WPS */
734         { "ess_disassoc", hostapd_cli_cmd_ess_disassoc },
735         { "get_config", hostapd_cli_cmd_get_config },
736         { "help", hostapd_cli_cmd_help },
737         { "interface", hostapd_cli_cmd_interface },
738         { "level", hostapd_cli_cmd_level },
739         { "license", hostapd_cli_cmd_license },
740         { "quit", hostapd_cli_cmd_quit },
741         { "set", hostapd_cli_cmd_set },
742         { "get", hostapd_cli_cmd_get },
743         { NULL, NULL }
744 };
747 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
749         struct hostapd_cli_cmd *cmd, *match = NULL;
750         int count;
752         count = 0;
753         cmd = hostapd_cli_commands;
754         while (cmd->cmd) {
755                 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
756                         match = cmd;
757                         if (os_strcasecmp(cmd->cmd, argv[0]) == 0) {
758                                 /* we have an exact match */
759                                 count = 1;
760                                 break;
761                         }
762                         count++;
763                 }
764                 cmd++;
765         }
767         if (count > 1) {
768                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
769                 cmd = hostapd_cli_commands;
770                 while (cmd->cmd) {
771                         if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
772                             0) {
773                                 printf(" %s", cmd->cmd);
774                         }
775                         cmd++;
776                 }
777                 printf("\n");
778         } else if (count == 0) {
779                 printf("Unknown command '%s'\n", argv[0]);
780         } else {
781                 match->handler(ctrl, argc - 1, &argv[1]);
782         }
786 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
787                                      int action_monitor)
789         int first = 1;
790         if (ctrl_conn == NULL)
791                 return;
792         while (wpa_ctrl_pending(ctrl)) {
793                 char buf[256];
794                 size_t len = sizeof(buf) - 1;
795                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
796                         buf[len] = '\0';
797                         if (action_monitor)
798                                 hostapd_cli_action_process(buf, len);
799                         else {
800                                 if (in_read && first)
801                                         printf("\n");
802                                 first = 0;
803                                 printf("%s\n", buf);
804                         }
805                 } else {
806                         printf("Could not read pending message.\n");
807                         break;
808                 }
809         }
813 #define max_args 10
815 static int tokenize_cmd(char *cmd, char *argv[])
817         char *pos;
818         int argc = 0;
820         pos = cmd;
821         for (;;) {
822                 while (*pos == ' ')
823                         pos++;
824                 if (*pos == '\0')
825                         break;
826                 argv[argc] = pos;
827                 argc++;
828                 if (argc == max_args)
829                         break;
830                 if (*pos == '"') {
831                         char *pos2 = os_strrchr(pos, '"');
832                         if (pos2)
833                                 pos = pos2 + 1;
834                 }
835                 while (*pos != '\0' && *pos != ' ')
836                         pos++;
837                 if (*pos == ' ')
838                         *pos++ = '\0';
839         }
841         return argc;
845 static void hostapd_cli_ping(void *eloop_ctx, void *timeout_ctx)
847         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
848                 printf("Connection to hostapd lost - trying to reconnect\n");
849                 hostapd_cli_close_connection();
850         }
851         if (!ctrl_conn) {
852                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
853                 if (ctrl_conn) {
854                         printf("Connection to hostapd re-established\n");
855                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
856                                 hostapd_cli_attached = 1;
857                         } else {
858                                 printf("Warning: Failed to attach to "
859                                        "hostapd.\n");
860                         }
861                 }
862         }
863         if (ctrl_conn)
864                 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
865         eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
869 static void hostapd_cli_eloop_terminate(int sig, void *signal_ctx)
871         eloop_terminate();
875 static void hostapd_cli_edit_cmd_cb(void *ctx, char *cmd)
877         char *argv[max_args];
878         int argc;
879         argc = tokenize_cmd(cmd, argv);
880         if (argc)
881                 wpa_request(ctrl_conn, argc, argv);
885 static void hostapd_cli_edit_eof_cb(void *ctx)
887         eloop_terminate();
891 static void hostapd_cli_interactive(void)
893         printf("\nInteractive mode\n\n");
895         eloop_register_signal_terminate(hostapd_cli_eloop_terminate, NULL);
896         edit_init(hostapd_cli_edit_cmd_cb, hostapd_cli_edit_eof_cb,
897                   NULL, NULL, NULL);
898         eloop_register_timeout(ping_interval, 0, hostapd_cli_ping, NULL, NULL);
900         eloop_run();
902         edit_deinit(NULL, NULL);
903         eloop_cancel_timeout(hostapd_cli_ping, NULL, NULL);
907 static void hostapd_cli_cleanup(void)
909         hostapd_cli_close_connection();
910         if (pid_file)
911                 os_daemonize_terminate(pid_file);
913         os_program_deinit();
917 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
919         fd_set rfds;
920         int fd, res;
921         struct timeval tv;
922         char buf[256];
923         size_t len;
925         fd = wpa_ctrl_get_fd(ctrl);
927         while (!hostapd_cli_quit) {
928                 FD_ZERO(&rfds);
929                 FD_SET(fd, &rfds);
930                 tv.tv_sec = ping_interval;
931                 tv.tv_usec = 0;
932                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
933                 if (res < 0 && errno != EINTR) {
934                         perror("select");
935                         break;
936                 }
938                 if (FD_ISSET(fd, &rfds))
939                         hostapd_cli_recv_pending(ctrl, 0, 1);
940                 else {
941                         len = sizeof(buf) - 1;
942                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
943                                              hostapd_cli_action_process) < 0 ||
944                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
945                                 printf("hostapd did not reply to PING "
946                                        "command - exiting\n");
947                                 break;
948                         }
949                 }
950         }
954 int main(int argc, char *argv[])
956         int warning_displayed = 0;
957         int c;
958         int daemonize = 0;
960         if (os_program_init())
961                 return -1;
963         for (;;) {
964                 c = getopt(argc, argv, "a:BhG:i:p:v");
965                 if (c < 0)
966                         break;
967                 switch (c) {
968                 case 'a':
969                         action_file = optarg;
970                         break;
971                 case 'B':
972                         daemonize = 1;
973                         break;
974                 case 'G':
975                         ping_interval = atoi(optarg);
976                         break;
977                 case 'h':
978                         usage();
979                         return 0;
980                 case 'v':
981                         printf("%s\n", hostapd_cli_version);
982                         return 0;
983                 case 'i':
984                         os_free(ctrl_ifname);
985                         ctrl_ifname = os_strdup(optarg);
986                         break;
987                 case 'p':
988                         ctrl_iface_dir = optarg;
989                         break;
990                 default:
991                         usage();
992                         return -1;
993                 }
994         }
996         interactive = (argc == optind) && (action_file == NULL);
998         if (interactive) {
999                 printf("%s\n\n%s\n\n", hostapd_cli_version,
1000                        hostapd_cli_license);
1001         }
1003         if (eloop_init())
1004                 return -1;
1006         for (;;) {
1007                 if (ctrl_ifname == NULL) {
1008                         struct dirent *dent;
1009                         DIR *dir = opendir(ctrl_iface_dir);
1010                         if (dir) {
1011                                 while ((dent = readdir(dir))) {
1012                                         if (os_strcmp(dent->d_name, ".") == 0
1013                                             ||
1014                                             os_strcmp(dent->d_name, "..") == 0)
1015                                                 continue;
1016                                         printf("Selected interface '%s'\n",
1017                                                dent->d_name);
1018                                         ctrl_ifname = os_strdup(dent->d_name);
1019                                         break;
1020                                 }
1021                                 closedir(dir);
1022                         }
1023                 }
1024                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
1025                 if (ctrl_conn) {
1026                         if (warning_displayed)
1027                                 printf("Connection established.\n");
1028                         break;
1029                 }
1031                 if (!interactive) {
1032                         perror("Failed to connect to hostapd - "
1033                                "wpa_ctrl_open");
1034                         return -1;
1035                 }
1037                 if (!warning_displayed) {
1038                         printf("Could not connect to hostapd - re-trying\n");
1039                         warning_displayed = 1;
1040                 }
1041                 os_sleep(1, 0);
1042                 continue;
1043         }
1045         if (interactive || action_file) {
1046                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
1047                         hostapd_cli_attached = 1;
1048                 } else {
1049                         printf("Warning: Failed to attach to hostapd.\n");
1050                         if (action_file)
1051                                 return -1;
1052                 }
1053         }
1055         if (daemonize && os_daemonize(pid_file))
1056                 return -1;
1058         if (interactive)
1059                 hostapd_cli_interactive();
1060         else if (action_file)
1061                 hostapd_cli_action(ctrl_conn);
1062         else
1063                 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
1065         os_free(ctrl_ifname);
1066         eloop_destroy();
1067         hostapd_cli_cleanup();
1068         return 0;