Skip to content

Commit

Permalink
* resolv/resolv.h (RES_SNGLKUP): Define.
Browse files Browse the repository at this point in the history
	* 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.
  • Loading branch information
Ulrich Drepper committed Apr 7, 2009
1 parent 735be40 commit ae06191
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 11 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
3 changes: 3 additions & 0 deletions resolv/res_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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? */
}
Expand Down
37 changes: 26 additions & 11 deletions resolv/res_send.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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)
Expand All @@ -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);
Expand All @@ -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);
}
Expand Down Expand Up @@ -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)
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions resolv/resolv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down

0 comments on commit ae06191

Please sign in to comment.