]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - build-utilities/hostap.git/blob - hostapd/hostapd_cli.c
Add support for action scripts in hostapd_cli
[build-utilities/hostap.git] / hostapd / hostapd_cli.c
1 /*
2  * hostapd - command line interface for hostapd daemon
3  * Copyright (c) 2004-2010, 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 "common.h"
20 #include "common/version.h"
23 static const char *hostapd_cli_version =
24 "hostapd_cli v" VERSION_STR "\n"
25 "Copyright (c) 2004-2010, 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"
31 "\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"
39 "\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"
44 "\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"
48 "\n"
49 "Alternatively, this software may be distributed under the terms of the\n"
50 "BSD license.\n"
51 "\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"
54 "met:\n"
55 "\n"
56 "1. Redistributions of source code must retain the above copyright\n"
57 "   notice, this list of conditions and the following disclaimer.\n"
58 "\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"
62 "\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"
66 "\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"
78 "\n";
80 static const char *commands_help =
81 "Commands:\n"
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 */
89 #ifdef CONFIG_WPS
90 "   wps_pin <uuid> <pin> [timeout]  add WPS Enrollee PIN (Device Password)\n"
91 "   wps_pbc              indicate button pushed to initiate PBC\n"
92 #ifdef CONFIG_WPS_OOB
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 const char *pid_file = NULL;
108 static const char *action_file = NULL;
109 static int ping_interval = 5;
112 static void usage(void)
114         fprintf(stderr, "%s\n", hostapd_cli_version);
115         fprintf(stderr,
116                 "\n"
117                 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
118                 "[-a<path>] \\\n"
119                 "                   [-G<ping interval>] [command..]\n"
120                 "\n"
121                 "Options:\n"
122                 "   -h           help (show this usage text)\n"
123                 "   -v           shown version information\n"
124                 "   -p<path>     path to find control sockets (default: "
125                 "/var/run/hostapd)\n"
126                 "   -a<file>     run in daemon mode executing the action file "
127                 "based on events\n"
128                 "                from hostapd\n"
129                 "   -B           run a daemon in the background\n"
130                 "   -i<ifname>   Interface to listen on (default: first "
131                 "interface found in the\n"
132                 "                socket path)\n\n"
133                 "%s",
134                 commands_help);
138 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
140         char *cfile;
141         int flen;
143         if (ifname == NULL)
144                 return NULL;
146         flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
147         cfile = malloc(flen);
148         if (cfile == NULL)
149                 return NULL;
150         snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
152         ctrl_conn = wpa_ctrl_open(cfile);
153         free(cfile);
154         return ctrl_conn;
158 static void hostapd_cli_close_connection(void)
160         if (ctrl_conn == NULL)
161                 return;
163         if (hostapd_cli_attached) {
164                 wpa_ctrl_detach(ctrl_conn);
165                 hostapd_cli_attached = 0;
166         }
167         wpa_ctrl_close(ctrl_conn);
168         ctrl_conn = NULL;
172 static void hostapd_cli_msg_cb(char *msg, size_t len)
174         printf("%s\n", msg);
178 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
180         char buf[4096];
181         size_t len;
182         int ret;
184         if (ctrl_conn == NULL) {
185                 printf("Not connected to hostapd - command dropped.\n");
186                 return -1;
187         }
188         len = sizeof(buf) - 1;
189         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
190                                hostapd_cli_msg_cb);
191         if (ret == -2) {
192                 printf("'%s' command timed out.\n", cmd);
193                 return -2;
194         } else if (ret < 0) {
195                 printf("'%s' command failed.\n", cmd);
196                 return -1;
197         }
198         if (print) {
199                 buf[len] = '\0';
200                 printf("%s", buf);
201         }
202         return 0;
206 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
208         return _wpa_ctrl_command(ctrl, cmd, 1);
212 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
214         return wpa_ctrl_command(ctrl, "PING");
218 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
220         return wpa_ctrl_command(ctrl, "MIB");
224 static int hostapd_cli_exec(const char *program, const char *arg1,
225                             const char *arg2)
227         char *cmd;
228         size_t len;
229         int res;
230         int ret = 0;
232         len = os_strlen(program) + os_strlen(arg1) + os_strlen(arg2) + 3;
233         cmd = os_malloc(len);
234         if (cmd == NULL)
235                 return -1;
236         res = os_snprintf(cmd, len, "%s %s %s", program, arg1, arg2);
237         if (res < 0 || (size_t) res >= len) {
238                 os_free(cmd);
239                 return -1;
240         }
241         cmd[len - 1] = '\0';
242 #ifndef _WIN32_WCE
243         if (system(cmd) < 0)
244                 ret = -1;
245 #endif /* _WIN32_WCE */
246         os_free(cmd);
248         return ret;
252 static void hostapd_cli_action_process(char *msg, size_t len)
254         const char *pos;
256         pos = msg;
257         if (*pos == '<') {
258                 pos = os_strchr(pos, '>');
259                 if (pos)
260                         pos++;
261                 else
262                         pos = msg;
263         }
265         hostapd_cli_exec(action_file, ctrl_ifname, pos);
269 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
271         char buf[64];
272         if (argc != 1) {
273                 printf("Invalid 'sta' command - exactly one argument, STA "
274                        "address, is required.\n");
275                 return -1;
276         }
277         snprintf(buf, sizeof(buf), "STA %s", argv[0]);
278         return wpa_ctrl_command(ctrl, buf);
282 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
283                                    char *argv[])
285         char buf[64];
286         if (argc != 1) {
287                 printf("Invalid 'new_sta' command - exactly one argument, STA "
288                        "address, is required.\n");
289                 return -1;
290         }
291         snprintf(buf, sizeof(buf), "NEW_STA %s", argv[0]);
292         return wpa_ctrl_command(ctrl, buf);
296 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
297                                           char *argv[])
299         char buf[64];
300         if (argc < 1) {
301                 printf("Invalid 'deauthenticate' command - exactly one "
302                        "argument, STA address, is required.\n");
303                 return -1;
304         }
305         if (argc > 1)
306                 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s %s",
307                             argv[0], argv[1]);
308         else
309                 os_snprintf(buf, sizeof(buf), "DEAUTHENTICATE %s", argv[0]);
310         return wpa_ctrl_command(ctrl, buf);
314 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
315                                         char *argv[])
317         char buf[64];
318         if (argc < 1) {
319                 printf("Invalid 'disassociate' command - exactly one "
320                        "argument, STA address, is required.\n");
321                 return -1;
322         }
323         if (argc > 1)
324                 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s %s",
325                             argv[0], argv[1]);
326         else
327                 os_snprintf(buf, sizeof(buf), "DISASSOCIATE %s", argv[0]);
328         return wpa_ctrl_command(ctrl, buf);
332 #ifdef CONFIG_IEEE80211W
333 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
334                                     char *argv[])
336         char buf[64];
337         if (argc != 1) {
338                 printf("Invalid 'sa_query' command - exactly one argument, "
339                        "STA address, is required.\n");
340                 return -1;
341         }
342         snprintf(buf, sizeof(buf), "SA_QUERY %s", argv[0]);
343         return wpa_ctrl_command(ctrl, buf);
345 #endif /* CONFIG_IEEE80211W */
348 #ifdef CONFIG_WPS
349 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
350                                    char *argv[])
352         char buf[64];
353         if (argc < 2) {
354                 printf("Invalid 'wps_pin' command - at least two arguments, "
355                        "UUID and PIN, are required.\n");
356                 return -1;
357         }
358         if (argc > 2)
359                 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
360                          argv[0], argv[1], argv[2]);
361         else
362                 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
363         return wpa_ctrl_command(ctrl, buf);
367 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
368                                    char *argv[])
370         return wpa_ctrl_command(ctrl, "WPS_PBC");
374 #ifdef CONFIG_WPS_OOB
375 static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc,
376                                    char *argv[])
378         char cmd[256];
379         int res;
381         if (argc != 3 && argc != 4) {
382                 printf("Invalid WPS_OOB command: need three or four "
383                        "arguments:\n"
384                        "- DEV_TYPE: use 'ufd' or 'nfc'\n"
385                        "- PATH: path of OOB device like '/mnt'\n"
386                        "- METHOD: OOB method 'pin-e' or 'pin-r', "
387                        "'cred'\n"
388                        "- DEV_NAME: (only for NFC) device name like "
389                        "'pn531'\n");
390                 return -1;
391         }
393         if (argc == 3)
394                 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
395                                   argv[0], argv[1], argv[2]);
396         else
397                 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
398                                   argv[0], argv[1], argv[2], argv[3]);
399         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
400                 printf("Too long WPS_OOB command.\n");
401                 return -1;
402         }
403         return wpa_ctrl_command(ctrl, cmd);
405 #endif /* CONFIG_WPS_OOB */
406 #endif /* CONFIG_WPS */
409 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
410                                 char *addr, size_t addr_len)
412         char buf[4096], *pos;
413         size_t len;
414         int ret;
416         if (ctrl_conn == NULL) {
417                 printf("Not connected to hostapd - command dropped.\n");
418                 return -1;
419         }
420         len = sizeof(buf) - 1;
421         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
422                                hostapd_cli_msg_cb);
423         if (ret == -2) {
424                 printf("'%s' command timed out.\n", cmd);
425                 return -2;
426         } else if (ret < 0) {
427                 printf("'%s' command failed.\n", cmd);
428                 return -1;
429         }
431         buf[len] = '\0';
432         if (memcmp(buf, "FAIL", 4) == 0)
433                 return -1;
434         printf("%s", buf);
436         pos = buf;
437         while (*pos != '\0' && *pos != '\n')
438                 pos++;
439         *pos = '\0';
440         os_strlcpy(addr, buf, addr_len);
441         return 0;
445 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
446                                    char *argv[])
448         char addr[32], cmd[64];
450         if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
451                 return 0;
452         do {
453                 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
454         } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
456         return -1;
460 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
462         printf("%s", commands_help);
463         return 0;
467 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
468                                    char *argv[])
470         printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
471         return 0;
475 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
477         hostapd_cli_quit = 1;
478         return 0;
482 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
484         char cmd[256];
485         if (argc != 1) {
486                 printf("Invalid LEVEL command: needs one argument (debug "
487                        "level)\n");
488                 return 0;
489         }
490         snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
491         return wpa_ctrl_command(ctrl, cmd);
495 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
497         struct dirent *dent;
498         DIR *dir;
500         dir = opendir(ctrl_iface_dir);
501         if (dir == NULL) {
502                 printf("Control interface directory '%s' could not be "
503                        "openned.\n", ctrl_iface_dir);
504                 return;
505         }
507         printf("Available interfaces:\n");
508         while ((dent = readdir(dir))) {
509                 if (strcmp(dent->d_name, ".") == 0 ||
510                     strcmp(dent->d_name, "..") == 0)
511                         continue;
512                 printf("%s\n", dent->d_name);
513         }
514         closedir(dir);
518 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
519                                      char *argv[])
521         if (argc < 1) {
522                 hostapd_cli_list_interfaces(ctrl);
523                 return 0;
524         }
526         hostapd_cli_close_connection();
527         free(ctrl_ifname);
528         ctrl_ifname = strdup(argv[0]);
530         if (hostapd_cli_open_connection(ctrl_ifname)) {
531                 printf("Connected to interface '%s.\n", ctrl_ifname);
532                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
533                         hostapd_cli_attached = 1;
534                 } else {
535                         printf("Warning: Failed to attach to "
536                                "hostapd.\n");
537                 }
538         } else {
539                 printf("Could not connect to interface '%s' - re-trying\n",
540                         ctrl_ifname);
541         }
542         return 0;
546 struct hostapd_cli_cmd {
547         const char *cmd;
548         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
549 };
551 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
552         { "ping", hostapd_cli_cmd_ping },
553         { "mib", hostapd_cli_cmd_mib },
554         { "sta", hostapd_cli_cmd_sta },
555         { "all_sta", hostapd_cli_cmd_all_sta },
556         { "new_sta", hostapd_cli_cmd_new_sta },
557         { "deauthenticate", hostapd_cli_cmd_deauthenticate },
558         { "disassociate", hostapd_cli_cmd_disassociate },
559 #ifdef CONFIG_IEEE80211W
560         { "sa_query", hostapd_cli_cmd_sa_query },
561 #endif /* CONFIG_IEEE80211W */
562 #ifdef CONFIG_WPS
563         { "wps_pin", hostapd_cli_cmd_wps_pin },
564         { "wps_pbc", hostapd_cli_cmd_wps_pbc },
565 #ifdef CONFIG_WPS_OOB
566         { "wps_oob", hostapd_cli_cmd_wps_oob },
567 #endif /* CONFIG_WPS_OOB */
568 #endif /* CONFIG_WPS */
569         { "help", hostapd_cli_cmd_help },
570         { "interface", hostapd_cli_cmd_interface },
571         { "level", hostapd_cli_cmd_level },
572         { "license", hostapd_cli_cmd_license },
573         { "quit", hostapd_cli_cmd_quit },
574         { NULL, NULL }
575 };
578 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
580         struct hostapd_cli_cmd *cmd, *match = NULL;
581         int count;
583         count = 0;
584         cmd = hostapd_cli_commands;
585         while (cmd->cmd) {
586                 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
587                         match = cmd;
588                         count++;
589                 }
590                 cmd++;
591         }
593         if (count > 1) {
594                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
595                 cmd = hostapd_cli_commands;
596                 while (cmd->cmd) {
597                         if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
598                             0) {
599                                 printf(" %s", cmd->cmd);
600                         }
601                         cmd++;
602                 }
603                 printf("\n");
604         } else if (count == 0) {
605                 printf("Unknown command '%s'\n", argv[0]);
606         } else {
607                 match->handler(ctrl, argc - 1, &argv[1]);
608         }
612 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
613                                      int action_monitor)
615         int first = 1;
616         if (ctrl_conn == NULL)
617                 return;
618         while (wpa_ctrl_pending(ctrl)) {
619                 char buf[256];
620                 size_t len = sizeof(buf) - 1;
621                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
622                         buf[len] = '\0';
623                         if (action_monitor)
624                                 hostapd_cli_action_process(buf, len);
625                         else {
626                                 if (in_read && first)
627                                         printf("\n");
628                                 first = 0;
629                                 printf("%s\n", buf);
630                         }
631                 } else {
632                         printf("Could not read pending message.\n");
633                         break;
634                 }
635         }
639 static void hostapd_cli_interactive(void)
641         const int max_args = 10;
642         char cmd[256], *res, *argv[max_args], *pos;
643         int argc;
645         printf("\nInteractive mode\n\n");
647         do {
648                 hostapd_cli_recv_pending(ctrl_conn, 0, 0);
649                 printf("> ");
650                 alarm(ping_interval);
651                 res = fgets(cmd, sizeof(cmd), stdin);
652                 alarm(0);
653                 if (res == NULL)
654                         break;
655                 pos = cmd;
656                 while (*pos != '\0') {
657                         if (*pos == '\n') {
658                                 *pos = '\0';
659                                 break;
660                         }
661                         pos++;
662                 }
663                 argc = 0;
664                 pos = cmd;
665                 for (;;) {
666                         while (*pos == ' ')
667                                 pos++;
668                         if (*pos == '\0')
669                                 break;
670                         argv[argc] = pos;
671                         argc++;
672                         if (argc == max_args)
673                                 break;
674                         while (*pos != '\0' && *pos != ' ')
675                                 pos++;
676                         if (*pos == ' ')
677                                 *pos++ = '\0';
678                 }
679                 if (argc)
680                         wpa_request(ctrl_conn, argc, argv);
681         } while (!hostapd_cli_quit);
685 static void hostapd_cli_cleanup(void)
687         hostapd_cli_close_connection();
688         if (pid_file)
689                 os_daemonize_terminate(pid_file);
691         os_program_deinit();
695 static void hostapd_cli_terminate(int sig)
697         hostapd_cli_cleanup();
698         exit(0);
702 static void hostapd_cli_alarm(int sig)
704         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
705                 printf("Connection to hostapd lost - trying to reconnect\n");
706                 hostapd_cli_close_connection();
707         }
708         if (!ctrl_conn) {
709                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
710                 if (ctrl_conn) {
711                         printf("Connection to hostapd re-established\n");
712                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
713                                 hostapd_cli_attached = 1;
714                         } else {
715                                 printf("Warning: Failed to attach to "
716                                        "hostapd.\n");
717                         }
718                 }
719         }
720         if (ctrl_conn)
721                 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
722         alarm(ping_interval);
726 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
728         fd_set rfds;
729         int fd, res;
730         struct timeval tv;
731         char buf[256];
732         size_t len;
734         fd = wpa_ctrl_get_fd(ctrl);
736         while (!hostapd_cli_quit) {
737                 FD_ZERO(&rfds);
738                 FD_SET(fd, &rfds);
739                 tv.tv_sec = ping_interval;
740                 tv.tv_usec = 0;
741                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
742                 if (res < 0 && errno != EINTR) {
743                         perror("select");
744                         break;
745                 }
747                 if (FD_ISSET(fd, &rfds))
748                         hostapd_cli_recv_pending(ctrl, 0, 1);
749                 else {
750                         len = sizeof(buf) - 1;
751                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
752                                              hostapd_cli_action_process) < 0 ||
753                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
754                                 printf("hostapd did not reply to PING "
755                                        "command - exiting\n");
756                                 break;
757                         }
758                 }
759         }
763 int main(int argc, char *argv[])
765         int interactive;
766         int warning_displayed = 0;
767         int c;
768         int daemonize = 0;
770         if (os_program_init())
771                 return -1;
773         for (;;) {
774                 c = getopt(argc, argv, "a:BhG:i:p:v");
775                 if (c < 0)
776                         break;
777                 switch (c) {
778                 case 'a':
779                         action_file = optarg;
780                         break;
781                 case 'B':
782                         daemonize = 1;
783                         break;
784                 case 'G':
785                         ping_interval = atoi(optarg);
786                         break;
787                 case 'h':
788                         usage();
789                         return 0;
790                 case 'v':
791                         printf("%s\n", hostapd_cli_version);
792                         return 0;
793                 case 'i':
794                         free(ctrl_ifname);
795                         ctrl_ifname = strdup(optarg);
796                         break;
797                 case 'p':
798                         ctrl_iface_dir = optarg;
799                         break;
800                 default:
801                         usage();
802                         return -1;
803                 }
804         }
806         interactive = (argc == optind) && (action_file == NULL);
808         if (interactive) {
809                 printf("%s\n\n%s\n\n", hostapd_cli_version,
810                        hostapd_cli_license);
811         }
813         for (;;) {
814                 if (ctrl_ifname == NULL) {
815                         struct dirent *dent;
816                         DIR *dir = opendir(ctrl_iface_dir);
817                         if (dir) {
818                                 while ((dent = readdir(dir))) {
819                                         if (strcmp(dent->d_name, ".") == 0 ||
820                                             strcmp(dent->d_name, "..") == 0)
821                                                 continue;
822                                         printf("Selected interface '%s'\n",
823                                                dent->d_name);
824                                         ctrl_ifname = strdup(dent->d_name);
825                                         break;
826                                 }
827                                 closedir(dir);
828                         }
829                 }
830                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
831                 if (ctrl_conn) {
832                         if (warning_displayed)
833                                 printf("Connection established.\n");
834                         break;
835                 }
837                 if (!interactive) {
838                         perror("Failed to connect to hostapd - "
839                                "wpa_ctrl_open");
840                         return -1;
841                 }
843                 if (!warning_displayed) {
844                         printf("Could not connect to hostapd - re-trying\n");
845                         warning_displayed = 1;
846                 }
847                 sleep(1);
848                 continue;
849         }
851         signal(SIGINT, hostapd_cli_terminate);
852         signal(SIGTERM, hostapd_cli_terminate);
853         signal(SIGALRM, hostapd_cli_alarm);
855         if (interactive || action_file) {
856                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
857                         hostapd_cli_attached = 1;
858                 } else {
859                         printf("Warning: Failed to attach to hostapd.\n");
860                         if (action_file)
861                                 return -1;
862                 }
863         }
865         if (daemonize && os_daemonize(pid_file))
866                 return -1;
868         if (interactive)
869                 hostapd_cli_interactive();
870         else if (action_file)
871                 hostapd_cli_action(ctrl_conn);
872         else
873                 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
875         os_free(ctrl_ifname);
876         hostapd_cli_cleanup();
877         return 0;