The branch, master has been updated
       via  98a05e5 tests: Add sendmsg_recvmsg_fd test.
       via  c29f759 tests: Add test_echo_udp_sendmsg_recvmsg.
       via  ae88bf8 swrap: Implement recvmsg().
       via  6d328a2 swrap: Fix DGRAM in swrap_recvmsg(before|after).
       via  11b077a swrap: Use swrap_recvmsg_* in swrap_read().
       via  7e5f1f5 swrap: Use swrap_recvmsg_* in swrap_recv().
       via  35bcc16 swrap: Use swrap_recvmsg_* in swrap_recvfrom().
       via  e11fd61 swrap: Add swrap_recvmsg_after().
       via  76ff3d4 swrap: Add swrap_recvmsg_before().
      from  e9de990 echo_srv: Add fd duplication and test it works.

http://gitweb.samba.org/?p=socket_wrapper.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 98a05e5b2ca9e3ac6ad22ae5c5bbb754ab8f6641
Author: Jakub Hrozek <[email protected]>
Date:   Mon Jan 20 13:45:58 2014 +0100

    tests: Add sendmsg_recvmsg_fd test.

commit c29f7596696ec67fdf9ad2c860362bd0fc1516ae
Author: Andreas Schneider <[email protected]>
Date:   Mon Jan 20 18:36:47 2014 +0100

    tests: Add test_echo_udp_sendmsg_recvmsg.

commit ae88bf8a6894df56f0be77610d47a0f3730c8804
Author: Andreas Schneider <[email protected]>
Date:   Wed Jan 15 16:55:20 2014 +0100

    swrap: Implement recvmsg().

commit 6d328a234f8e5557a2e6898aff4bc92ace4b8b01
Author: Andreas Schneider <[email protected]>
Date:   Tue Dec 24 13:06:40 2013 +0100

    swrap: Fix DGRAM in swrap_recvmsg(before|after).

commit 11b077a674fa146b2744f6cd4c5f947e7d1f531d
Author: Stefan Metzmacher <[email protected]>
Date:   Tue Dec 24 11:37:29 2013 +0100

    swrap: Use swrap_recvmsg_* in swrap_read().

commit 7e5f1f5abc66dff745cb4cc2bcf187189fa19d12
Author: Stefan Metzmacher <[email protected]>
Date:   Tue Dec 24 11:35:16 2013 +0100

    swrap: Use swrap_recvmsg_* in swrap_recv().

commit 35bcc16674140864e2816cb6a5a536afaed9e597
Author: Stefan Metzmacher <[email protected]>
Date:   Tue Dec 24 11:31:50 2013 +0100

    swrap: Use swrap_recvmsg_* in swrap_recvfrom().

commit e11fd61be098aed3ed2b16e6ed9fe12e6a8f2b13
Author: Stefan Metzmacher <[email protected]>
Date:   Tue Dec 24 11:28:29 2013 +0100

    swrap: Add swrap_recvmsg_after().

commit 76ff3d42b48c0d25d505496d3e90f50fe7d6f9db
Author: Stefan Metzmacher <[email protected]>
Date:   Tue Dec 24 11:28:13 2013 +0100

    swrap: Add swrap_recvmsg_before().

-----------------------------------------------------------------------

Summary of changes:
 src/socket_wrapper.c                               |  349 ++++++++++++++++++--
 tests/CMakeLists.txt                               |    4 +-
 ..._recvfrom.c => test_echo_udp_sendmsg_recvmsg.c} |  111 +++----
 tests/test_sendmsg_recvmsg_fd.c                    |  116 +++++++
 4 files changed, 487 insertions(+), 93 deletions(-)
 copy tests/{test_echo_udp_sendto_recvfrom.c => 
test_echo_udp_sendmsg_recvmsg.c} (71%)
 create mode 100644 tests/test_sendmsg_recvmsg_fd.c


Changeset truncated at 500 lines:

diff --git a/src/socket_wrapper.c b/src/socket_wrapper.c
index dc6ffb1..b85021a 100644
--- a/src/socket_wrapper.c
+++ b/src/socket_wrapper.c
@@ -313,6 +313,7 @@ struct swrap_libc_fns {
                             int flags,
                             struct sockaddr *src_addr,
                             socklen_t *addrlen);
+       int (*libc_recvmsg)(int sockfd, const struct msghdr *msg, int flags);
        int (*libc_send)(int sockfd, const void *buf, size_t len, int flags);
        int (*libc_sendmsg)(int sockfd, const struct msghdr *msg, int flags);
        int (*libc_sendto)(int sockfd,
@@ -603,6 +604,13 @@ static int libc_recvfrom(int sockfd,
        return swrap.fns.libc_recvfrom(sockfd, buf, len, flags, src_addr, 
addrlen);
 }
 
+static int libc_recvmsg(int sockfd, struct msghdr *msg, int flags)
+{
+       swrap_load_lib_function(SWRAP_LIBSOCKET, recvmsg);
+
+       return swrap.fns.libc_recvmsg(sockfd, msg, flags);
+}
+
 static int libc_send(int sockfd, const void *buf, size_t len, int flags)
 {
        swrap_load_lib_function(SWRAP_LIBSOCKET, send);
@@ -2814,6 +2822,168 @@ static void swrap_sendmsg_after(struct socket_info *si,
        errno = saved_errno;
 }
 
+static int swrap_recvmsg_before(int fd,
+                               struct socket_info *si,
+                               struct msghdr *msg,
+                               struct iovec *tmp_iov)
+{
+       size_t i, len = 0;
+       ssize_t ret;
+
+       (void)fd; /* unused */
+
+       switch (si->type) {
+       case SOCK_STREAM:
+               if (!si->connected) {
+                       errno = ENOTCONN;
+                       return -1;
+               }
+
+               if (msg->msg_iovlen == 0) {
+                       break;
+               }
+
+               for (i=0; i < msg->msg_iovlen; i++) {
+                       size_t nlen;
+                       nlen = len + msg->msg_iov[i].iov_len;
+                       if (nlen > SOCKET_MAX_PACKET) {
+                               break;
+                       }
+               }
+               msg->msg_iovlen = i;
+               if (msg->msg_iovlen == 0) {
+                       *tmp_iov = msg->msg_iov[0];
+                       tmp_iov->iov_len = MIN(tmp_iov->iov_len, 
SOCKET_MAX_PACKET);
+                       msg->msg_iov = tmp_iov;
+                       msg->msg_iovlen = 1;
+               }
+               break;
+
+       case SOCK_DGRAM:
+               if (msg->msg_name == NULL) {
+                       errno = EINVAL;
+                       return -1;
+               }
+
+               if (msg->msg_iovlen == 0) {
+                       break;
+               }
+
+               if (si->bound == 0) {
+                       ret = swrap_auto_bind(fd, si, si->family);
+                       if (ret == -1) {
+                               return -1;
+                       }
+               }
+               break;
+       default:
+               errno = EHOSTUNREACH;
+               return -1;
+       }
+
+       return 0;
+}
+
+static int swrap_recvmsg_after(struct socket_info *si,
+                              struct msghdr *msg,
+                              const struct sockaddr_un *un_addr,
+                              socklen_t un_addrlen,
+                              ssize_t ret)
+{
+       int saved_errno = errno;
+       size_t i;
+       uint8_t *buf;
+       off_t ofs = 0;
+       size_t avail = 0;
+       size_t remain;
+
+       /* to give better errors */
+       if (ret == -1 && saved_errno == ENOENT) {
+               saved_errno = EHOSTUNREACH;
+       }
+
+       for (i=0; i < msg->msg_iovlen; i++) {
+               avail += msg->msg_iov[i].iov_len;
+       }
+
+       if (avail == 0) {
+               errno = saved_errno;
+               return 0;
+       }
+
+       if (ret == -1) {
+               remain = MIN(80, avail);
+       } else {
+               remain = ret;
+       }
+
+       /* we capture it as one single packet */
+       buf = (uint8_t *)malloc(remain);
+       if (!buf) {
+               /* we just not capture the packet */
+               errno = saved_errno;
+               return -1;
+       }
+
+       for (i=0; i < msg->msg_iovlen; i++) {
+               size_t this_time = MIN(remain, msg->msg_iov[i].iov_len);
+               memcpy(buf + ofs,
+                      msg->msg_iov[i].iov_base,
+                      this_time);
+               ofs += this_time;
+               remain -= this_time;
+       }
+
+       switch (si->type) {
+       case SOCK_STREAM:
+               if (ret == -1 && saved_errno != EAGAIN && saved_errno != 
ENOBUFS) {
+                       swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
+               } else if (ret == 0) { /* END OF FILE */
+                       swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
+               } else if (ret > 0) {
+                       swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
+               }
+               break;
+
+       case SOCK_DGRAM:
+               if (ret == -1) {
+                       break;
+               }
+
+               if (un_addr != NULL) {
+                       int rc;
+
+                       rc = sockaddr_convert_from_un(si,
+                                                     un_addr,
+                                                     un_addrlen,
+                                                     si->family,
+                                                     msg->msg_name,
+                                                     &msg->msg_namelen);
+                       if (rc == -1) {
+                               return -1;
+                       }
+
+                       swrap_dump_packet(si,
+                                         msg->msg_name,
+                                         SWRAP_RECVFROM,
+                                         buf,
+                                         ret);
+               } else {
+                       swrap_dump_packet(si,
+                                         msg->msg_name,
+                                         SWRAP_RECV,
+                                         buf,
+                                         ret);
+               }
+
+               break;
+       }
+
+       free(buf);
+       errno = saved_errno;
+       return 0;
+}
+
 /****************************************************************************
  *   RECVFROM
  ***************************************************************************/
@@ -2821,12 +2991,15 @@ static void swrap_sendmsg_after(struct socket_info *si,
 static ssize_t swrap_recvfrom(int s, void *buf, size_t len, int flags,
                              struct sockaddr *from, socklen_t *fromlen)
 {
-       struct sockaddr_un un_addr;
-       socklen_t un_addrlen = sizeof(un_addr);
+       struct sockaddr_un from_addr;
+       socklen_t from_addrlen = sizeof(from_addr);
        ssize_t ret;
        struct socket_info *si = find_socket_info(s);
        struct sockaddr_storage ss;
        socklen_t ss_len = sizeof(ss);
+       struct msghdr msg;
+       struct iovec tmp;
+       int tret;
 
        if (!si) {
                return libc_recvfrom(s,
@@ -2837,32 +3010,55 @@ static ssize_t swrap_recvfrom(int s, void *buf, size_t 
len, int flags,
                                     fromlen);
        }
 
-       if (!from) {
-               from = (struct sockaddr *)(void *)&ss;
-               fromlen = &ss_len;
+       if (from != NULL && fromlen != NULL) {
+               msg.msg_name = from;   /* optional address */
+               msg.msg_namelen = *fromlen; /* size of address */
+       } else {
+               msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional 
address */
+               msg.msg_namelen = ss_len; /* size of address */
        }
 
-       if (si->type == SOCK_STREAM) {
-               len = MIN(len, SOCKET_MAX_PACKET);
+       tmp.iov_base = buf;
+       tmp.iov_len = len;
+
+       msg.msg_iov = &tmp;            /* scatter/gather array */
+       msg.msg_iovlen = 1;            /* # elements in msg_iov */
+       msg.msg_control = NULL;        /* ancillary data, see below */
+       msg.msg_controllen = 0;        /* ancillary data buffer len */
+       msg.msg_flags = 0;             /* flags on received message */
+
+       tret = swrap_recvmsg_before(s, si, &msg, &tmp);
+       if (tret == -1) {
+               return -1;
        }
 
+       buf = msg.msg_iov[0].iov_base;
+       len = msg.msg_iov[0].iov_len;
+
        /* irix 6.4 forgets to null terminate the sun_path string :-( */
-       memset(&un_addr, 0, sizeof(un_addr));
+       memset(&from_addr, 0, sizeof(from_addr));
        ret = libc_recvfrom(s,
                            buf,
                            len,
                            flags,
-                           (struct sockaddr *)(void *)&un_addr,
-                           &un_addrlen);
-       if (ret == -1) 
+                           (struct sockaddr *)(void *)&from_addr,
+                           &from_addrlen);
+       if (ret == -1) {
                return ret;
+       }
 
-       if (sockaddr_convert_from_un(si, &un_addr, un_addrlen,
-                                    si->family, from, fromlen) == -1) {
-               return -1;
+       tret = swrap_recvmsg_after(si,
+                                  &msg,
+                                  &from_addr,
+                                  from_addrlen,
+                                  ret);
+       if (tret != 0) {
+               return tret;
        }
 
-       swrap_dump_packet(si, from, SWRAP_RECVFROM, buf, ret);
+       if (from != NULL && fromlen != NULL) {
+               *fromlen = msg.msg_namelen;
+       }
 
        return ret;
 }
@@ -2968,24 +3164,44 @@ ssize_t sendto(int s, const void *buf, size_t len, int 
flags,
 
 static ssize_t swrap_recv(int s, void *buf, size_t len, int flags)
 {
+       struct socket_info *si;
+       struct msghdr msg;
+       struct sockaddr_storage ss;
+       socklen_t ss_len = sizeof(ss);
+       struct iovec tmp;
        ssize_t ret;
-       struct socket_info *si = find_socket_info(s);
+       int tret;
 
-       if (!si) {
+       si = find_socket_info(s);
+       if (si == NULL) {
                return libc_recv(s, buf, len, flags);
        }
 
-       if (si->type == SOCK_STREAM) {
-               len = MIN(len, SOCKET_MAX_PACKET);
+       tmp.iov_base = buf;
+       tmp.iov_len = len;
+
+       msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
+       msg.msg_namelen = ss_len;      /* size of address */
+       msg.msg_iov = &tmp;            /* scatter/gather array */
+       msg.msg_iovlen = 1;            /* # elements in msg_iov */
+       msg.msg_control = NULL;        /* ancillary data, see below */
+       msg.msg_controllen = 0;        /* ancillary data buffer len */
+       msg.msg_flags = 0;             /* flags on received message */
+
+       tret = swrap_recvmsg_before(s, si, &msg, &tmp);
+       if (tret == -1) {
+               SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_recvmsg_before failed");
+               return -1;
        }
 
+       buf = msg.msg_iov[0].iov_base;
+       len = msg.msg_iov[0].iov_len;
+
        ret = libc_recv(s, buf, len, flags);
-       if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
-               swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
-       } else if (ret == 0) { /* END OF FILE */
-               swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
-       } else if (ret > 0) {
-               swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
+
+       tret = swrap_recvmsg_after(si, &msg, NULL, 0, ret);
+       if (tret != 0) {
+               return tret;
        }
 
        return ret;
@@ -3002,24 +3218,44 @@ ssize_t recv(int s, void *buf, size_t len, int flags)
 
 static ssize_t swrap_read(int s, void *buf, size_t len)
 {
+       struct socket_info *si;
+       struct msghdr msg;
+       struct iovec tmp;
+       struct sockaddr_storage ss;
+       socklen_t ss_len = sizeof(ss);
        ssize_t ret;
-       struct socket_info *si = find_socket_info(s);
+       int tret;
 
-       if (!si) {
+       si = find_socket_info(s);
+       if (si == NULL) {
                return libc_read(s, buf, len);
        }
 
-       if (si->type == SOCK_STREAM) {
-               len = MIN(len, SOCKET_MAX_PACKET);
+       tmp.iov_base = buf;
+       tmp.iov_len = len;
+
+       msg.msg_name = (struct sockaddr *)(void *)&ss; /* optional address */
+       msg.msg_namelen = ss_len;      /* size of address */
+       msg.msg_iov = &tmp;            /* scatter/gather array */
+       msg.msg_iovlen = 1;            /* # elements in msg_iov */
+       msg.msg_control = NULL;        /* ancillary data, see below */
+       msg.msg_controllen = 0;        /* ancillary data buffer len */
+       msg.msg_flags = 0;             /* flags on received message */
+
+       tret = swrap_recvmsg_before(s, si, &msg, &tmp);
+       if (tret == -1) {
+               SWRAP_LOG(SWRAP_LOG_ERROR, "swrap_recvmsg_before failed");
+               return -1;
        }
 
+       buf = msg.msg_iov[0].iov_base;
+       len = msg.msg_iov[0].iov_len;
+
        ret = libc_read(s, buf, len);
-       if (ret == -1 && errno != EAGAIN && errno != ENOBUFS) {
-               swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
-       } else if (ret == 0) { /* END OF FILE */
-               swrap_dump_packet(si, NULL, SWRAP_RECV_RST, NULL, 0);
-       } else if (ret > 0) {
-               swrap_dump_packet(si, NULL, SWRAP_RECV, buf, ret);
+
+       tret = swrap_recvmsg_after(si, &msg, NULL, 0, ret);
+       if (tret != 0) {
+               return tret;
        }
 
        return ret;
@@ -3082,7 +3318,48 @@ ssize_t send(int s, const void *buf, size_t len, int 
flags)
  *   RECVMSG
  ***************************************************************************/
 
-/* TODO */
+static ssize_t swrap_recvmsg(int s, struct msghdr *omsg, int flags)
+{
+       struct sockaddr_un from_addr;
+       socklen_t from_addrlen = sizeof(from_addr);
+       struct socket_info *si;
+       struct msghdr msg;
+       struct iovec tmp;
+
+       ssize_t ret;
+       int rc;
+
+       si = find_socket_info(s);
+       if (si == NULL) {
+               return libc_recvmsg(s, omsg, flags);
+       }
+
+       rc = swrap_recvmsg_before(s, si, omsg, &tmp);
+       if (rc == -1) {
+               return -1;
+       }
+
+       msg = *omsg;
+       tmp.iov_base = msg.msg_iov;
+       tmp.iov_len = msg.msg_iovlen;
+
+       msg.msg_name = (struct sockaddr *)&from_addr;
+       msg.msg_namelen = from_addrlen;
+
+       ret = libc_recvmsg(s, &msg, flags);
+
+       rc = swrap_recvmsg_after(si, omsg, &from_addr, from_addrlen, ret);
+       if (rc != 0) {
+               return rc;
+       }
+
+       return ret;
+}
+
+ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)
+{
+       return swrap_recvmsg(sockfd, msg, flags);
+}
 
 /****************************************************************************
  *   SENDMSG
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 45db1db..c626c02 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -24,7 +24,9 @@ set(SWRAP_TESTS
     test_echo_tcp_write_read
     test_echo_tcp_writev_readv
     test_echo_udp_sendto_recvfrom
-    test_echo_udp_send_recv)
+    test_echo_udp_send_recv
+    test_echo_udp_sendmsg_recvmsg
+    test_sendmsg_recvmsg_fd)
 
 foreach(_SWRAP_TEST ${SWRAP_TESTS})
     add_cmocka_test(${_SWRAP_TEST} ${_SWRAP_TEST}.c ${TORTURE_LIBRARY})
diff --git a/tests/test_echo_udp_sendto_recvfrom.c 
b/tests/test_echo_udp_sendmsg_recvmsg.c
similarity index 71%
copy from tests/test_echo_udp_sendto_recvfrom.c
copy to tests/test_echo_udp_sendmsg_recvmsg.c
index b0ed24a..caabdb4 100644
--- a/tests/test_echo_udp_sendto_recvfrom.c
+++ b/tests/test_echo_udp_sendmsg_recvmsg.c
@@ -62,23 +62,39 @@ static void test_sendto_recvfrom_ipv4(void **state)
                const char *a;
                struct sockaddr_in srv_in;
                socklen_t rlen = sizeof(srv_in);
+               struct msghdr s_msg;
+               struct msghdr r_msg;
+               struct iovec s_iov;
+               struct iovec r_iov;
 
                snprintf(send_buf, sizeof(send_buf), "packet.%d", i);
 
-               ret = sendto(s,
-                            send_buf,
-                            sizeof(send_buf),
-                            0,
-                            (struct sockaddr *)(void *)&sin,
-                            slen);
+               ZERO_STRUCT(s_msg);
+
+               s_msg.msg_name = (struct sockaddr *)(void *)&sin;
+               s_msg.msg_namelen = slen;
+
+               s_iov.iov_base = send_buf;
+               s_iov.iov_len = sizeof(send_buf);
+
+               s_msg.msg_iov = &s_iov;
+               s_msg.msg_iovlen = 1;
+
+               ret = sendmsg(s, &s_msg, 0);
                assert_int_not_equal(ret, -1);
 
-               ret = recvfrom(s,
-                              recv_buf,
-                              sizeof(recv_buf),
-                              0,
-                              (struct sockaddr *)&srv_in,


-- 
Socket Wrapper Repository

Reply via email to