From patchwork Tue Jun 27 08:24:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Florian Weimer X-Patchwork-Id: 21283 Received: (qmail 125304 invoked by alias); 27 Jun 2017 08:24:36 -0000 Mailing-List: contact libc-alpha-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: libc-alpha-owner@sourceware.org Delivered-To: mailing list libc-alpha@sourceware.org Received: (qmail 124960 invoked by uid 89); 27 Jun 2017 08:24:04 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.4 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_SORBS_SPAM, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=loopback, SERVFAIL, servfail X-HELO: mx1.redhat.com DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com EB2C3FEF15 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=fweimer@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com EB2C3FEF15 Date: Tue, 27 Jun 2017 10:24:00 +0200 To: libc-alpha@sourceware.org Subject: [PATCH COMMITTED] resolv: Avoid timeouts in test-resolv-res-init, test-resolv-res_init-thread User-Agent: Heirloom mailx 12.5 7/5/10 MIME-Version: 1.0 Message-Id: <20170627082400.ADDCB439942F0@oldenburg.str.redhat.com> From: fweimer@redhat.com (Florian Weimer) Some Linux kernels have very aggressive ICMP rate limiting on the loopback interface. This commit introduces a minimal echoing DNS server inside the network namespace, so that there is no need for ICMP error messages anymore. 2017-06-27 Florian Weimer Work around test timeouts with ICMP rate limiting on localhost. * resolv/tst-resolv-res_init-skeleton.c (start_dummy_server): New function. (do_test): Call it. diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c index 1d2c475..2b68c5f 100644 --- a/resolv/tst-resolv-res_init-skeleton.c +++ b/resolv/tst-resolv-res_init-skeleton.c @@ -21,6 +21,7 @@ in. */ #include +#include #include #include #include /* For DEPRECATED_RES_USE_INET6. */ @@ -33,6 +34,7 @@ #include #include #include +#include #include #include @@ -527,6 +529,73 @@ test_file_contents (const struct test_case *t) } } +/* Dummy DNS server. It ensures that the probe queries sent by + gethostbyname and getaddrinfo receive a reply even if the system + applies a very strict rate limit to localhost. */ +static pid_t +start_dummy_server (void) +{ + int server_socket = xsocket (AF_INET, SOCK_DGRAM, 0); + { + struct sockaddr_in sin = + { + .sin_family = AF_INET, + .sin_addr = { .s_addr = htonl (INADDR_LOOPBACK) }, + .sin_port = htons (53), + }; + int ret = bind (server_socket, (struct sockaddr *) &sin, sizeof (sin)); + if (ret < 0) + { + if (errno == EACCES) + /* The port is reserved, which means we cannot start the + server. */ + return -1; + FAIL_EXIT1 ("cannot bind socket to port 53: %m"); + } + } + + pid_t pid = xfork (); + if (pid == 0) + { + /* Child process. Echo back queries as SERVFAIL responses. */ + while (true) + { + union + { + HEADER header; + unsigned char bytes[512]; + } packet; + struct sockaddr_in sin; + socklen_t sinlen = sizeof (sin); + + ssize_t ret = recvfrom + (server_socket, &packet, sizeof (packet), + MSG_NOSIGNAL, (struct sockaddr *) &sin, &sinlen); + if (ret < 0) + FAIL_EXIT1 ("recvfrom on fake server socket: %m"); + if (ret > sizeof (HEADER)) + { + /* Turn the query into a SERVFAIL response. */ + packet.header.qr = 1; + packet.header.rcode = ns_r_servfail; + + /* Send the response. */ + ret = sendto (server_socket, &packet, ret, + MSG_NOSIGNAL, (struct sockaddr *) &sin, sinlen); + if (ret < 0) + /* The peer may have closed socket prematurely, so + this is not an error. */ + printf ("warning: sending DNS server reply: %m\n"); + } + } + } + + /* In the parent, close the socket. */ + xclose (server_socket); + + return pid; +} + static int do_test (void) { @@ -552,6 +621,8 @@ do_test (void) support_capture_subprocess_free (&proc); } + pid_t server = start_dummy_server (); + for (size_t i = 0; test_cases[i].name != NULL; ++i) { if (test_verbose > 0) @@ -590,6 +661,13 @@ do_test (void) } } + if (server > 0) + { + if (kill (server, SIGTERM) < 0) + FAIL_EXIT1 ("could not terminate server process: %m"); + xwaitpid (server, NULL, 0); + } + free (path_chroot); path_chroot = NULL; free (path_resolv_conf);