Implement EDNS0 support, as EDNS0 support will be made mandatory for

IPv6 transport-ready resolvers/DNS servers.  Need careful configuration
when enable it. (default config is not affected).
See manpage for details.

XXX visible symbol __res_opt() is added, however, it is not supposed to be
called from outside, libc minor is not bumped.

Obtained from:	KAME/NetBSD
This commit is contained in:
Hajimu UMEMOTO 2001-06-10 20:25:24 +00:00
parent 4fd6d738cb
commit ce6282db3b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=78012
10 changed files with 104 additions and 2 deletions

View File

@ -273,6 +273,7 @@ typedef enum __ns_type {
ns_t_srv = 33, /* Server Selection. */
ns_t_atma = 34, /* ATM Address */
ns_t_naptr = 35, /* Naming Authority PoinTeR */
ns_t_opt = 41, /* OPT pseudo-RR, RFC2761 */
/* Query type values which do not appear in resource records. */
ns_t_ixfr = 251, /* Incremental zone transfer. */
ns_t_axfr = 252, /* Transfer zone of authority. */

View File

@ -173,6 +173,7 @@ typedef struct {
#define T_SRV ns_t_srv
#define T_ATMA ns_t_atma
#define T_NAPTR ns_t_naptr
#define T_OPT ns_t_opt
#define T_IXFR ns_t_ixfr
#define T_AXFR ns_t_axfr
#define T_MAILB ns_t_mailb

View File

@ -150,6 +150,8 @@ struct __res_state_ext {
#define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */
#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */
#define RES_NOTLDQUERY 0x00004000 /* Don't query TLD names */
/* KAME extensions: use higher bit to avoid conflict with ISC use */
#define RES_USE_EDNS0 0x40000000 /* use EDNS0 */
#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH)
@ -249,6 +251,7 @@ extern const struct res_sym __p_type_syms[];
#define res_nameinquery __res_nameinquery
#define res_queriesmatch __res_queriesmatch
#define res_close __res_close
#define res_opt __res_opt
#define res_mkupdate __res_mkupdate
#define res_mkupdrec __res_mkupdrec
#define res_freeupdrec __res_freeupdrec
@ -303,6 +306,7 @@ int res_nameinquery __P((const char *, int, int,
int res_queriesmatch __P((const u_char *, const u_char *,
const u_char *, const u_char *));
void res_close __P((void));
int res_opt __P((int, u_char *, int, int));
const char * p_section __P((int, int));
/* XXX The following depend on the ns_updrec typedef in arpa/nameser.h */
#ifdef _ARPA_NAMESER_H_

View File

@ -79,7 +79,6 @@
* - other KAME platforms already nuked FAITH ($GAI), but as FreeBSD
* 4.0-RELEASE supplies it, we still have the code here.
* - AI_ADDRCONFIG support is supplied
* - EDNS0 support is not available due to resolver differences
* - some of FreeBSD style (#define tabify and others)
* - classful IPv4 numeric (127.1) is allowed.
*/
@ -101,6 +100,9 @@
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#ifdef DEBUG
#include <syslog.h>
#endif
#include <syslog.h>
#include <stdarg.h>
@ -1718,6 +1720,8 @@ res_queryN(name, target)
n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
buf, sizeof(buf));
if (n > 0 && (_res.options & RES_USE_EDNS0) != 0)
n = res_opt(n, buf, sizeof(buf), anslen);
if (n <= 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)

View File

@ -519,6 +519,10 @@ p_option(u_long option) {
case RES_DNSRCH: return "dnsrch";
case RES_INSECURE1: return "insecure1";
case RES_INSECURE2: return "insecure2";
case RES_NOALIASES: return "noaliases";
case RES_USE_INET6: return "inet6";
case RES_NOTLDQUERY: return "no-tld-query";
case RES_USE_EDNS0: return "edns0";
default: sprintf(nbuf, "?0x%lx?", (u_long)option);
return (nbuf);
}

View File

@ -532,6 +532,8 @@ res_setoptions(options, source)
_res.options |= RES_USE_INET6;
} else if (!strncmp(cp, "no_tld_query", sizeof("no_tld_query") - 1)) {
_res.options |= RES_NOTLDQUERY;
} else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
_res.options |= RES_USE_EDNS0;
} else {
/* XXX - print a warning here? */
}

View File

@ -204,3 +204,40 @@ res_mkquery(op, dname, class, type, data, datalen, newrr_in, buf, buflen)
*/
#undef res_mkquery
__weak_reference(__res_mkquery, res_mkquery);
/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
int
res_opt(n0, buf, buflen, anslen)
int n0;
u_char *buf; /* buffer to put query */
int buflen; /* size of buffer */
int anslen; /* answer buffer length */
{
register HEADER *hp;
register u_char *cp;
hp = (HEADER *) buf;
cp = buf + n0;
buflen -= n0;
if (buflen < 1 + RRFIXEDSZ)
return -1;
*cp++ = 0; /* "." */
buflen--;
__putshort(T_OPT, cp); /* TYPE */
cp += INT16SZ;
__putshort(anslen & 0xffff, cp); /* CLASS = UDP payload size */
cp += INT16SZ;
*cp++ = NOERROR; /* extended RCODE */
*cp++ = 0; /* EDNS version */
__putshort(0, cp); /* MBZ */
cp += INT16SZ;
__putshort(0, cp); /* RDLEN */
cp += INT16SZ;
hp->arcount = htons(ntohs(hp->arcount) + 1);
buflen -= RRFIXEDSZ;
return cp - buf;
}

View File

@ -129,6 +129,8 @@ res_query(name, class, type, answer, anslen)
n = res_mkquery(QUERY, name, class, type, NULL, 0, NULL,
buf, sizeof(buf));
if (n > 0 && (_res.options & RES_USE_EDNS0) != 0)
n = res_opt(n, buf, sizeof(buf), anslen);
if (n <= 0) {
#ifdef DEBUG
if (_res.options & RES_DEBUG)

View File

@ -119,7 +119,7 @@ are defined in
and are as follows.
Options are stored as a simple bit mask containing the bitwise ``or''
of the options enabled.
.Bl -tag -width RES_DEFNAMES
.Bl -tag -width RES_USE_INET6
.It Dv RES_INIT
True if the initial name server address and default domain name are
initialized (i.e.,
@ -176,6 +176,19 @@ This option is enabled by default.
This option turns off the user level aliasing feature controlled by the
.Dq Ev HOSTALIASES
environment variable. Network daemons should set this option.
.It Dv RES_USE_INET6
Enables support for IPv6-only applications.
This causes IPv4 addresses to be returned as an IPv4 mapped address.
For example, 10.1.1.1 will be returned as ::ffff:10.1.1.1.
The option is meaningful with certain kernel configuration only.
.It Dv RES_USE_EDNS0
Enables support for OPT pseudo-RR for EDNS0 extension.
With the option, resolver code will attach OPT pseudo-RR into DNS queries,
to inform of our receive buffer size.
The option will allow DNS servers to take advantage of non-default receive
buffer size, and to send larger replies.
DNS query packets with EDNS0 extension is not compatible with
non-EDNS0 DNS servers.
.El
.Pp
The

View File

@ -626,4 +626,38 @@ Configuration at Host-A:
-E rc5-cbc "kamekame"
-A hmac-md5 "this is the test" ;
<<<EDNS0>>>
EDNS0 is defined in RFC2671. With EDNS0, the resolver library can tell DNS
server of its receiving buffer size, and permit DNS server to transmit large
reply packet. EDNS0 is necessary to take advantage of larger minimum MTU
in IPv6. KAME libinet6 includes resolver side support for EDNS0.
Server side support for EDNS0 is included in ISC BIND9.
query packet with EDNS0
tells receive buffer size
KAME box -----------------------------> BIND9 DNS server
KAME box <----------------------------- BIND9 DNS server
can transmit jumbo reply, since DNS server
knows receive buffer size of KAME box
How to play with it:
- prepare KAME box and BIND9 DNS server (can be a same node)
- add the following into /etc/resolv.conf on KAME box:
options edns0 <--- enables EDNS0
nameserver <IPv4 or v6 address of BIND9 box>
- run applications compiled with libinet6 (like /usr/local/v6/bin/telnet),
see EDNS0 packet fly on the wire by tcpdump or some other method.
Caveats:
- BIND 4/8 DNS server will choke with EDNS0 packet, so you must not
turn the option on if you have BIND 4/8 DNS server. If you enable
"options edns0" against BIND 4/8 DNS server, you will never be able
to resolve names.
- If you use IPv6 UDP as DNS transport, path MTU discovery may
affect the traffic. KAME box tries to fragment packet to 1280
bytes, however, BIND9 may not.
- Some of our platforms do not use our extended resolver code in libinet6.
See COVERAGE for detail.
<end of USAGE>