mirror of
https://sourceware.org/git/glibc.git
synced 2025-01-18 06:30:05 +00:00
* resolv/res_init.c (res_setoptions): Recognize edns0 option.
* resolv/res_mkquery.c: Define __res_nopt. * resolv/res_query.c (__libc_res_nquery): If RES_USE_EDNS0 is set try adding EDNS0 record. * resolv/res_send.c (send_dg): If request failed with FORMERR and EDNS0 record was send make sure we don't try it again. * resolv/resolv.h: Define RES_F_EDNS0ERR and RES_USE_EDNS0. * include/resolv.h: Declare __res_nopt.
This commit is contained in:
parent
00458b5bee
commit
2bbb7d5b3c
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
|||||||
|
2007-02-09 Ulrich Drepper <drepper@redhat.com>
|
||||||
|
|
||||||
|
* resolv/res_init.c (res_setoptions): Recognize edns0 option.
|
||||||
|
* resolv/res_mkquery.c: Define __res_nopt.
|
||||||
|
* resolv/res_query.c (__libc_res_nquery): If RES_USE_EDNS0 is set
|
||||||
|
try adding EDNS0 record.
|
||||||
|
* resolv/res_send.c (send_dg): If request failed with FORMERR and
|
||||||
|
EDNS0 record was send make sure we don't try it again.
|
||||||
|
* resolv/resolv.h: Define RES_F_EDNS0ERR and RES_USE_EDNS0.
|
||||||
|
* include/resolv.h: Declare __res_nopt.
|
||||||
|
|
||||||
2007-02-08 Jakub Jelinek <jakub@redhat.com>
|
2007-02-08 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
[BZ #3944]
|
[BZ #3944]
|
||||||
|
@ -48,6 +48,8 @@ extern void res_send_setrhook (res_send_rhook __hook);
|
|||||||
extern int res_ourserver_p (const res_state __statp,
|
extern int res_ourserver_p (const res_state __statp,
|
||||||
const struct sockaddr_in6 *__inp);
|
const struct sockaddr_in6 *__inp);
|
||||||
extern void __res_iclose (res_state statp, bool free_addr);
|
extern void __res_iclose (res_state statp, bool free_addr);
|
||||||
|
extern int __res_nopt(res_state statp, int n0, u_char *buf, int buflen,
|
||||||
|
int anslen);
|
||||||
libc_hidden_proto (__res_ninit)
|
libc_hidden_proto (__res_ninit)
|
||||||
libc_hidden_proto (__res_maybe_init)
|
libc_hidden_proto (__res_maybe_init)
|
||||||
libc_hidden_proto (__res_nclose)
|
libc_hidden_proto (__res_nclose)
|
||||||
@ -100,6 +102,7 @@ libresolv_hidden_proto (__ns_name_ntop)
|
|||||||
libresolv_hidden_proto (__ns_name_unpack)
|
libresolv_hidden_proto (__ns_name_unpack)
|
||||||
libresolv_hidden_proto (__ns_get16)
|
libresolv_hidden_proto (__ns_get16)
|
||||||
libresolv_hidden_proto (__ns_get32)
|
libresolv_hidden_proto (__ns_get32)
|
||||||
|
libresolv_hidden_proto (__res_nopt)
|
||||||
|
|
||||||
extern const char *_res_opcodes[];
|
extern const char *_res_opcodes[];
|
||||||
libresolv_hidden_proto (_res_opcodes)
|
libresolv_hidden_proto (_res_opcodes)
|
||||||
|
@ -510,6 +510,8 @@ res_setoptions(res_state statp, const char *options, const char *source) {
|
|||||||
} else if (!strncmp(cp, "no-check-names",
|
} else if (!strncmp(cp, "no-check-names",
|
||||||
sizeof("no-check-names") - 1)) {
|
sizeof("no-check-names") - 1)) {
|
||||||
statp->options |= RES_NOCHECKNAME;
|
statp->options |= RES_NOCHECKNAME;
|
||||||
|
} else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
|
||||||
|
statp->options |= RES_USE_EDNS0;
|
||||||
} else {
|
} else {
|
||||||
/* XXX - print a warning here? */
|
/* XXX - print a warning here? */
|
||||||
}
|
}
|
||||||
|
@ -208,3 +208,49 @@ res_nmkquery(res_state statp,
|
|||||||
return (cp - buf);
|
return (cp - buf);
|
||||||
}
|
}
|
||||||
libresolv_hidden_def (res_nmkquery)
|
libresolv_hidden_def (res_nmkquery)
|
||||||
|
|
||||||
|
|
||||||
|
/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
|
||||||
|
#ifndef T_OPT
|
||||||
|
#define T_OPT 41
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int
|
||||||
|
__res_nopt(res_state statp,
|
||||||
|
int n0, /* current offset in buffer */
|
||||||
|
u_char *buf, /* buffer to put query */
|
||||||
|
int buflen, /* size of buffer */
|
||||||
|
int anslen) /* UDP answer buffer size */
|
||||||
|
{
|
||||||
|
u_int16_t flags = 0;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if ((statp->options & RES_DEBUG) != 0U)
|
||||||
|
printf(";; res_nopt()\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
HEADER *hp = (HEADER *) buf;
|
||||||
|
u_char *cp = buf + n0;
|
||||||
|
u_char *ep = buf + buflen;
|
||||||
|
|
||||||
|
if ((ep - cp) < 1 + RRFIXEDSZ)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*cp++ = 0; /* "." */
|
||||||
|
|
||||||
|
ns_put16(T_OPT, cp); /* TYPE */
|
||||||
|
cp += INT16SZ;
|
||||||
|
ns_put16(anslen & 0xffff, cp); /* CLASS = UDP payload size */
|
||||||
|
cp += INT16SZ;
|
||||||
|
*cp++ = NOERROR; /* extended RCODE */
|
||||||
|
*cp++ = 0; /* EDNS version */
|
||||||
|
/* XXX Once we support DNSSEC we change the flag value here. */
|
||||||
|
ns_put16(flags, cp);
|
||||||
|
cp += INT16SZ;
|
||||||
|
ns_put16(0, cp); /* RDLEN */
|
||||||
|
cp += INT16SZ;
|
||||||
|
hp->arcount = htons(ntohs(hp->arcount) + 1);
|
||||||
|
|
||||||
|
return cp - buf;
|
||||||
|
}
|
||||||
|
libresolv_hidden_def (__res_nopt)
|
||||||
|
@ -120,29 +120,44 @@ __libc_res_nquery(res_state statp,
|
|||||||
u_char *buf;
|
u_char *buf;
|
||||||
HEADER *hp = (HEADER *) answer;
|
HEADER *hp = (HEADER *) answer;
|
||||||
int n, use_malloc = 0;
|
int n, use_malloc = 0;
|
||||||
|
u_int oflags = statp->_flags;
|
||||||
|
|
||||||
|
size_t bufsize = QUERYSIZE;
|
||||||
|
buf = alloca (bufsize);
|
||||||
|
|
||||||
|
again:
|
||||||
hp->rcode = NOERROR; /* default */
|
hp->rcode = NOERROR; /* default */
|
||||||
|
|
||||||
buf = alloca (QUERYSIZE);
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (statp->options & RES_DEBUG)
|
if (statp->options & RES_DEBUG)
|
||||||
printf(";; res_query(%s, %d, %d)\n", name, class, type);
|
printf(";; res_query(%s, %d, %d)\n", name, class, type);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
|
n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
|
||||||
buf, QUERYSIZE);
|
buf, bufsize);
|
||||||
if (__builtin_expect (n <= 0, 0)) {
|
if (n > 0
|
||||||
|
&& (oflags & RES_F_EDNS0ERR) == 0
|
||||||
|
&& (statp->options & RES_USE_EDNS0) != 0)
|
||||||
|
n = __res_nopt(statp, n, buf, bufsize, anslen);
|
||||||
|
if (__builtin_expect (n <= 0, 0) && !use_malloc) {
|
||||||
/* Retry just in case res_nmkquery failed because of too
|
/* Retry just in case res_nmkquery failed because of too
|
||||||
short buffer. Shouldn't happen. */
|
short buffer. Shouldn't happen. */
|
||||||
buf = malloc (MAXPACKET);
|
bufsize = MAXPACKET;
|
||||||
|
buf = malloc (bufsize);
|
||||||
if (buf != NULL) {
|
if (buf != NULL) {
|
||||||
use_malloc = 1;
|
use_malloc = 1;
|
||||||
n = res_nmkquery(statp, QUERY, name, class, type, NULL,
|
goto again;
|
||||||
0, NULL, buf, MAXPACKET);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (__builtin_expect (n <= 0, 0)) {
|
if (__builtin_expect (n <= 0, 0)) {
|
||||||
|
/* If the query choked with EDNS0, retry without EDNS0. */
|
||||||
|
if ((statp->options & RES_USE_EDNS0) != 0
|
||||||
|
&& ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
|
||||||
|
statp->_flags |= RES_F_EDNS0ERR;
|
||||||
|
if (statp->options & RES_DEBUG)
|
||||||
|
printf(";; res_nquery: retry without EDNS0\n");
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (statp->options & RES_DEBUG)
|
if (statp->options & RES_DEBUG)
|
||||||
printf(";; res_query: mkquery failed\n");
|
printf(";; res_query: mkquery failed\n");
|
||||||
|
@ -986,6 +986,24 @@ send_dg(res_state statp,
|
|||||||
ans, (resplen > anssiz) ? anssiz : resplen);
|
ans, (resplen > anssiz) ? anssiz : resplen);
|
||||||
goto wait;
|
goto wait;
|
||||||
}
|
}
|
||||||
|
#ifdef RES_USE_EDNS0
|
||||||
|
if (anhp->rcode == FORMERR
|
||||||
|
&& (statp->options & RES_USE_EDNS0) != 0U) {
|
||||||
|
/*
|
||||||
|
* Do not retry if the server do not understand
|
||||||
|
* EDNS0. The case has to be captured here, as
|
||||||
|
* FORMERR packet do not carry query section, hence
|
||||||
|
* res_queriesmatch() returns 0.
|
||||||
|
*/
|
||||||
|
DprintQ(statp->options & RES_DEBUG,
|
||||||
|
(stdout,
|
||||||
|
"server rejected query with EDNS0:\n"),
|
||||||
|
ans, (resplen > anssiz) ? anssiz : resplen);
|
||||||
|
/* record the error */
|
||||||
|
statp->_flags |= RES_F_EDNS0ERR;
|
||||||
|
goto err_out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (!(statp->options & RES_INSECURE2) &&
|
if (!(statp->options & RES_INSECURE2) &&
|
||||||
!res_queriesmatch(buf, buf + buflen,
|
!res_queriesmatch(buf, buf + buflen,
|
||||||
ans, ans + anssiz)) {
|
ans, ans + anssiz)) {
|
||||||
|
@ -180,6 +180,7 @@ struct res_sym {
|
|||||||
*/
|
*/
|
||||||
#define RES_F_VC 0x00000001 /* socket is TCP */
|
#define RES_F_VC 0x00000001 /* socket is TCP */
|
||||||
#define RES_F_CONN 0x00000002 /* socket is connected */
|
#define RES_F_CONN 0x00000002 /* socket is connected */
|
||||||
|
#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors */
|
||||||
|
|
||||||
/* res_findzonecut() options */
|
/* res_findzonecut() options */
|
||||||
#define RES_EXHAUSTIVE 0x00000001 /* always do all queries */
|
#define RES_EXHAUSTIVE 0x00000001 /* always do all queries */
|
||||||
@ -209,6 +210,7 @@ struct res_sym {
|
|||||||
strings */
|
strings */
|
||||||
#define RES_NOIP6DOTINT 0x00080000 /* Do not use .ip6.int in IPv6
|
#define RES_NOIP6DOTINT 0x00080000 /* Do not use .ip6.int in IPv6
|
||||||
reverse lookup */
|
reverse lookup */
|
||||||
|
#define RES_USE_EDNS0 0x00100000 /* Use EDNS0. */
|
||||||
|
|
||||||
#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT)
|
#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user