mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
Implement second fallback mode for DNS requests.
There is some more shardware/software out there which has problems if two DNS requests are sent using the same tuple (source addr, source port, dest addr, dest port) This can range from firewalls to load balancers. Some of the vendors already fixed it in response to this problem. Still, we need a way to make glibc work with broken environments. The single-request-reopen flag can be used or we fall back automatically to this mode.
This commit is contained in:
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
|||||||
|
2009-06-26 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* resolv/resolv.h: Define RES_SNGLKUPREOP.
|
||||||
|
* resolv/res_init.c (res_setoptions): Recognize single-request-reopen
|
||||||
|
option.
|
||||||
|
* resolv/res_send.c (reopen): New function. Broken out of...
|
||||||
|
(send_dg): ... here. Recognize RES_SNGLKUPREOP. Implement second
|
||||||
|
fallback mechanism. If single-request fails switch to
|
||||||
|
single-request-reopen mode which opens a new socket for the second
|
||||||
|
request.
|
||||||
|
|
||||||
2009-06-25 Andreas Schwab <aschwab@redhat.com>
|
2009-06-25 Andreas Schwab <aschwab@redhat.com>
|
||||||
|
|
||||||
* sysdeps/powerpc/powerpc32/____longjmp_chk.S (LOAD_ARG): Define.
|
* sysdeps/powerpc/powerpc32/____longjmp_chk.S (LOAD_ARG): Define.
|
||||||
|
@ -540,6 +540,9 @@ res_setoptions(res_state statp, const char *options, const char *source) {
|
|||||||
statp->options |= RES_NOCHECKNAME;
|
statp->options |= RES_NOCHECKNAME;
|
||||||
} else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
|
} else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
|
||||||
statp->options |= RES_USE_EDNS0;
|
statp->options |= RES_USE_EDNS0;
|
||||||
|
} else if (!strncmp(cp, "single-request-reopen",
|
||||||
|
sizeof("single-request-reopen") - 1)) {
|
||||||
|
statp->options |= RES_SNGLKUPREOP;
|
||||||
} else if (!strncmp(cp, "single-request",
|
} else if (!strncmp(cp, "single-request",
|
||||||
sizeof("single-request") - 1)) {
|
sizeof("single-request") - 1)) {
|
||||||
statp->options |= RES_SNGLKUP;
|
statp->options |= RES_SNGLKUP;
|
||||||
|
@ -908,24 +908,11 @@ send_vc(res_state statp,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
send_dg(res_state statp,
|
reopen (res_state statp, int *terrno, int ns)
|
||||||
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
|
|
||||||
u_char **ansp, int *anssizp,
|
|
||||||
int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
|
|
||||||
u_char **ansp2, int *anssizp2, int *resplen2)
|
|
||||||
{
|
{
|
||||||
const HEADER *hp = (HEADER *) buf;
|
|
||||||
const HEADER *hp2 = (HEADER *) buf2;
|
|
||||||
u_char *ans = *ansp;
|
|
||||||
int orig_anssizp = *anssizp;
|
|
||||||
struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
|
|
||||||
struct timespec now, timeout, finish;
|
|
||||||
struct pollfd pfd[1];
|
|
||||||
int ptimeout;
|
|
||||||
struct sockaddr_in6 from;
|
|
||||||
int resplen, n;
|
|
||||||
|
|
||||||
if (EXT(statp).nssocks[ns] == -1) {
|
if (EXT(statp).nssocks[ns] == -1) {
|
||||||
|
struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
|
||||||
|
|
||||||
/* only try IPv6 if IPv6 NS and if not failed before */
|
/* only try IPv6 if IPv6 NS and if not failed before */
|
||||||
if ((EXT(statp).nscount6 > 0) && !statp->ipv6_unavail) {
|
if ((EXT(statp).nscount6 > 0) && !statp->ipv6_unavail) {
|
||||||
if (__builtin_expect (__have_o_nonblock >= 0, 1)) {
|
if (__builtin_expect (__have_o_nonblock >= 0, 1)) {
|
||||||
@ -1000,6 +987,26 @@ send_dg(res_state statp,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
send_dg(res_state statp,
|
||||||
|
const u_char *buf, int buflen, const u_char *buf2, int buflen2,
|
||||||
|
u_char **ansp, int *anssizp,
|
||||||
|
int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp,
|
||||||
|
u_char **ansp2, int *anssizp2, int *resplen2)
|
||||||
|
{
|
||||||
|
const HEADER *hp = (HEADER *) buf;
|
||||||
|
const HEADER *hp2 = (HEADER *) buf2;
|
||||||
|
u_char *ans = *ansp;
|
||||||
|
int orig_anssizp = *anssizp;
|
||||||
|
struct timespec now, timeout, finish;
|
||||||
|
struct pollfd pfd[1];
|
||||||
|
int ptimeout;
|
||||||
|
struct sockaddr_in6 from;
|
||||||
|
int resplen, n;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute time for the total operation.
|
* Compute time for the total operation.
|
||||||
*/
|
*/
|
||||||
@ -1008,8 +1015,15 @@ send_dg(res_state statp,
|
|||||||
seconds /= statp->nscount;
|
seconds /= statp->nscount;
|
||||||
if (seconds <= 0)
|
if (seconds <= 0)
|
||||||
seconds = 1;
|
seconds = 1;
|
||||||
bool single_request = (statp->options & RES_SNGLKUP) != 0;// XXX
|
bool single_request = (statp->options & RES_SNGLKUP) != 0;
|
||||||
|
bool single_request_reopen = (statp->options & RES_SNGLKUPREOP) != 0;
|
||||||
int save_gotsomewhere = *gotsomewhere;
|
int save_gotsomewhere = *gotsomewhere;
|
||||||
|
|
||||||
|
int retval;
|
||||||
|
retry_reopen:
|
||||||
|
retval = reopen (statp, terrno, ns);
|
||||||
|
if (retval <= 0)
|
||||||
|
return retval;
|
||||||
retry:
|
retry:
|
||||||
evNowTime(&now);
|
evNowTime(&now);
|
||||||
evConsTime(&timeout, seconds, 0);
|
evConsTime(&timeout, seconds, 0);
|
||||||
@ -1064,6 +1078,14 @@ send_dg(res_state statp,
|
|||||||
*gotsomewhere = save_gotsomewhere;
|
*gotsomewhere = save_gotsomewhere;
|
||||||
goto retry;
|
goto retry;
|
||||||
}
|
}
|
||||||
|
else if (!single_request_reopen)
|
||||||
|
{
|
||||||
|
statp->options |= RES_SNGLKUPREOP;
|
||||||
|
single_request_reopen = true;
|
||||||
|
*gotsomewhere = save_gotsomewhere;
|
||||||
|
__res_iclose (statp, false);
|
||||||
|
goto retry_reopen;
|
||||||
|
}
|
||||||
|
|
||||||
*resplen2 = 1;
|
*resplen2 = 1;
|
||||||
return resplen;
|
return resplen;
|
||||||
@ -1092,7 +1114,8 @@ send_dg(res_state statp,
|
|||||||
Perror(statp, stderr, "send", errno);
|
Perror(statp, stderr, "send", errno);
|
||||||
goto err_out;
|
goto err_out;
|
||||||
}
|
}
|
||||||
if (nwritten != 0 || buf2 == NULL || single_request)
|
if (nwritten != 0 || buf2 == NULL
|
||||||
|
|| single_request || single_request_reopen)
|
||||||
pfd[0].events = POLLIN;
|
pfd[0].events = POLLIN;
|
||||||
else
|
else
|
||||||
pfd[0].events = POLLIN | POLLOUT;
|
pfd[0].events = POLLIN | POLLOUT;
|
||||||
@ -1306,8 +1329,15 @@ send_dg(res_state statp,
|
|||||||
recvresp2 = 1;
|
recvresp2 = 1;
|
||||||
/* Repeat waiting if we have a second answer to arrive. */
|
/* Repeat waiting if we have a second answer to arrive. */
|
||||||
if ((recvresp1 & recvresp2) == 0) {
|
if ((recvresp1 & recvresp2) == 0) {
|
||||||
if (single_request)
|
if (single_request || single_request_reopen) {
|
||||||
pfd[0].events = POLLOUT;
|
pfd[0].events = POLLOUT;
|
||||||
|
if (single_request_reopen) {
|
||||||
|
__res_iclose (statp, false);
|
||||||
|
retval = reopen (statp, terrno, ns);
|
||||||
|
if (retval <= 0)
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
}
|
||||||
goto wait;
|
goto wait;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -216,6 +216,8 @@ struct res_sym {
|
|||||||
reverse lookup */
|
reverse lookup */
|
||||||
#define RES_USE_EDNS0 0x00100000 /* Use EDNS0. */
|
#define RES_USE_EDNS0 0x00100000 /* Use EDNS0. */
|
||||||
#define RES_SNGLKUP 0x00200000 /* one outstanding request at a time */
|
#define RES_SNGLKUP 0x00200000 /* one outstanding request at a time */
|
||||||
|
#define RES_SNGLKUPREOP 0x00400000 /* -"-, but open new socket for each
|
||||||
|
request */
|
||||||
|
|
||||||
#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT)
|
#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user