summaryrefslogtreecommitdiff
path: root/resolv
diff options
context:
space:
mode:
authorThomas Schwinge <thomas@codesourcery.com>2012-07-22 19:58:41 +0200
committerThomas Schwinge <thomas@codesourcery.com>2012-07-22 19:58:41 +0200
commitef724a37cdb3012efb5b7233eb8b450ad91d3d69 (patch)
tree2334455220f417223cc1a75aebe76302cdffdf5a /resolv
parent6f276c2517990f6569b961b4d4919cbce570ac45 (diff)
parent47e5dcdf349a1aea5c8997104ef785412f0d34fa (diff)
Merge branch 'baseline' into refs/top-bases/tschwinge/Roger_Whittaker
Conflicts: configure configure.in elf/rtld.c misc/syslog.c sysdeps/gnu/configure sysdeps/gnu/configure.in sysdeps/mach/hurd/accept4.c sysdeps/mach/hurd/bits/posix_opt.h sysdeps/mach/hurd/dup3.c sysdeps/mach/hurd/i386/init-first.c sysdeps/mach/hurd/kernel-features.h sysdeps/mach/hurd/readlinkat.c
Diffstat (limited to 'resolv')
-rw-r--r--resolv/nss_dns/dns-host.c21
-rw-r--r--resolv/res_send.c102
2 files changed, 103 insertions, 20 deletions
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 10aecb8604..a924d40844 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2004, 2007-2009, 2010 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2012 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
@@ -744,6 +744,10 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME)
{
+ /* A CNAME could also have a TTL entry. */
+ if (ttlp != NULL && ttl < *ttlp)
+ *ttlp = ttl;
+
if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
continue;
n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
@@ -905,7 +909,10 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
{
register int nn;
- if (ttlp != NULL)
+ /* We compose a single hostent out of the entire chain of
+ entries, so the TTL of the hostent is essentially the lowest
+ TTL in the chain. */
+ if (ttlp != NULL && ttl < *ttlp)
*ttlp = ttl;
if (canonp != NULL)
*canonp = bp;
@@ -1081,6 +1088,11 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
if (type == T_CNAME)
{
char tbuf[MAXDNAME];
+
+ /* A CNAME could also have a TTL entry. */
+ if (ttlp != NULL && ttl < *ttlp)
+ *ttlp = ttl;
+
n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
if (__builtin_expect (n < 0 || res_hnok (tbuf) == 0, 0))
{
@@ -1161,7 +1173,10 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
if (*firstp)
{
- if (ttlp != NULL)
+ /* We compose a single hostent out of the entire chain of
+ entries, so the TTL of the hostent is essentially the lowest
+ TTL in the chain. */
+ if (ttlp != NULL && ttl < *ttlp)
*ttlp = ttl;
(*pat)->name = canon ?: h_name;
diff --git a/resolv/res_send.c b/resolv/res_send.c
index a001c1e753..0a28cd784b 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -1013,8 +1013,9 @@ send_dg(res_state statp,
seconds /= statp->nscount;
if (seconds <= 0)
seconds = 1;
- bool single_request = (statp->options & RES_SNGLKUP) != 0;
bool single_request_reopen = (statp->options & RES_SNGLKUPREOP) != 0;
+ bool single_request = (((statp->options & RES_SNGLKUP) != 0)
+ | single_request_reopen);
int save_gotsomewhere = *gotsomewhere;
int retval;
@@ -1100,24 +1101,91 @@ send_dg(res_state statp,
}
__set_errno (0);
if (pfd[0].revents & POLLOUT) {
- ssize_t sr;
- if (nwritten != 0)
- sr = send (pfd[0].fd, buf2, buflen2, MSG_NOSIGNAL);
- else
- sr = send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL);
+#ifndef __ASSUME_SENDMMSG
+ static int have_sendmmsg;
+#else
+# define have_sendmmsg 1
+#endif
+ if (have_sendmmsg >= 0 && nwritten == 0 && buf2 != NULL
+ && !single_request)
+ {
+ struct iovec iov[2];
+ struct mmsghdr reqs[2];
+ reqs[0].msg_hdr.msg_name = NULL;
+ reqs[0].msg_hdr.msg_namelen = 0;
+ reqs[0].msg_hdr.msg_iov = &iov[0];
+ reqs[0].msg_hdr.msg_iovlen = 1;
+ iov[0].iov_base = (void *) buf;
+ iov[0].iov_len = buflen;
+ reqs[0].msg_hdr.msg_control = NULL;
+ reqs[0].msg_hdr.msg_controllen = 0;
+
+ reqs[1].msg_hdr.msg_name = NULL;
+ reqs[1].msg_hdr.msg_namelen = 0;
+ reqs[1].msg_hdr.msg_iov = &iov[1];
+ reqs[1].msg_hdr.msg_iovlen = 1;
+ iov[1].iov_base = (void *) buf2;
+ iov[1].iov_len = buflen2;
+ reqs[1].msg_hdr.msg_control = NULL;
+ reqs[1].msg_hdr.msg_controllen = 0;
+
+ int ndg = sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL);
+ if (__builtin_expect (ndg == 2, 1))
+ {
+ if (reqs[0].msg_len != buflen
+ || reqs[1].msg_len != buflen2)
+ goto fail_sendmmsg;
- if (sr != buflen) {
- if (errno == EINTR || errno == EAGAIN)
- goto recompute_resend;
- Perror(statp, stderr, "send", errno);
+ pfd[0].events = POLLIN;
+ nwritten += 2;
+ }
+ else if (ndg == 1 && reqs[0].msg_len == buflen)
+ goto just_one;
+ else if (ndg < 0 && (errno == EINTR || errno == EAGAIN))
+ goto recompute_resend;
+ else
+ {
+#ifndef __ASSUME_SENDMMSG
+ if (__builtin_expect (have_sendmmsg == 0, 0))
+ {
+ if (ndg < 0 && errno == ENOSYS)
+ {
+ have_sendmmsg = -1;
+ goto try_send;
+ }
+ have_sendmmsg = 1;
+ }
+#endif
+
+ fail_sendmmsg:
+ Perror(statp, stderr, "sendmmsg", errno);
goto err_out;
- }
- if (nwritten != 0 || buf2 == NULL
- || single_request || single_request_reopen)
- pfd[0].events = POLLIN;
+ }
+ }
else
- pfd[0].events = POLLIN | POLLOUT;
- ++nwritten;
+ {
+ ssize_t sr;
+#ifndef __ASSUME_SENDMMSG
+ try_send:
+#endif
+ if (nwritten != 0)
+ sr = send (pfd[0].fd, buf2, buflen2, MSG_NOSIGNAL);
+ else
+ sr = send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL);
+
+ if (sr != (nwritten != 0 ? buflen2 : buflen)) {
+ if (errno == EINTR || errno == EAGAIN)
+ goto recompute_resend;
+ Perror(statp, stderr, "send", errno);
+ goto err_out;
+ }
+ just_one:
+ if (nwritten != 0 || buf2 == NULL || single_request)
+ pfd[0].events = POLLIN;
+ else
+ pfd[0].events = POLLIN | POLLOUT;
+ ++nwritten;
+ }
goto wait;
} else if (pfd[0].revents & POLLIN) {
int *thisanssizp;
@@ -1327,7 +1395,7 @@ send_dg(res_state statp,
recvresp2 = 1;
/* Repeat waiting if we have a second answer to arrive. */
if ((recvresp1 & recvresp2) == 0) {
- if (single_request || single_request_reopen) {
+ if (single_request) {
pfd[0].events = POLLOUT;
if (single_request_reopen) {
__res_iclose (statp, false);