]> git.ipfire.org Git - thirdparty/hostap.git/blobdiff - src/common/wpa_ctrl.c
Add attribute for dwell time in QCA vendor scan
[thirdparty/hostap.git] / src / common / wpa_ctrl.c
index 5820a1364f3f721cdbccec49fc0fe7c3ad63cc53..40a979531b53673b4f7dafbc8d55919c8c493a7f 100644 (file)
@@ -11,6 +11,8 @@
 #ifdef CONFIG_CTRL_IFACE
 
 #ifdef CONFIG_CTRL_IFACE_UNIX
+#include <sys/stat.h>
+#include <fcntl.h>
 #include <sys/un.h>
 #include <unistd.h>
 #include <fcntl.h>
@@ -21,6 +23,7 @@
 
 #ifdef ANDROID
 #include <dirent.h>
+#include <sys/stat.h>
 #include <cutils/sockets.h>
 #include "private/android_filesystem_config.h"
 #endif /* ANDROID */
@@ -83,6 +86,13 @@ struct wpa_ctrl {
 
 
 struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
+{
+       return wpa_ctrl_open2(ctrl_path, NULL);
+}
+
+
+struct wpa_ctrl * wpa_ctrl_open2(const char *ctrl_path,
+                                const char *cli_path)
 {
        struct wpa_ctrl *ctrl;
        static int counter = 0;
@@ -94,10 +104,9 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
        if (ctrl_path == NULL)
                return NULL;
 
-       ctrl = os_malloc(sizeof(*ctrl));
+       ctrl = os_zalloc(sizeof(*ctrl));
        if (ctrl == NULL)
                return NULL;
-       os_memset(ctrl, 0, sizeof(*ctrl));
 
        ctrl->s = socket(PF_UNIX, SOCK_DGRAM, 0);
        if (ctrl->s < 0) {
@@ -108,16 +117,37 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
        ctrl->local.sun_family = AF_UNIX;
        counter++;
 try_again:
-       ret = os_snprintf(ctrl->local.sun_path, sizeof(ctrl->local.sun_path),
-                         CONFIG_CTRL_IFACE_CLIENT_DIR "/"
-                         CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d",
-                         (int) getpid(), counter);
-       if (ret < 0 || (size_t) ret >= sizeof(ctrl->local.sun_path)) {
+       if (cli_path && cli_path[0] == '/') {
+               ret = os_snprintf(ctrl->local.sun_path,
+                                 sizeof(ctrl->local.sun_path),
+                                 "%s/" CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d",
+                                 cli_path, (int) getpid(), counter);
+       } else {
+               ret = os_snprintf(ctrl->local.sun_path,
+                                 sizeof(ctrl->local.sun_path),
+                                 CONFIG_CTRL_IFACE_CLIENT_DIR "/"
+                                 CONFIG_CTRL_IFACE_CLIENT_PREFIX "%d-%d",
+                                 (int) getpid(), counter);
+       }
+       if (os_snprintf_error(sizeof(ctrl->local.sun_path), ret)) {
                close(ctrl->s);
                os_free(ctrl);
                return NULL;
        }
        tries++;
+#ifdef ANDROID
+       /* Set client socket file permissions so that bind() creates the client
+        * socket with these permissions and there is no need to try to change
+        * them with chmod() after bind() which would have potential issues with
+        * race conditions. These permissions are needed to make sure the server
+        * side (wpa_supplicant or hostapd) can reply to the control interface
+        * messages.
+        *
+        * The lchown() calls below after bind() are also part of the needed
+        * operations to allow the response to go through. Those are using the
+        * no-deference-symlinks version to avoid races. */
+       fchmod(ctrl->s, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+#endif /* ANDROID */
        if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
                    sizeof(ctrl->local)) < 0) {
                if (errno == EADDRINUSE && tries < 2) {
@@ -136,8 +166,9 @@ try_again:
        }
 
 #ifdef ANDROID
-       chmod(ctrl->local.sun_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
-       chown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
+       /* Set group even if we do not have privileges to change owner */
+       lchown(ctrl->local.sun_path, -1, AID_WIFI);
+       lchown(ctrl->local.sun_path, AID_SYSTEM, AID_WIFI);
 
        if (os_strncmp(ctrl_path, "@android:", 9) == 0) {
                if (socket_local_client_connect(
@@ -235,7 +266,6 @@ void wpa_ctrl_close(struct wpa_ctrl *ctrl)
 void wpa_ctrl_cleanup(void)
 {
        DIR *dir;
-       struct dirent entry;
        struct dirent *result;
        size_t dirnamelen;
        size_t maxcopy;
@@ -253,8 +283,8 @@ void wpa_ctrl_cleanup(void)
        }
        namep = pathname + dirnamelen;
        maxcopy = PATH_MAX - dirnamelen;
-       while (readdir_r(dir, &entry, &result) == 0 && result != NULL) {
-               if (os_strlcpy(namep, entry.d_name, maxcopy) < maxcopy)
+       while ((result = readdir(dir)) != NULL) {
+               if (os_strlcpy(namep, result->d_name, maxcopy) < maxcopy)
                        unlink(pathname);
        }
        closedir(dir);
@@ -283,10 +313,9 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
        struct hostent *h;
 #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
 
-       ctrl = os_malloc(sizeof(*ctrl));
+       ctrl = os_zalloc(sizeof(*ctrl));
        if (ctrl == NULL)
                return NULL;
-       os_memset(ctrl, 0, sizeof(*ctrl));
 
 #ifdef CONFIG_CTRL_IFACE_UDP_IPV6
        ctrl->s = socket(PF_INET6, SOCK_DGRAM, 0);
@@ -516,13 +545,16 @@ retry_send:
                FD_ZERO(&rfds);
                FD_SET(ctrl->s, &rfds);
                res = select(ctrl->s + 1, &rfds, NULL, NULL, &tv);
+               if (res < 0 && errno == EINTR)
+                       continue;
                if (res < 0)
                        return res;
                if (FD_ISSET(ctrl->s, &rfds)) {
                        res = recv(ctrl->s, reply, *reply_len, 0);
                        if (res < 0)
                                return res;
-                       if (res > 0 && reply[0] == '<') {
+                       if ((res > 0 && reply[0] == '<') ||
+                           (res > 6 && strncmp(reply, "IFNAME=", 7) == 0)) {
                                /* This is an unsolicited message from
                                 * wpa_supplicant, not the reply to the
                                 * request. Use msg_cb to report this to the
@@ -643,7 +675,7 @@ struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
                ret = os_snprintf(name, 256, NAMED_PIPE_PREFIX "-%s",
                                  ctrl_path);
 #endif /* UNICODE */
-       if (ret < 0 || ret >= 256) {
+       if (os_snprintf_error(256, ret)) {
                os_free(ctrl);
                return NULL;
        }