]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - build-utilities/hostap.git/blob - hostapd/hostapd_cli.c
WPS: Add support for dynamic AP PIN management
[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 "   deauthenticate <addr>  deauthenticate a station\n"
87 "   disassociate <addr>  disassociate a station\n"
88 #ifdef CONFIG_IEEE80211W
89 "   sa_query <addr>      send SA Query to a station\n"
90 #endif /* CONFIG_IEEE80211W */
91 #ifdef CONFIG_WPS
92 "   wps_pin <uuid> <pin> [timeout]  add WPS Enrollee PIN (Device Password)\n"
93 "   wps_pbc              indicate button pushed to initiate PBC\n"
94 #ifdef CONFIG_WPS_OOB
95 "   wps_oob <type> <path> <method>  use WPS with out-of-band (UFD)\n"
96 #endif /* CONFIG_WPS_OOB */
97 "   wps_ap_pin <cmd> [params..]  enable/disable AP PIN\n"
98 #endif /* CONFIG_WPS */
99 "   help                 show this usage help\n"
100 "   interface [ifname]   show interfaces/select interface\n"
101 "   level <debug level>  change debug level\n"
102 "   license              show full hostapd_cli license\n"
103 "   quit                 exit hostapd_cli\n";
105 static struct wpa_ctrl *ctrl_conn;
106 static int hostapd_cli_quit = 0;
107 static int hostapd_cli_attached = 0;
108 static const char *ctrl_iface_dir = "/var/run/hostapd";
109 static char *ctrl_ifname = NULL;
110 static const char *pid_file = NULL;
111 static const char *action_file = NULL;
112 static int ping_interval = 5;
115 static void usage(void)
117         fprintf(stderr, "%s\n", hostapd_cli_version);
118         fprintf(stderr,
119                 "\n"
120                 "usage: hostapd_cli [-p<path>] [-i<ifname>] [-hvB] "
121                 "[-a<path>] \\\n"
122                 "                   [-G<ping interval>] [command..]\n"
123                 "\n"
124                 "Options:\n"
125                 "   -h           help (show this usage text)\n"
126                 "   -v           shown version information\n"
127                 "   -p<path>     path to find control sockets (default: "
128                 "/var/run/hostapd)\n"
129                 "   -a<file>     run in daemon mode executing the action file "
130                 "based on events\n"
131                 "                from hostapd\n"
132                 "   -B           run a daemon in the background\n"
133                 "   -i<ifname>   Interface to listen on (default: first "
134                 "interface found in the\n"
135                 "                socket path)\n\n"
136                 "%s",
137                 commands_help);
141 static struct wpa_ctrl * hostapd_cli_open_connection(const char *ifname)
143         char *cfile;
144         int flen;
146         if (ifname == NULL)
147                 return NULL;
149         flen = strlen(ctrl_iface_dir) + strlen(ifname) + 2;
150         cfile = malloc(flen);
151         if (cfile == NULL)
152                 return NULL;
153         snprintf(cfile, flen, "%s/%s", ctrl_iface_dir, ifname);
155         ctrl_conn = wpa_ctrl_open(cfile);
156         free(cfile);
157         return ctrl_conn;
161 static void hostapd_cli_close_connection(void)
163         if (ctrl_conn == NULL)
164                 return;
166         if (hostapd_cli_attached) {
167                 wpa_ctrl_detach(ctrl_conn);
168                 hostapd_cli_attached = 0;
169         }
170         wpa_ctrl_close(ctrl_conn);
171         ctrl_conn = NULL;
175 static void hostapd_cli_msg_cb(char *msg, size_t len)
177         printf("%s\n", msg);
181 static int _wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd, int print)
183         char buf[4096];
184         size_t len;
185         int ret;
187         if (ctrl_conn == NULL) {
188                 printf("Not connected to hostapd - command dropped.\n");
189                 return -1;
190         }
191         len = sizeof(buf) - 1;
192         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
193                                hostapd_cli_msg_cb);
194         if (ret == -2) {
195                 printf("'%s' command timed out.\n", cmd);
196                 return -2;
197         } else if (ret < 0) {
198                 printf("'%s' command failed.\n", cmd);
199                 return -1;
200         }
201         if (print) {
202                 buf[len] = '\0';
203                 printf("%s", buf);
204         }
205         return 0;
209 static inline int wpa_ctrl_command(struct wpa_ctrl *ctrl, char *cmd)
211         return _wpa_ctrl_command(ctrl, cmd, 1);
215 static int hostapd_cli_cmd_ping(struct wpa_ctrl *ctrl, int argc, char *argv[])
217         return wpa_ctrl_command(ctrl, "PING");
221 static int hostapd_cli_cmd_mib(struct wpa_ctrl *ctrl, int argc, char *argv[])
223         return wpa_ctrl_command(ctrl, "MIB");
227 static int hostapd_cli_exec(const char *program, const char *arg1,
228                             const char *arg2)
230         char *cmd;
231         size_t len;
232         int res;
233         int ret = 0;
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);
251         return ret;
255 static void hostapd_cli_action_process(char *msg, size_t len)
257         const char *pos;
259         pos = msg;
260         if (*pos == '<') {
261                 pos = os_strchr(pos, '>');
262                 if (pos)
263                         pos++;
264                 else
265                         pos = msg;
266         }
268         hostapd_cli_exec(action_file, ctrl_ifname, pos);
272 static int hostapd_cli_cmd_sta(struct wpa_ctrl *ctrl, int argc, char *argv[])
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);
285 static int hostapd_cli_cmd_new_sta(struct wpa_ctrl *ctrl, int argc,
286                                    char *argv[])
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);
299 static int hostapd_cli_cmd_deauthenticate(struct wpa_ctrl *ctrl, int argc,
300                                           char *argv[])
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);
317 static int hostapd_cli_cmd_disassociate(struct wpa_ctrl *ctrl, int argc,
318                                         char *argv[])
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);
335 #ifdef CONFIG_IEEE80211W
336 static int hostapd_cli_cmd_sa_query(struct wpa_ctrl *ctrl, int argc,
337                                     char *argv[])
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);
348 #endif /* CONFIG_IEEE80211W */
351 #ifdef CONFIG_WPS
352 static int hostapd_cli_cmd_wps_pin(struct wpa_ctrl *ctrl, int argc,
353                                    char *argv[])
355         char buf[64];
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 > 2)
362                 snprintf(buf, sizeof(buf), "WPS_PIN %s %s %s",
363                          argv[0], argv[1], argv[2]);
364         else
365                 snprintf(buf, sizeof(buf), "WPS_PIN %s %s", argv[0], argv[1]);
366         return wpa_ctrl_command(ctrl, buf);
370 static int hostapd_cli_cmd_wps_pbc(struct wpa_ctrl *ctrl, int argc,
371                                    char *argv[])
373         return wpa_ctrl_command(ctrl, "WPS_PBC");
377 #ifdef CONFIG_WPS_OOB
378 static int hostapd_cli_cmd_wps_oob(struct wpa_ctrl *ctrl, int argc,
379                                    char *argv[])
381         char cmd[256];
382         int res;
384         if (argc != 3 && argc != 4) {
385                 printf("Invalid WPS_OOB command: need three or four "
386                        "arguments:\n"
387                        "- DEV_TYPE: use 'ufd' or 'nfc'\n"
388                        "- PATH: path of OOB device like '/mnt'\n"
389                        "- METHOD: OOB method 'pin-e' or 'pin-r', "
390                        "'cred'\n"
391                        "- DEV_NAME: (only for NFC) device name like "
392                        "'pn531'\n");
393                 return -1;
394         }
396         if (argc == 3)
397                 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s",
398                                   argv[0], argv[1], argv[2]);
399         else
400                 res = os_snprintf(cmd, sizeof(cmd), "WPS_OOB %s %s %s %s",
401                                   argv[0], argv[1], argv[2], argv[3]);
402         if (res < 0 || (size_t) res >= sizeof(cmd) - 1) {
403                 printf("Too long WPS_OOB command.\n");
404                 return -1;
405         }
406         return wpa_ctrl_command(ctrl, cmd);
408 #endif /* CONFIG_WPS_OOB */
411 static int hostapd_cli_cmd_wps_ap_pin(struct wpa_ctrl *ctrl, int argc,
412                                       char *argv[])
414         char buf[64];
415         if (argc < 1) {
416                 printf("Invalid 'wps_ap_pin' command - at least one argument "
417                        "is required.\n");
418                 return -1;
419         }
420         if (argc > 2)
421                 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s %s",
422                          argv[0], argv[1], argv[2]);
423         else if (argc > 1)
424                 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s %s",
425                          argv[0], argv[1]);
426         else
427                 snprintf(buf, sizeof(buf), "WPS_AP_PIN %s", argv[0]);
428         return wpa_ctrl_command(ctrl, buf);
430 #endif /* CONFIG_WPS */
433 static int wpa_ctrl_command_sta(struct wpa_ctrl *ctrl, char *cmd,
434                                 char *addr, size_t addr_len)
436         char buf[4096], *pos;
437         size_t len;
438         int ret;
440         if (ctrl_conn == NULL) {
441                 printf("Not connected to hostapd - command dropped.\n");
442                 return -1;
443         }
444         len = sizeof(buf) - 1;
445         ret = wpa_ctrl_request(ctrl, cmd, strlen(cmd), buf, &len,
446                                hostapd_cli_msg_cb);
447         if (ret == -2) {
448                 printf("'%s' command timed out.\n", cmd);
449                 return -2;
450         } else if (ret < 0) {
451                 printf("'%s' command failed.\n", cmd);
452                 return -1;
453         }
455         buf[len] = '\0';
456         if (memcmp(buf, "FAIL", 4) == 0)
457                 return -1;
458         printf("%s", buf);
460         pos = buf;
461         while (*pos != '\0' && *pos != '\n')
462                 pos++;
463         *pos = '\0';
464         os_strlcpy(addr, buf, addr_len);
465         return 0;
469 static int hostapd_cli_cmd_all_sta(struct wpa_ctrl *ctrl, int argc,
470                                    char *argv[])
472         char addr[32], cmd[64];
474         if (wpa_ctrl_command_sta(ctrl, "STA-FIRST", addr, sizeof(addr)))
475                 return 0;
476         do {
477                 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", addr);
478         } while (wpa_ctrl_command_sta(ctrl, cmd, addr, sizeof(addr)) == 0);
480         return -1;
484 static int hostapd_cli_cmd_help(struct wpa_ctrl *ctrl, int argc, char *argv[])
486         printf("%s", commands_help);
487         return 0;
491 static int hostapd_cli_cmd_license(struct wpa_ctrl *ctrl, int argc,
492                                    char *argv[])
494         printf("%s\n\n%s\n", hostapd_cli_version, hostapd_cli_full_license);
495         return 0;
499 static int hostapd_cli_cmd_quit(struct wpa_ctrl *ctrl, int argc, char *argv[])
501         hostapd_cli_quit = 1;
502         return 0;
506 static int hostapd_cli_cmd_level(struct wpa_ctrl *ctrl, int argc, char *argv[])
508         char cmd[256];
509         if (argc != 1) {
510                 printf("Invalid LEVEL command: needs one argument (debug "
511                        "level)\n");
512                 return 0;
513         }
514         snprintf(cmd, sizeof(cmd), "LEVEL %s", argv[0]);
515         return wpa_ctrl_command(ctrl, cmd);
519 static void hostapd_cli_list_interfaces(struct wpa_ctrl *ctrl)
521         struct dirent *dent;
522         DIR *dir;
524         dir = opendir(ctrl_iface_dir);
525         if (dir == NULL) {
526                 printf("Control interface directory '%s' could not be "
527                        "openned.\n", ctrl_iface_dir);
528                 return;
529         }
531         printf("Available interfaces:\n");
532         while ((dent = readdir(dir))) {
533                 if (strcmp(dent->d_name, ".") == 0 ||
534                     strcmp(dent->d_name, "..") == 0)
535                         continue;
536                 printf("%s\n", dent->d_name);
537         }
538         closedir(dir);
542 static int hostapd_cli_cmd_interface(struct wpa_ctrl *ctrl, int argc,
543                                      char *argv[])
545         if (argc < 1) {
546                 hostapd_cli_list_interfaces(ctrl);
547                 return 0;
548         }
550         hostapd_cli_close_connection();
551         free(ctrl_ifname);
552         ctrl_ifname = strdup(argv[0]);
554         if (hostapd_cli_open_connection(ctrl_ifname)) {
555                 printf("Connected to interface '%s.\n", ctrl_ifname);
556                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
557                         hostapd_cli_attached = 1;
558                 } else {
559                         printf("Warning: Failed to attach to "
560                                "hostapd.\n");
561                 }
562         } else {
563                 printf("Could not connect to interface '%s' - re-trying\n",
564                         ctrl_ifname);
565         }
566         return 0;
570 struct hostapd_cli_cmd {
571         const char *cmd;
572         int (*handler)(struct wpa_ctrl *ctrl, int argc, char *argv[]);
573 };
575 static struct hostapd_cli_cmd hostapd_cli_commands[] = {
576         { "ping", hostapd_cli_cmd_ping },
577         { "mib", hostapd_cli_cmd_mib },
578         { "sta", hostapd_cli_cmd_sta },
579         { "all_sta", hostapd_cli_cmd_all_sta },
580         { "new_sta", hostapd_cli_cmd_new_sta },
581         { "deauthenticate", hostapd_cli_cmd_deauthenticate },
582         { "disassociate", hostapd_cli_cmd_disassociate },
583 #ifdef CONFIG_IEEE80211W
584         { "sa_query", hostapd_cli_cmd_sa_query },
585 #endif /* CONFIG_IEEE80211W */
586 #ifdef CONFIG_WPS
587         { "wps_pin", hostapd_cli_cmd_wps_pin },
588         { "wps_pbc", hostapd_cli_cmd_wps_pbc },
589 #ifdef CONFIG_WPS_OOB
590         { "wps_oob", hostapd_cli_cmd_wps_oob },
591 #endif /* CONFIG_WPS_OOB */
592         { "wps_ap_pin", hostapd_cli_cmd_wps_ap_pin },
593 #endif /* CONFIG_WPS */
594         { "help", hostapd_cli_cmd_help },
595         { "interface", hostapd_cli_cmd_interface },
596         { "level", hostapd_cli_cmd_level },
597         { "license", hostapd_cli_cmd_license },
598         { "quit", hostapd_cli_cmd_quit },
599         { NULL, NULL }
600 };
603 static void wpa_request(struct wpa_ctrl *ctrl, int argc, char *argv[])
605         struct hostapd_cli_cmd *cmd, *match = NULL;
606         int count;
608         count = 0;
609         cmd = hostapd_cli_commands;
610         while (cmd->cmd) {
611                 if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) == 0) {
612                         match = cmd;
613                         count++;
614                 }
615                 cmd++;
616         }
618         if (count > 1) {
619                 printf("Ambiguous command '%s'; possible commands:", argv[0]);
620                 cmd = hostapd_cli_commands;
621                 while (cmd->cmd) {
622                         if (strncasecmp(cmd->cmd, argv[0], strlen(argv[0])) ==
623                             0) {
624                                 printf(" %s", cmd->cmd);
625                         }
626                         cmd++;
627                 }
628                 printf("\n");
629         } else if (count == 0) {
630                 printf("Unknown command '%s'\n", argv[0]);
631         } else {
632                 match->handler(ctrl, argc - 1, &argv[1]);
633         }
637 static void hostapd_cli_recv_pending(struct wpa_ctrl *ctrl, int in_read,
638                                      int action_monitor)
640         int first = 1;
641         if (ctrl_conn == NULL)
642                 return;
643         while (wpa_ctrl_pending(ctrl)) {
644                 char buf[256];
645                 size_t len = sizeof(buf) - 1;
646                 if (wpa_ctrl_recv(ctrl, buf, &len) == 0) {
647                         buf[len] = '\0';
648                         if (action_monitor)
649                                 hostapd_cli_action_process(buf, len);
650                         else {
651                                 if (in_read && first)
652                                         printf("\n");
653                                 first = 0;
654                                 printf("%s\n", buf);
655                         }
656                 } else {
657                         printf("Could not read pending message.\n");
658                         break;
659                 }
660         }
664 static void hostapd_cli_interactive(void)
666         const int max_args = 10;
667         char cmd[256], *res, *argv[max_args], *pos;
668         int argc;
670         printf("\nInteractive mode\n\n");
672         do {
673                 hostapd_cli_recv_pending(ctrl_conn, 0, 0);
674                 printf("> ");
675                 alarm(ping_interval);
676                 res = fgets(cmd, sizeof(cmd), stdin);
677                 alarm(0);
678                 if (res == NULL)
679                         break;
680                 pos = cmd;
681                 while (*pos != '\0') {
682                         if (*pos == '\n') {
683                                 *pos = '\0';
684                                 break;
685                         }
686                         pos++;
687                 }
688                 argc = 0;
689                 pos = cmd;
690                 for (;;) {
691                         while (*pos == ' ')
692                                 pos++;
693                         if (*pos == '\0')
694                                 break;
695                         argv[argc] = pos;
696                         argc++;
697                         if (argc == max_args)
698                                 break;
699                         while (*pos != '\0' && *pos != ' ')
700                                 pos++;
701                         if (*pos == ' ')
702                                 *pos++ = '\0';
703                 }
704                 if (argc)
705                         wpa_request(ctrl_conn, argc, argv);
706         } while (!hostapd_cli_quit);
710 static void hostapd_cli_cleanup(void)
712         hostapd_cli_close_connection();
713         if (pid_file)
714                 os_daemonize_terminate(pid_file);
716         os_program_deinit();
720 static void hostapd_cli_terminate(int sig)
722         hostapd_cli_cleanup();
723         exit(0);
727 static void hostapd_cli_alarm(int sig)
729         if (ctrl_conn && _wpa_ctrl_command(ctrl_conn, "PING", 0)) {
730                 printf("Connection to hostapd lost - trying to reconnect\n");
731                 hostapd_cli_close_connection();
732         }
733         if (!ctrl_conn) {
734                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
735                 if (ctrl_conn) {
736                         printf("Connection to hostapd re-established\n");
737                         if (wpa_ctrl_attach(ctrl_conn) == 0) {
738                                 hostapd_cli_attached = 1;
739                         } else {
740                                 printf("Warning: Failed to attach to "
741                                        "hostapd.\n");
742                         }
743                 }
744         }
745         if (ctrl_conn)
746                 hostapd_cli_recv_pending(ctrl_conn, 1, 0);
747         alarm(ping_interval);
751 static void hostapd_cli_action(struct wpa_ctrl *ctrl)
753         fd_set rfds;
754         int fd, res;
755         struct timeval tv;
756         char buf[256];
757         size_t len;
759         fd = wpa_ctrl_get_fd(ctrl);
761         while (!hostapd_cli_quit) {
762                 FD_ZERO(&rfds);
763                 FD_SET(fd, &rfds);
764                 tv.tv_sec = ping_interval;
765                 tv.tv_usec = 0;
766                 res = select(fd + 1, &rfds, NULL, NULL, &tv);
767                 if (res < 0 && errno != EINTR) {
768                         perror("select");
769                         break;
770                 }
772                 if (FD_ISSET(fd, &rfds))
773                         hostapd_cli_recv_pending(ctrl, 0, 1);
774                 else {
775                         len = sizeof(buf) - 1;
776                         if (wpa_ctrl_request(ctrl, "PING", 4, buf, &len,
777                                              hostapd_cli_action_process) < 0 ||
778                             len < 4 || os_memcmp(buf, "PONG", 4) != 0) {
779                                 printf("hostapd did not reply to PING "
780                                        "command - exiting\n");
781                                 break;
782                         }
783                 }
784         }
788 int main(int argc, char *argv[])
790         int interactive;
791         int warning_displayed = 0;
792         int c;
793         int daemonize = 0;
795         if (os_program_init())
796                 return -1;
798         for (;;) {
799                 c = getopt(argc, argv, "a:BhG:i:p:v");
800                 if (c < 0)
801                         break;
802                 switch (c) {
803                 case 'a':
804                         action_file = optarg;
805                         break;
806                 case 'B':
807                         daemonize = 1;
808                         break;
809                 case 'G':
810                         ping_interval = atoi(optarg);
811                         break;
812                 case 'h':
813                         usage();
814                         return 0;
815                 case 'v':
816                         printf("%s\n", hostapd_cli_version);
817                         return 0;
818                 case 'i':
819                         os_free(ctrl_ifname);
820                         ctrl_ifname = os_strdup(optarg);
821                         break;
822                 case 'p':
823                         ctrl_iface_dir = optarg;
824                         break;
825                 default:
826                         usage();
827                         return -1;
828                 }
829         }
831         interactive = (argc == optind) && (action_file == NULL);
833         if (interactive) {
834                 printf("%s\n\n%s\n\n", hostapd_cli_version,
835                        hostapd_cli_license);
836         }
838         for (;;) {
839                 if (ctrl_ifname == NULL) {
840                         struct dirent *dent;
841                         DIR *dir = opendir(ctrl_iface_dir);
842                         if (dir) {
843                                 while ((dent = readdir(dir))) {
844                                         if (os_strcmp(dent->d_name, ".") == 0
845                                             ||
846                                             os_strcmp(dent->d_name, "..") == 0)
847                                                 continue;
848                                         printf("Selected interface '%s'\n",
849                                                dent->d_name);
850                                         ctrl_ifname = os_strdup(dent->d_name);
851                                         break;
852                                 }
853                                 closedir(dir);
854                         }
855                 }
856                 ctrl_conn = hostapd_cli_open_connection(ctrl_ifname);
857                 if (ctrl_conn) {
858                         if (warning_displayed)
859                                 printf("Connection established.\n");
860                         break;
861                 }
863                 if (!interactive) {
864                         perror("Failed to connect to hostapd - "
865                                "wpa_ctrl_open");
866                         return -1;
867                 }
869                 if (!warning_displayed) {
870                         printf("Could not connect to hostapd - re-trying\n");
871                         warning_displayed = 1;
872                 }
873                 os_sleep(1, 0);
874                 continue;
875         }
877         signal(SIGINT, hostapd_cli_terminate);
878         signal(SIGTERM, hostapd_cli_terminate);
879         signal(SIGALRM, hostapd_cli_alarm);
881         if (interactive || action_file) {
882                 if (wpa_ctrl_attach(ctrl_conn) == 0) {
883                         hostapd_cli_attached = 1;
884                 } else {
885                         printf("Warning: Failed to attach to hostapd.\n");
886                         if (action_file)
887                                 return -1;
888                 }
889         }
891         if (daemonize && os_daemonize(pid_file))
892                 return -1;
894         if (interactive)
895                 hostapd_cli_interactive();
896         else if (action_file)
897                 hostapd_cli_action(ctrl_conn);
898         else
899                 wpa_request(ctrl_conn, argc - optind, &argv[optind]);
901         os_free(ctrl_ifname);
902         hostapd_cli_cleanup();
903         return 0;