]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
hostapd: Add global control interface
authorShan Palanisamy <shanp@qca.qualcomm.com>
Tue, 20 Dec 2011 15:10:47 +0000 (17:10 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 25 Aug 2012 10:47:24 +0000 (13:47 +0300)
Signed-hostap: Jouni Malinen <jouni@qca.qualcomm.com>

hostapd/ctrl_iface.c
hostapd/ctrl_iface.h
hostapd/main.c
src/ap/hostapd.h

index 77146e3e5ab825b6334ff44473080df8424250b5..c21c8a0173c3932e257e748c1cfb34f440448fac 100644 (file)
@@ -1092,6 +1092,191 @@ void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
 }
 
 
+static void hostapd_global_ctrl_iface_receive(int sock, void *eloop_ctx,
+                                             void *sock_ctx)
+{
+       char buf[256];
+       int res;
+       struct sockaddr_un from;
+       socklen_t fromlen = sizeof(from);
+       char reply[24];
+       int reply_len;
+
+       res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
+                      (struct sockaddr *) &from, &fromlen);
+       if (res < 0) {
+               perror("recvfrom(ctrl_iface)");
+               return;
+       }
+       buf[res] = '\0';
+
+       os_memcpy(reply, "OK\n", 3);
+       reply_len = 3;
+
+       if (os_strcmp(buf, "PING") == 0) {
+               os_memcpy(reply, "PONG\n", 5);
+               reply_len = 5;
+       } else {
+               wpa_printf(MSG_DEBUG, "Unrecognized global ctrl_iface command "
+                          "ignored");
+               reply_len = -1;
+       }
+
+       if (reply_len < 0) {
+               os_memcpy(reply, "FAIL\n", 5);
+               reply_len = 5;
+       }
+
+       sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);
+}
+
+
+static char * hostapd_global_ctrl_iface_path(struct hapd_interfaces *interface)
+{
+       char *buf;
+       size_t len;
+
+       if (interface->global_iface_path == NULL)
+               return NULL;
+
+       len = os_strlen(interface->global_iface_path) +
+               os_strlen(interface->global_iface_name) + 2;
+       buf = os_malloc(len);
+       if (buf == NULL)
+               return NULL;
+
+       os_snprintf(buf, len, "%s/%s", interface->global_iface_path,
+                   interface->global_iface_name);
+       buf[len - 1] = '\0';
+       return buf;
+}
+
+
+int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
+{
+       struct sockaddr_un addr;
+       int s = -1;
+       char *fname = NULL;
+
+       if (interface->global_iface_path == NULL) {
+               wpa_printf(MSG_DEBUG, "ctrl_iface not configured!");
+               return 0;
+       }
+
+       if (mkdir(interface->global_iface_path, S_IRWXU | S_IRWXG) < 0) {
+               if (errno == EEXIST) {
+                       wpa_printf(MSG_DEBUG, "Using existing control "
+                                  "interface directory.");
+               } else {
+                       perror("mkdir[ctrl_interface]");
+                       goto fail;
+               }
+       }
+
+       if (os_strlen(interface->global_iface_path) + 1 +
+           os_strlen(interface->global_iface_name) >= sizeof(addr.sun_path))
+               goto fail;
+
+       s = socket(PF_UNIX, SOCK_DGRAM, 0);
+       if (s < 0) {
+               perror("socket(PF_UNIX)");
+               goto fail;
+       }
+
+       os_memset(&addr, 0, sizeof(addr));
+#ifdef __FreeBSD__
+       addr.sun_len = sizeof(addr);
+#endif /* __FreeBSD__ */
+       addr.sun_family = AF_UNIX;
+       fname = hostapd_global_ctrl_iface_path(interface);
+       if (fname == NULL)
+               goto fail;
+       os_strlcpy(addr.sun_path, fname, sizeof(addr.sun_path));
+       if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+               wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",
+                          strerror(errno));
+               if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+                       wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"
+                                  " allow connections - assuming it was left"
+                                  "over from forced program termination");
+                       if (unlink(fname) < 0) {
+                               perror("unlink[ctrl_iface]");
+                               wpa_printf(MSG_ERROR, "Could not unlink "
+                                          "existing ctrl_iface socket '%s'",
+                                          fname);
+                               goto fail;
+                       }
+                       if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <
+                           0) {
+                               perror("bind(PF_UNIX)");
+                               goto fail;
+                       }
+                       wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
+                                  "ctrl_iface socket '%s'", fname);
+               } else {
+                       wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "
+                                  "be in use - cannot override it");
+                       wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
+                                  "not used anymore", fname);
+                       os_free(fname);
+                       fname = NULL;
+                       goto fail;
+               }
+       }
+
+       if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {
+               perror("chmod[ctrl_interface/ifname]");
+               goto fail;
+       }
+       os_free(fname);
+
+       interface->global_ctrl_sock = s;
+       eloop_register_read_sock(s, hostapd_global_ctrl_iface_receive,
+                                interface, NULL);
+
+       return 0;
+
+fail:
+       if (s >= 0)
+               close(s);
+       if (fname) {
+               unlink(fname);
+               os_free(fname);
+       }
+       return -1;
+}
+
+
+void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interfaces)
+{
+       char *fname = NULL;
+
+       if (interfaces->global_ctrl_sock > -1) {
+               eloop_unregister_read_sock(interfaces->global_ctrl_sock);
+               close(interfaces->global_ctrl_sock);
+               interfaces->global_ctrl_sock = -1;
+               fname = hostapd_global_ctrl_iface_path(interfaces);
+               if (fname) {
+                       unlink(fname);
+                       os_free(fname);
+               }
+
+               if (interfaces->global_iface_path &&
+                   rmdir(interfaces->global_iface_path) < 0) {
+                       if (errno == ENOTEMPTY) {
+                               wpa_printf(MSG_DEBUG, "Control interface "
+                                          "directory not empty - leaving it "
+                                          "behind");
+                       } else {
+                               perror("rmdir[ctrl_interface]");
+                       }
+               }
+               os_free(interfaces->global_iface_path);
+               interfaces->global_iface_path = NULL;
+       }
+}
+
+
 static void hostapd_ctrl_iface_send(struct hostapd_data *hapd, int level,
                                    const char *buf, size_t len)
 {
index 64a50803908ffc68a40a08c3492094048525acde..3341a66bdc6c1481b7541c4b828b1cb3513279d5 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef CONFIG_NO_CTRL_IFACE
 int hostapd_ctrl_iface_init(struct hostapd_data *hapd);
 void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd);
+int hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface);
+void hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface);
 #else /* CONFIG_NO_CTRL_IFACE */
 static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
 {
@@ -21,6 +23,17 @@ static inline int hostapd_ctrl_iface_init(struct hostapd_data *hapd)
 static inline void hostapd_ctrl_iface_deinit(struct hostapd_data *hapd)
 {
 }
+
+static inline int
+hostapd_global_ctrl_iface_init(struct hapd_interfaces *interface)
+{
+       return 0;
+}
+
+static inline void
+hostapd_global_ctrl_iface_deinit(struct hapd_interfaces *interface)
+{
+}
 #endif /* CONFIG_NO_CTRL_IFACE */
 
 #endif /* CTRL_IFACE_H */
index d1790a43533ad1d2ee7b149fdf456b4dbdb4dd5b..94b90beb283c17892a6a607e3ef5f8217de5686f 100644 (file)
@@ -494,13 +494,15 @@ static void usage(void)
        fprintf(stderr,
                "\n"
                "usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
-               "<configuration file(s)>\n"
+               "\\\n"
+               "         [-g <global ctrl_iface>] <configuration file(s)>\n"
                "\n"
                "options:\n"
                "   -h   show this usage\n"
                "   -d   show more debug messages (-dd for even more)\n"
                "   -B   run daemon in the background\n"
                "   -e   entropy file\n"
+               "   -g   global control interface path\n"
                "   -P   PID file\n"
                "   -K   include key data in debug messages\n"
 #ifdef CONFIG_DEBUG_FILE
@@ -522,6 +524,28 @@ static const char * hostapd_msg_ifname_cb(void *ctx)
 }
 
 
+static int hostapd_get_global_ctrl_iface(struct hapd_interfaces *interfaces,
+                                        const char *path)
+{
+       char *pos;
+       os_free(interfaces->global_iface_path);
+       interfaces->global_iface_path = os_strdup(path);
+       if (interfaces->global_iface_path == NULL)
+               return -1;
+       pos = os_strrchr(interfaces->global_iface_path, '/');
+       if (pos == NULL) {
+               os_free(interfaces->global_iface_path);
+               interfaces->global_iface_path = NULL;
+               return -1;
+       }
+
+       *pos = '\0';
+       interfaces->global_iface_name = pos + 1;
+
+       return 0;
+}
+
+
 int main(int argc, char *argv[])
 {
        struct hapd_interfaces interfaces;
@@ -541,9 +565,12 @@ int main(int argc, char *argv[])
        interfaces.for_each_interface = hostapd_for_each_interface;
        interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
        interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
+       interfaces.global_iface_path = NULL;
+       interfaces.global_iface_name = NULL;
+       interfaces.global_ctrl_sock = -1;
 
        for (;;) {
-               c = getopt(argc, argv, "Bde:f:hKP:tv");
+               c = getopt(argc, argv, "Bde:f:hKP:tvg:");
                if (c < 0)
                        break;
                switch (c) {
@@ -578,6 +605,9 @@ int main(int argc, char *argv[])
                        show_version();
                        exit(1);
                        break;
+               case 'g':
+                       hostapd_get_global_ctrl_iface(&interfaces, optarg);
+                       break;
 
                default:
                        usage();
@@ -613,12 +643,15 @@ int main(int argc, char *argv[])
                        goto out;
        }
 
+       hostapd_global_ctrl_iface_init(&interfaces);
+
        if (hostapd_global_run(&interfaces, daemonize, pid_file))
                goto out;
 
        ret = 0;
 
  out:
+       hostapd_global_ctrl_iface_deinit(&interfaces);
        /* Deinitialize all interfaces */
        for (i = 0; i < interfaces.count; i++)
                hostapd_interface_deinit_free(interfaces.iface[i]);
index 05e349f9bc6afa168af39bd7fc50b9be546dc652..3b79e12867c2b7d1d60a4e4984e99d788d458e9c 100644 (file)
@@ -35,6 +35,9 @@ struct hapd_interfaces {
                                            void *ctx), void *ctx);
 
        size_t count;
+       int global_ctrl_sock;
+       char *global_iface_path;
+       char *global_iface_name;
        struct hostapd_iface **iface;
 };