]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
ISC_SOCKEVENTATTR_TRUNC was not be set
authorMark Andrews <marka@isc.org>
Tue, 1 May 2018 06:52:01 +0000 (16:52 +1000)
committerMark Andrews <marka@isc.org>
Fri, 18 May 2018 06:02:04 +0000 (16:02 +1000)
(cherry picked from commit 6bff1768cfeb156f05a3a6078d79afa9c98b29b3)

CHANGES
lib/isc/tests/socket_test.c
lib/isc/unix/socket.c

diff --git a/CHANGES b/CHANGES
index bb9169d313236f1cd5a147bdfbdcf10ae86917fc..dad45a87e052bcc81fe0ccf0144659480e73b73c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,5 @@
+4950.  [bug]           ISC_SOCKEVENTATTR_TRUNC was not be set. [GL #238]
+
 4949.  [bug]           lib/isc/print.c failed to handle floating point
                        output correctly. [GL #261]
 
index e5e4f7105dff236d0ac77f66f829d35156677154..c867b1f7e87970b335aef57d563968b95e372111 100644 (file)
@@ -33,6 +33,7 @@
 
 static isc_boolean_t recv_dscp;
 static unsigned int recv_dscp_value;
+static isc_boolean_t recv_trunc;
 
 /*
  * Helper functions
@@ -78,8 +79,10 @@ event_done(isc_task_t *task, isc_event_t *event) {
        if ((dev->attributes & ISC_SOCKEVENTATTR_DSCP) != 0) {
                recv_dscp = ISC_TRUE;
                recv_dscp_value = dev->dscp;;
-       } else
+       } else {
                recv_dscp = ISC_FALSE;
+       }
+       recv_trunc = ISC_TF((dev->attributes & ISC_SOCKEVENTATTR_TRUNC) != 0);
        isc_event_free(&event);
 }
 
@@ -782,6 +785,131 @@ ATF_TC_BODY(net_probedscp, tc) {
 #endif
 }
 
+/* Test UDP truncation detection */
+ATF_TC(udp_trunc);
+ATF_TC_HEAD(udp_trunc, tc) {
+       atf_tc_set_md_var(tc, "descr", "UDP Truncation detection");
+}
+ATF_TC_BODY(udp_trunc, tc) {
+       isc_result_t result;
+       isc_sockaddr_t addr1, addr2;
+       struct in_addr in;
+       isc_socket_t *s1 = NULL, *s2 = NULL;
+       isc_task_t *task = NULL;
+       char sendbuf[BUFSIZ*2], recvbuf[BUFSIZ];
+       completion_t completion;
+       isc_region_t r;
+       isc_socketevent_t *socketevent;
+
+       UNUSED(tc);
+
+       result = isc_test_begin(NULL, ISC_TRUE, 0);
+       ATF_REQUIRE_EQ(result, ISC_R_SUCCESS);
+
+       in.s_addr = inet_addr("127.0.0.1");
+       isc_sockaddr_fromin(&addr1, &in, 0);
+       isc_sockaddr_fromin(&addr2, &in, 0);
+
+       result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s1);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+       result = isc_socket_bind(s1, &addr1, ISC_SOCKET_REUSEADDRESS);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+       result = isc_socket_getsockname(s1, &addr1);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                        isc_result_totext(result));
+       ATF_REQUIRE(isc_sockaddr_getport(&addr1) != 0);
+
+       result = isc_socket_create(socketmgr, PF_INET, isc_sockettype_udp, &s2);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+       result = isc_socket_bind(s2, &addr2, ISC_SOCKET_REUSEADDRESS);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+       result = isc_socket_getsockname(s2, &addr2);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                        isc_result_totext(result));
+       ATF_REQUIRE(isc_sockaddr_getport(&addr2) != 0);
+
+       result = isc_task_create(taskmgr, 0, &task);
+       ATF_CHECK_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+
+       /*
+        * Send a message that will not be truncated.
+        */
+       memset(sendbuf, 0xff, sizeof(sendbuf));
+       snprintf(sendbuf, sizeof(sendbuf), "Hello");
+       r.base = (void *) sendbuf;
+       r.length = strlen(sendbuf) + 1;
+
+       completion_init(&completion);
+
+       socketevent = isc_socket_socketevent(mctx, s1, ISC_SOCKEVENT_SENDDONE,
+                                            event_done, &completion);
+       ATF_REQUIRE(socketevent != NULL);
+
+       result = isc_socket_sendto2(s1, &r, task, &addr2, NULL, socketevent, 0);
+       ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+
+       r.base = (void *) recvbuf;
+       r.length = BUFSIZ;
+       completion_init(&completion);
+       recv_trunc = ISC_FALSE;
+       result = isc_socket_recv(s2, &r, 1, task, event_done, &completion);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(recvbuf, "Hello");
+       ATF_CHECK_EQ(recv_trunc, ISC_FALSE);
+
+       /*
+        * Send a message that will be truncated.
+        */
+       memset(sendbuf, 0xff, sizeof(sendbuf));
+       snprintf(sendbuf, sizeof(sendbuf), "Hello");
+       r.base = (void *) sendbuf;
+       r.length = sizeof(sendbuf);
+
+       completion_init(&completion);
+
+       socketevent = isc_socket_socketevent(mctx, s1, ISC_SOCKEVENT_SENDDONE,
+                                            event_done, &completion);
+       ATF_REQUIRE(socketevent != NULL);
+
+       result = isc_socket_sendto2(s1, &r, task, &addr2, NULL, socketevent, 0);
+       ATF_REQUIRE_EQ_MSG(result, ISC_R_SUCCESS, "%s",
+                          isc_result_totext(result));
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+
+       r.base = (void *) recvbuf;
+       r.length = BUFSIZ;
+       completion_init(&completion);
+       recv_trunc = ISC_FALSE;
+       result = isc_socket_recv(s2, &r, 1, task, event_done, &completion);
+       ATF_CHECK_EQ(result, ISC_R_SUCCESS);
+       waitfor(&completion);
+       ATF_CHECK(completion.done);
+       ATF_CHECK_EQ(completion.result, ISC_R_SUCCESS);
+       ATF_CHECK_STREQ(recvbuf, "Hello");
+       ATF_CHECK_EQ(recv_trunc, ISC_TRUE);
+
+       isc_task_detach(&task);
+
+       isc_socket_detach(&s1);
+       isc_socket_detach(&s2);
+
+       isc_test_end();
+}
+
 /*
  * Main
  */
@@ -793,6 +921,7 @@ ATF_TP_ADD_TCS(tp) {
        ATF_TP_ADD_TC(tp, udp_dscp_v4);
        ATF_TP_ADD_TC(tp, udp_dscp_v6);
        ATF_TP_ADD_TC(tp, net_probedscp);
+       ATF_TP_ADD_TC(tp, udp_trunc);
 
        return (atf_no_error());
 }
index 2bcbb39762fbf7367bd9ea5ccf5c5f6fc85af8ae..2a2a5b08efb54be972dc97c1d52183cb1bcd154d 100644 (file)
@@ -370,7 +370,7 @@ struct isc__socket {
                                active : 1,         /* currently active */
                                pktdscp : 1;        /* per packet dscp */
 
-#ifdef ISC_NET_RECVOVERFLOW
+#ifdef ISC_PLATFORM_RECVOVERFLOW
        unsigned char           overflow; /* used for MSG_TRUNC fake */
 #endif
 
@@ -462,7 +462,7 @@ static isc__socketmgr_t *socketmgr = NULL;
  * send() and recv() iovec counts
  */
 #define MAXSCATTERGATHER_SEND  (ISC_SOCKET_MAXSCATTERGATHER)
-#ifdef ISC_NET_RECVOVERFLOW
+#ifdef ISC_PLATFORM_RECVOVERFLOW
 # define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER + 1)
 #else
 # define MAXSCATTERGATHER_RECV (ISC_SOCKET_MAXSCATTERGATHER)
@@ -1697,10 +1697,6 @@ build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev,
 #else
                msg->msg_name = (void *)&dev->address.type.sa;
                msg->msg_namelen = sizeof(dev->address.type);
-#endif
-#ifdef ISC_NET_RECVOVERFLOW
-               /* If needed, steal one iovec for overflow detection. */
-               maxiov--;
 #endif
        } else { /* TCP */
                msg->msg_name = NULL;
@@ -1752,12 +1748,11 @@ build_msghdr_recv(isc__socket_t *sock, isc_socketevent_t *dev,
  config:
 
        /*
-        * If needed, set up to receive that one extra byte.  Note that
-        * we know there is at least one iov left, since we stole it
-        * at the top of this function.
+        * If needed, set up to receive that one extra byte.
         */
-#ifdef ISC_NET_RECVOVERFLOW
+#ifdef ISC_PLATFORM_RECVOVERFLOW
        if (sock->type == isc_sockettype_udp) {
+               INSIST(iovcount < MAXSCATTERGATHER_RECV);
                iov[iovcount].iov_base = (void *)(&sock->overflow);
                iov[iovcount].iov_len = 1;
                iovcount++;
@@ -1994,7 +1989,7 @@ doio_recv(isc__socket_t *sock, isc_socketevent_t *dev) {
         * this indicates an overflow situation.  Set the flag in the
         * dev entry and adjust how much we read by one.
         */
-#ifdef ISC_NET_RECVOVERFLOW
+#ifdef ISC_PLATFORM_RECVOVERFLOW
        if ((sock->type == isc_sockettype_udp) && ((size_t)cc > read_count)) {
                dev->attributes |= ISC_SOCKEVENTATTR_TRUNC;
                cc--;