2 * hostapd - command line interface for hostapd daemon
3 * Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
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.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
18 #include "common/wpa_ctrl.h"
20 #include "common/version.h"
23 static const char *hostapd_cli_version
=
24 "hostapd_cli v" VERSION_STR
"\n"
25 "Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi> and contributors";
28 static const char *hostapd_cli_license
=
29 "This program is free software. You can distribute it and/or modify it\n"
30 "under the terms of the GNU General Public License version 2.\n"
32 "Alternatively, this software may be distributed under the terms of the\n"
33 "BSD license. See README and COPYING for more details.\n";
35 static const char *hostapd_cli_full_license
=
36 "This program is free software; you can redistribute it and/or modify\n"
37 "it under the terms of the GNU General Public License version 2 as\n"
38 "published by the Free Software Foundation.\n"
40 "This program is distributed in the hope that it will be useful,\n"
41 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
42 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
43 "GNU General Public License for more details.\n"
45 "You should have received a copy of the GNU General Public License\n"
46 "along with this program; if not, write to the Free Software\n"
47 "Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\n"
49 "Alternatively, this software may be distributed under the terms of the\n"
52 "Redistribution and use in source and binary forms, with or without\n"
53 "modification, are permitted provided that the following conditions are\n"
56 "1. Redistributions of source code must retain the above copyright\n"
57 " notice, this list of conditions and the following disclaimer.\n"
59 "2. Redistributions in binary form must reproduce the above copyright\n"
60 " notice, this list of conditions and the following disclaimer in the\n"
61 " documentation and/or other materials provided with the distribution.\n"
63 "3. Neither the name(s) of the above-listed copyright holder(s) nor the\n"
64 " names of its contributors may be used to endorse or promote products\n"
65 " derived from this software without specific prior written permission.\n"
67 "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n"
68 "\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n"
69 "LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n"
70 "A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n"
71 "OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n"
72 "SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n"
73 "LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n"
74 "DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n"
75 "THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n"
76 "(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n"
77 "OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
80 static const char *commands_help
=
82 " mib get MIB variables (dot1x, dot11, radius)\n"
83 " sta <addr> get MIB variables for one station\n"
84 " all_sta get MIB variables for all stations\n"
85 " new_sta <addr> add a new station\n"
86 #ifdef CONFIG_IEEE80211W
87 " sa_query <addr> send SA Query to a station\n"
88 #endif /* CONFIG_IEEE80211W */
90 " wps_pin <uuid> <pin> [timeout] add WPS Enrollee PIN (Device Password)\n"
91 " wps_pbc indicate button pushed to initiate PBC\n"
93 " wps_oob <type> <path> <method> use WPS with out-of-band (UFD)\n"
94 #endif /* CONFIG_WPS_OOB */
95 #endif /* CONFIG_WPS */
96 " help show this usage help\n"
97 " interface [ifname] show interfaces/select interface\n"
98 " level <debug level> change debug level\n"
99 " license show full hostapd_cli license\n"
100 " quit exit hostapd_cli\n";
102 static struct wpa_ctrl
*ctrl_conn
;
103 static int hostapd_cli_quit
= 0;
104 static int hostapd_cli_attached
= 0;
105 static const char *ctrl_iface_dir
= "/var/run/hostapd";
106 static char *ctrl_ifname
= NULL
;
107 static int ping_interval
= 5;
110 static void usage(void)
112 fprintf(stderr
, "%s\n", hostapd_cli_version
);
115 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hv] "
116 "[-G<ping interval>] \\\n"
120 " -h help (show this usage text)\n"
121 " -v shown version information\n"
122 " -p<path> path to find control sockets (default: "
123 "/var/run/hostapd)\n"
124 " -i<ifname> Interface to listen on (default: first "
125 "interface found in the\n"
132 static struct wpa_ctrl
* hostapd_cli_open_connection(const char *ifname
)
140 flen
= strlen(ctrl_iface_dir
) + strlen(ifname
) + 2;
141 cfile
= malloc(flen
);
144 snprintf(cfile
, flen
, "%s/%s", ctrl_iface_dir
, ifname
);
146 ctrl_conn
= wpa_ctrl_open(cfile
);
152 static void hostapd_cli_close_connection(void)
154 if (ctrl_conn
== NULL
)
157 if (hostapd_cli_attached
) {
158 wpa_ctrl_detach(ctrl_conn
);
159 hostapd_cli_attached
= 0;
161 wpa_ctrl_close(ctrl_conn
);
166 static void hostapd_cli_msg_cb(char *msg
, size_t len
)
172 static int _wpa_ctrl_command(struct wpa_ctrl
*ctrl
, char *cmd
, int print
)
178 if (ctrl_conn
== NULL
) {
179 printf("Not connected to hostapd - command dropped.\n");
182 len
= sizeof(buf
) - 1;
183 ret
= wpa_ctrl_request(ctrl
, cmd
, strlen(cmd
), buf
, &len
,
186 printf("'%s' command timed out.\n", cmd
);
188 } else if (ret
< 0) {
189 printf("'%s' command failed.\n", cmd
);
200 static inline int wpa_ctrl_command(struct wpa_ctrl
*ctrl
, char *cmd
)
202 return _wpa_ctrl_command(ctrl
, cmd
, 1);
206 static int hostapd_cli_cmd_ping(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
208 return wpa_ctrl_command(ctrl
, "PING");
212 static int hostapd_cli_cmd_mib(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
214 return wpa_ctrl_command(ctrl
, "MIB");
218 static int hostapd_cli_cmd_sta(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
222 printf("Invalid 'sta' command - exactly one argument, STA "
223 "address, is required.\n");
226 snprintf(buf
, sizeof(buf
), "STA %s", argv
[0]);
227 return wpa_ctrl_command(ctrl
, buf
);
231 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl
*ctrl
, int argc
,
236 printf("Invalid 'new_sta' command - exactly one argument, STA "
237 "address, is required.\n");
240 snprintf(buf
, sizeof(buf
), "NEW_STA %s", argv
[0]);
241 return wpa_ctrl_command(ctrl
, buf
);
245 #ifdef CONFIG_IEEE80211W
246 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl
*ctrl
, int argc
,
251 printf("Invalid 'sa_query' command - exactly one argument, "
252 "STA address, is required.\n");
255 snprintf(buf
, sizeof(buf
), "SA_QUERY %s", argv
[0]);
256 return wpa_ctrl_command(ctrl
, buf
);
258 #endif /* CONFIG_IEEE80211W */
262 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl
*ctrl
, int argc
,
267 printf("Invalid 'wps_pin' command - at least two arguments, "
268 "UUID and PIN, are required.\n");
272 snprintf(buf
, sizeof(buf
), "WPS_PIN %s %s %s",
273 argv
[0], argv
[1], argv
[2]);
275 snprintf(buf
, sizeof(buf
), "WPS_PIN %s %s", argv
[0], argv
[1]);
276 return wpa_ctrl_command(ctrl
, buf
);
280 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl
*ctrl
, int argc
,
283 return wpa_ctrl_command(ctrl
, "WPS_PBC");
287 #ifdef CONFIG_WPS_OOB
288 static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl
*ctrl
, int argc
,
294 if (argc
!= 3 && argc
!= 4) {
295 printf("Invalid WPS_OOB command: need three or four "
297 "- DEV_TYPE: use 'ufd' or 'nfc'\n"
298 "- PATH: path of OOB device like '/mnt'\n"
299 "- METHOD: OOB method 'pin-e' or 'pin-r', "
301 "- DEV_NAME: (only for NFC) device name like "
307 res
= os_snprintf(cmd
, sizeof(cmd
), "WPS_OOB %s %s %s",
308 argv
[0], argv
[1], argv
[2]);
310 res
= os_snprintf(cmd
, sizeof(cmd
), "WPS_OOB %s %s %s %s",
311 argv
[0], argv
[1], argv
[2], argv
[3]);
312 if (res
< 0 || (size_t) res
>= sizeof(cmd
) - 1) {
313 printf("Too long WPS_OOB command.\n");
316 return wpa_ctrl_command(ctrl
, cmd
);
318 #endif /* CONFIG_WPS_OOB */
319 #endif /* CONFIG_WPS */
322 static int wpa_ctrl_command_sta(struct wpa_ctrl
*ctrl
, char *cmd
,
323 char *addr
, size_t addr_len
)
325 char buf
[4096], *pos
;
329 if (ctrl_conn
== NULL
) {
330 printf("Not connected to hostapd - command dropped.\n");
333 len
= sizeof(buf
) - 1;
334 ret
= wpa_ctrl_request(ctrl
, cmd
, strlen(cmd
), buf
, &len
,
337 printf("'%s' command timed out.\n", cmd
);
339 } else if (ret
< 0) {
340 printf("'%s' command failed.\n", cmd
);
345 if (memcmp(buf
, "FAIL", 4) == 0)
350 while (*pos
!= '\0' && *pos
!= '\n')
353 os_strlcpy(addr
, buf
, addr_len
);
358 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl
*ctrl
, int argc
,
361 char addr
[32], cmd
[64];
363 if (wpa_ctrl_command_sta(ctrl
, "STA-FIRST", addr
, sizeof(addr
)))
366 snprintf(cmd
, sizeof(cmd
), "STA-NEXT %s", addr
);
367 } while (wpa_ctrl_command_sta(ctrl
, cmd
, addr
, sizeof(addr
)) == 0);
373 static int hostapd_cli_cmd_help(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
375 printf("%s", commands_help
);
380 static int hostapd_cli_cmd_license(struct wpa_ctrl
*ctrl
, int argc
,
383 printf("%s\n\n%s\n", hostapd_cli_version
, hostapd_cli_full_license
);
388 static int hostapd_cli_cmd_quit(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
390 hostapd_cli_quit
= 1;
395 static int hostapd_cli_cmd_level(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
399 printf("Invalid LEVEL command: needs one argument (debug "
403 snprintf(cmd
, sizeof(cmd
), "LEVEL %s", argv
[0]);
404 return wpa_ctrl_command(ctrl
, cmd
);
408 static void hostapd_cli_list_interfaces(struct wpa_ctrl
*ctrl
)
413 dir
= opendir(ctrl_iface_dir
);
415 printf("Control interface directory '%s' could not be "
416 "openned.\n", ctrl_iface_dir
);
420 printf("Available interfaces:\n");
421 while ((dent
= readdir(dir
))) {
422 if (strcmp(dent
->d_name
, ".") == 0 ||
423 strcmp(dent
->d_name
, "..") == 0)
425 printf("%s\n", dent
->d_name
);
431 static int hostapd_cli_cmd_interface(struct wpa_ctrl
*ctrl
, int argc
,
435 hostapd_cli_list_interfaces(ctrl
);
439 hostapd_cli_close_connection();
441 ctrl_ifname
= strdup(argv
[0]);
443 if (hostapd_cli_open_connection(ctrl_ifname
)) {
444 printf("Connected to interface '%s.\n", ctrl_ifname
);
445 if (wpa_ctrl_attach(ctrl_conn
) == 0) {
446 hostapd_cli_attached
= 1;
448 printf("Warning: Failed to attach to "
452 printf("Could not connect to interface '%s' - re-trying\n",
459 struct hostapd_cli_cmd
{
461 int (*handler
)(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[]);
464 static struct hostapd_cli_cmd hostapd_cli_commands
[] = {
465 { "ping", hostapd_cli_cmd_ping
},
466 { "mib", hostapd_cli_cmd_mib
},
467 { "sta", hostapd_cli_cmd_sta
},
468 { "all_sta", hostapd_cli_cmd_all_sta
},
469 { "new_sta", hostapd_cli_cmd_new_sta
},
470 #ifdef CONFIG_IEEE80211W
471 { "sa_query", hostapd_cli_cmd_sa_query
},
472 #endif /* CONFIG_IEEE80211W */
474 { "wps_pin", hostapd_cli_cmd_wps_pin
},
475 { "wps_pbc", hostapd_cli_cmd_wps_pbc
},
476 #ifdef CONFIG_WPS_OOB
477 { "wps_oob", hostapd_cli_cmd_wps_oob
},
478 #endif /* CONFIG_WPS_OOB */
479 #endif /* CONFIG_WPS */
480 { "help", hostapd_cli_cmd_help
},
481 { "interface", hostapd_cli_cmd_interface
},
482 { "level", hostapd_cli_cmd_level
},
483 { "license", hostapd_cli_cmd_license
},
484 { "quit", hostapd_cli_cmd_quit
},
489 static void wpa_request(struct wpa_ctrl
*ctrl
, int argc
, char *argv
[])
491 struct hostapd_cli_cmd
*cmd
, *match
= NULL
;
495 cmd
= hostapd_cli_commands
;
497 if (strncasecmp(cmd
->cmd
, argv
[0], strlen(argv
[0])) == 0) {
505 printf("Ambiguous command '%s'; possible commands:", argv
[0]);
506 cmd
= hostapd_cli_commands
;
508 if (strncasecmp(cmd
->cmd
, argv
[0], strlen(argv
[0])) ==
510 printf(" %s", cmd
->cmd
);
515 } else if (count
== 0) {
516 printf("Unknown command '%s'\n", argv
[0]);
518 match
->handler(ctrl
, argc
- 1, &argv
[1]);
523 static void hostapd_cli_recv_pending(struct wpa_ctrl
*ctrl
, int in_read
)
526 if (ctrl_conn
== NULL
)
528 while (wpa_ctrl_pending(ctrl
)) {
530 size_t len
= sizeof(buf
) - 1;
531 if (wpa_ctrl_recv(ctrl
, buf
, &len
) == 0) {
533 if (in_read
&& first
)
538 printf("Could not read pending message.\n");
545 static void hostapd_cli_interactive(void)
547 const int max_args
= 10;
548 char cmd
[256], *res
, *argv
[max_args
], *pos
;
551 printf("\nInteractive mode\n\n");
554 hostapd_cli_recv_pending(ctrl_conn
, 0);
556 alarm(ping_interval
);
557 res
= fgets(cmd
, sizeof(cmd
), stdin
);
562 while (*pos
!= '\0') {
578 if (argc
== max_args
)
580 while (*pos
!= '\0' && *pos
!= ' ')
586 wpa_request(ctrl_conn
, argc
, argv
);
587 } while (!hostapd_cli_quit
);
591 static void hostapd_cli_terminate(int sig
)
593 hostapd_cli_close_connection();
598 static void hostapd_cli_alarm(int sig
)
600 if (ctrl_conn
&& _wpa_ctrl_command(ctrl_conn
, "PING", 0)) {
601 printf("Connection to hostapd lost - trying to reconnect\n");
602 hostapd_cli_close_connection();
605 ctrl_conn
= hostapd_cli_open_connection(ctrl_ifname
);
607 printf("Connection to hostapd re-established\n");
608 if (wpa_ctrl_attach(ctrl_conn
) == 0) {
609 hostapd_cli_attached
= 1;
611 printf("Warning: Failed to attach to "
617 hostapd_cli_recv_pending(ctrl_conn
, 1);
618 alarm(ping_interval
);
622 int main(int argc
, char *argv
[])
625 int warning_displayed
= 0;
628 if (os_program_init())
632 c
= getopt(argc
, argv
, "hG:i:p:v");
637 ping_interval
= atoi(optarg
);
643 printf("%s\n", hostapd_cli_version
);
647 ctrl_ifname
= strdup(optarg
);
650 ctrl_iface_dir
= optarg
;
658 interactive
= argc
== optind
;
661 printf("%s\n\n%s\n\n", hostapd_cli_version
,
662 hostapd_cli_license
);
666 if (ctrl_ifname
== NULL
) {
668 DIR *dir
= opendir(ctrl_iface_dir
);
670 while ((dent
= readdir(dir
))) {
671 if (strcmp(dent
->d_name
, ".") == 0 ||
672 strcmp(dent
->d_name
, "..") == 0)
674 printf("Selected interface '%s'\n",
676 ctrl_ifname
= strdup(dent
->d_name
);
682 ctrl_conn
= hostapd_cli_open_connection(ctrl_ifname
);
684 if (warning_displayed
)
685 printf("Connection established.\n");
690 perror("Failed to connect to hostapd - "
695 if (!warning_displayed
) {
696 printf("Could not connect to hostapd - re-trying\n");
697 warning_displayed
= 1;
703 signal(SIGINT
, hostapd_cli_terminate
);
704 signal(SIGTERM
, hostapd_cli_terminate
);
705 signal(SIGALRM
, hostapd_cli_alarm
);
708 if (wpa_ctrl_attach(ctrl_conn
) == 0) {
709 hostapd_cli_attached
= 1;
711 printf("Warning: Failed to attach to hostapd.\n");
713 hostapd_cli_interactive();
715 wpa_request(ctrl_conn
, argc
- optind
, &argv
[optind
]);
718 hostapd_cli_close_connection();