Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/external/bsd/wpa/dist/src/drivers Use recvmsg(2) to read rou...



details:   https://anonhg.NetBSD.org/src/rev/c6b41397bd39
branches:  trunk
changeset: 823065:c6b41397bd39
user:      roy <roy%NetBSD.org@localhost>
date:      Tue Apr 11 14:13:01 2017 +0000

description:
Use recvmsg(2) to read route(4) messages.
Use a shim function for this which can grow it's buffer when needed.

diffstat:

 external/bsd/wpa/dist/src/drivers/driver_bsd.c |  96 ++++++++++++++++---------
 1 files changed, 62 insertions(+), 34 deletions(-)

diffs (197 lines):

diff -r 932560dd96dc -r c6b41397bd39 external/bsd/wpa/dist/src/drivers/driver_bsd.c
--- a/external/bsd/wpa/dist/src/drivers/driver_bsd.c    Tue Apr 11 14:05:35 2017 +0000
+++ b/external/bsd/wpa/dist/src/drivers/driver_bsd.c    Tue Apr 11 14:13:01 2017 +0000
@@ -9,7 +9,7 @@
 
 #include "includes.h"
 #include <sys/ioctl.h>
-#include <sys/sysctl.h>
+#include <sys/param.h>
 
 #include "common.h"
 #include "driver.h"
@@ -45,15 +45,13 @@
 
 #include "common/ieee802_11_defs.h"
 #include "common/wpa_common.h"
-
 #include "l2_packet/l2_packet.h"
 
 struct bsd_driver_global {
        void            *ctx;
        int             sock;                   /* socket for 802.11 ioctls */
        int             route;                  /* routing socket for events */
-       char            *event_buf;
-       size_t          event_buf_len;
+       struct iovec    event_iov[1];
        struct dl_list  ifaces;                 /* list of interfaces */
 };
 
@@ -78,6 +76,50 @@
 
 /* Generic functions for hostapd and wpa_supplicant */
 
+#define IOVEC_BUFSIZ           256
+ssize_t
+recvmsg_realloc(int fd, struct msghdr *msg, int flags)
+{
+       struct iovec *iov;
+       ssize_t slen;
+       size_t len;
+       void *n;
+
+       /* Assume we are reallocing the last iovec. */
+       iov = &msg->msg_iov[msg->msg_iovlen - 1];
+
+       for (;;) {
+               /* Passing MSG_TRUNC should return the actual size needed. */
+               slen = recvmsg(fd, msg, flags | MSG_PEEK | MSG_TRUNC);
+               if (slen == -1)
+                       return -1;
+               if (!(msg->msg_flags & MSG_TRUNC))
+                       break;
+
+               len = (size_t)slen;
+
+               /* Some kernels return the size of the receive buffer
+                * on truncation, not the actual size needed.
+                * So grow the buffer and try again. */
+               if (iov->iov_len == len)
+                       len = roundup(len + 1, IOVEC_BUFSIZ);
+               else if (iov->iov_len > len)
+                       break;
+               if ((n = realloc(iov->iov_base, len)) == NULL)
+                       return -1;
+               iov->iov_base = n;
+               iov->iov_len = len;
+       }
+
+       slen = recvmsg(fd, msg, flags);
+       if (slen != -1 && msg->msg_flags & MSG_TRUNC) {
+               /* This should not be possible ... */
+               errno = ENOBUFS;
+               return -1;
+       }
+       return slen;
+}
+
 static struct bsd_driver_data *
 bsd_get_drvindex(void *priv, unsigned int ifindex)
 {
@@ -637,22 +679,6 @@
        return 0;
 }
 
-static size_t
-rtbuf_len(void)
-{
-       size_t len;
-
-       int mib[6] = {CTL_NET, AF_ROUTE, 0, AF_INET, NET_RT_DUMP, 0};
-
-       if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
-               wpa_printf(MSG_WARNING, "%s failed: %s", __func__,
-                          strerror(errno));
-               len = 2048;
-       }
-
-       return len;
-}
-
 #ifdef HOSTAPD
 
 /*
@@ -727,7 +753,7 @@
 }
 
 
-static int 
+static int
 bsd_flush(void *priv)
 {
        u8 allsta[IEEE80211_ADDR_LEN];
@@ -775,15 +801,19 @@
 {
        struct bsd_driver_global *global = sock_ctx;
        struct bsd_driver_data *drv;
+       struct msghdr msg;
        struct if_announcemsghdr *ifan;
        struct rt_msghdr *rtm;
        struct ieee80211_michael_event *mic;
        struct ieee80211_join_event *join;
        struct ieee80211_leave_event *leave;
-       int n;
+       ssize_t n;
        union wpa_event_data data;
 
-       n = read(sock, global->event_buf, global->event_buf_len);
+       memset(&msg, 0, sizeof(msg));
+       msg.msg_iov = global->event_iov;
+       msg.msg_iovlen = 1;
+       n = recvmsg_realloc(sock, &msg, 0);
        if (n < 0) {
                if (errno != EINTR && errno != EAGAIN)
                        wpa_printf(MSG_ERROR, "%s read() failed: %s",
@@ -791,7 +821,7 @@
                return;
        }
 
-       rtm = (struct rt_msghdr *) global->event_buf;
+       rtm = (struct rt_msghdr *) global->event_iov[0].iov_base;
        if (rtm->rtm_version != RTM_VERSION) {
                wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
                           rtm->rtm_version);
@@ -1213,6 +1243,7 @@
 {
        struct bsd_driver_global *global = sock_ctx;
        struct bsd_driver_data *drv;
+       struct msghdr msg;
        struct if_announcemsghdr *ifan;
        struct if_msghdr *ifm;
        struct rt_msghdr *rtm;
@@ -1220,9 +1251,12 @@
        struct ieee80211_michael_event *mic;
        struct ieee80211_leave_event *leave;
        struct ieee80211_join_event *join;
-       int n;
+       ssize_t n;
 
-       n = read(sock, global->event_buf, global->event_buf_len);
+       memset(&msg, 0, sizeof(msg));
+       msg.msg_iov = global->event_iov;
+       msg.msg_iovlen = 1;
+       n = recvmsg_realloc(sock, &msg, 0);
        if (n < 0) {
                if (errno != EINTR && errno != EAGAIN)
                        wpa_printf(MSG_ERROR, "%s read() failed: %s",
@@ -1230,7 +1264,7 @@
                return;
        }
 
-       rtm = (struct rt_msghdr *) global->event_buf;
+       rtm = (struct rt_msghdr *) global->event_iov[0].iov_base;
        if (rtm->rtm_version != RTM_VERSION) {
                wpa_printf(MSG_DEBUG, "Invalid routing message version=%d",
                           rtm->rtm_version);
@@ -1684,13 +1718,6 @@
                goto fail;
        }
 
-       global->event_buf_len = rtbuf_len();
-       global->event_buf = os_malloc(global->event_buf_len);
-       if (global->event_buf == NULL) {
-               wpa_printf(MSG_ERROR, "%s: os_malloc() failed", __func__);
-               goto fail;
-       }
-
 #ifdef HOSTAPD
        eloop_register_read_sock(global->route, bsd_wireless_event_receive,
                                 NULL, global);
@@ -1717,6 +1744,7 @@
        eloop_unregister_read_sock(global->route);
        (void) close(global->route);
        (void) close(global->sock);
+       free(global->event_iov[0].iov_base);
        os_free(global);
 }
 



Home | Main Index | Thread Index | Old Index