[SCM] Socket Wrapper Repository - branch master updated

Andreas Schneider asn at samba.org
Mon Jan 20 15:19:54 MST 2014


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 <jhrozek at redhat.com>
Date:   Mon Jan 20 13:45:58 2014 +0100

    tests: Add sendmsg_recvmsg_fd test.

commit c29f7596696ec67fdf9ad2c860362bd0fc1516ae
Author: Andreas Schneider <asn at samba.org>
Date:   Mon Jan 20 18:36:47 2014 +0100

    tests: Add test_echo_udp_sendmsg_recvmsg.

commit ae88bf8a6894df56f0be77610d47a0f3730c8804
Author: Andreas Schneider <asn at samba.org>
Date:   Wed Jan 15 16:55:20 2014 +0100

    swrap: Implement recvmsg().

commit 6d328a234f8e5557a2e6898aff4bc92ace4b8b01
Author: Andreas Schneider <asn at samba.org>
Date:   Tue Dec 24 13:06:40 2013 +0100

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

commit 11b077a674fa146b2744f6cd4c5f947e7d1f531d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Dec 24 11:37:29 2013 +0100

    swrap: Use swrap_recvmsg_* in swrap_read().

commit 7e5f1f5abc66dff745cb4cc2bcf187189fa19d12
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Dec 24 11:35:16 2013 +0100

    swrap: Use swrap_recvmsg_* in swrap_recv().

commit 35bcc16674140864e2816cb6a5a536afaed9e597
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Dec 24 11:31:50 2013 +0100

    swrap: Use swrap_recvmsg_* in swrap_recvfrom().

commit e11fd61be098aed3ed2b16e6ed9fe12e6a8f2b13
Author: Stefan Metzmacher <metze at samba.org>
Date:   Tue Dec 24 11:28:29 2013 +0100

    swrap: Add swrap_recvmsg_after().

commit 76ff3d42b48c0d25d505496d3e90f50fe7d6f9db
Author: Stefan Metzmacher <metze at samba.org>
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


More information about the samba-cvs mailing list