]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
* resolv/resolv.h (RES_SNGLKUP): Define. cvs/fedora-glibc-20090407T0545
authorUlrich Drepper <drepper@redhat.com>
Tue, 7 Apr 2009 02:00:27 +0000 (02:00 +0000)
committerUlrich Drepper <drepper@redhat.com>
Tue, 7 Apr 2009 02:00:27 +0000 (02:00 +0000)
* resolv/res_init.c (res_setoptions): Recognize single-request option.
* resolv/res_send.c (send_dg): If we sent two requests at once and
only get one reply before timeout switch to mode where we send the
second request only after the first answer has been received.

ChangeLog
resolv/res_init.c
resolv/res_send.c
resolv/resolv.h

index 44f1ebcb72206916c65ab689c2e095ce4776fb67..0646e39c0405fd2fb393dbe84c7b66d18d753aa0 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2009-04-06  Ulrich Drepper  <drepper@redhat.com>
+
+       * resolv/resolv.h (RES_SNGLKUP): Define.
+       * resolv/res_init.c (res_setoptions): Recognize single-request option.
+       * resolv/res_send.c (send_dg): If we sent two requests at once and
+       only get one reply before timeout switch to mode where we send the
+       second request only after the first answer has been received.
+
 2009-04-05  Ulrich Drepper  <drepper@redhat.com>
 
        * sysdeps/x86_64/strlen.S: Optimize by using SSE2 instructions.
index 2bf830cc950457da353814d05b5ef487a1276179..8841fe9faaafdd1d06bbcbe5ee11261fed66b473 100644 (file)
@@ -540,6 +540,9 @@ res_setoptions(res_state statp, const char *options, const char *source) {
                        statp->options |= RES_NOCHECKNAME;
                 } else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
                        statp->options |= RES_USE_EDNS0;
+                } else if (!strncmp(cp, "single-request",
+                                   sizeof("single-request") - 1)) {
+                       statp->options |= RES_SNGLKUP;
                } else {
                        /* XXX - print a warning here? */
                }
index f75a26ec23e4a870679058f2889ae6222181bd9d..0490b52fca6cc869c12915d7446d42460c0af14a 100644 (file)
@@ -923,12 +923,12 @@ send_dg(res_state statp,
        struct pollfd pfd[1];
         int ptimeout;
        struct sockaddr_in6 from;
-       int resplen, seconds, n;
+       int resplen, n;
 
        if (EXT(statp).nssocks[ns] == -1) {
                /* only try IPv6 if IPv6 NS and if not failed before */
                if ((EXT(statp).nscount6 > 0) && !statp->ipv6_unavail) {
-                       if (__have_o_nonblock >= 0) {
+                       if (__builtin_expect (__have_o_nonblock >= 0, 1)) {
                                EXT(statp).nssocks[ns] =
                                  socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK,
                                         0);
@@ -939,7 +939,7 @@ send_dg(res_state statp,
                                             && errno == EINVAL ? -1 : 1);
 #endif
                        }
-                       if (__have_o_nonblock < 0)
+                       if (__builtin_expect (__have_o_nonblock < 0, 0))
                                EXT(statp).nssocks[ns] =
                                  socket(PF_INET6, SOCK_DGRAM, 0);
                        if (EXT(statp).nssocks[ns] < 0)
@@ -950,7 +950,7 @@ send_dg(res_state statp,
                            convaddr4to6(nsap);
                }
                if (EXT(statp).nssocks[ns] < 0) {
-                       if (__have_o_nonblock >= 0) {
+                       if (__builtin_expect (__have_o_nonblock >= 0, 1)) {
                                EXT(statp).nssocks[ns]
                                  = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK,
                                           0);
@@ -961,7 +961,7 @@ send_dg(res_state statp,
                                             && errno == EINVAL ? -1 : 1);
 #endif
                        }
-                       if (__have_o_nonblock < 0)
+                       if (__builtin_expect (__have_o_nonblock < 0, 0))
                                EXT(statp).nssocks[ns]
                                  = socket(PF_INET, SOCK_DGRAM, 0);
                }
@@ -989,7 +989,7 @@ send_dg(res_state statp,
                        __res_iclose(statp, false);
                        return (0);
                }
-               if (__have_o_nonblock < 0) {
+               if (__builtin_expect (__have_o_nonblock < 0, 0)) {
                        /* Make socket non-blocking.  */
                        int fl = __fcntl (EXT(statp).nssocks[ns], F_GETFL);
                        if  (fl != -1)
@@ -1003,11 +1003,14 @@ send_dg(res_state statp,
        /*
         * Compute time for the total operation.
         */
-       seconds = (statp->retrans << ns);
+       int seconds = (statp->retrans << ns);
        if (ns > 0)
                seconds /= statp->nscount;
        if (seconds <= 0)
                seconds = 1;
+       bool single_request = ((statp->options) & RES_SNGLKUP) != 0;// XXX
+       int save_gotsomewhere = *gotsomewhere;
+ retry:
        evNowTime(&now);
        evConsTime(&timeout, seconds, 0);
        evAddTime(&finish, &now, &timeout);
@@ -1031,6 +1034,7 @@ send_dg(res_state statp,
                        return (0);
                }
                evSubTime(&timeout, &finish, &now);
+               need_recompute = 0;
        }
         /* Convert struct timespec in milliseconds.  */
        ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000;
@@ -1046,8 +1050,16 @@ send_dg(res_state statp,
                Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
                if (resplen > 1 && (recvresp1 || (buf2 != NULL && recvresp2)))
                  {
-                   *resplen2 = 1;
-                   return resplen;
+                   /* There are quite a few broken name servers out
+                      there which don't handle two outstanding
+                      requests from the same source.  There are also
+                      broken firewall settings.  If we time out after
+                      having received one answer switch to the mode
+                      where we send the second request only once we
+                      have received the first answer.  */
+                   single_request = true;
+                   *gotsomewhere = save_gotsomewhere;
+                   goto retry;
                  }
 
                *gotsomewhere = 1;
@@ -1073,7 +1085,7 @@ send_dg(res_state statp,
                        Perror(statp, stderr, "send", errno);
                        goto err_out;
                }
-               if (nwritten != 0 || buf2 == NULL)
+               if (nwritten != 0 || buf2 == NULL || single_request)
                  pfd[0].events = POLLIN;
                else
                  pfd[0].events = POLLIN | POLLOUT;
@@ -1286,8 +1298,11 @@ send_dg(res_state statp,
                else
                        recvresp2 = 1;
                /* Repeat waiting if we have a second answer to arrive.  */
-               if ((recvresp1 & recvresp2) == 0)
+               if ((recvresp1 & recvresp2) == 0) {
+                       if (single_request)
+                               pfd[0].events = POLLOUT;
                        goto wait;
+               }
                /*
                 * All is well, or the error is fatal.  Signal that the
                 * next nameserver ought not be tried.
index a0de320d0f765da6b25c52e55c88f3c6c1ea1dbc..c6e695dc727f69f947231acb3b9fd58ab2664fcf 100644 (file)
@@ -215,6 +215,7 @@ struct res_sym {
 #define RES_NOIP6DOTINT        0x00080000      /* Do not use .ip6.int in IPv6
                                           reverse lookup */
 #define RES_USE_EDNS0  0x00100000      /* Use EDNS0.  */
+#define RES_SNGLKUP    0x00200000      /* one outstanding request at a time */
 
 #define RES_DEFAULT    (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT)