diff --git a/CHANGES b/CHANGES index 0fb5c14aee..ee880612b6 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,8 @@ +1879. [func] Added framework for handling multiple EDNS versions. + +1878. [func] dig can now specify the EDNS version when making + a query. + 1868. [placeholder] rt14851 1867. [placeholder] rt14846 diff --git a/bin/dig/dig.c b/bin/dig/dig.c index 96baacbad9..df3032c973 100644 --- a/bin/dig/dig.c +++ b/bin/dig/dig.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dig.c,v 1.203 2005/04/27 04:55:44 sra Exp $ */ +/* $Id: dig.c,v 1.204 2005/06/07 00:15:58 marka Exp $ */ /*! \file */ @@ -192,6 +192,7 @@ help(void) { " +domain=### (Set default domainname)\n" " +bufsize=### (Set EDNS0 Max UDP packet size)\n" " +ndots=### (Set NDOTS value)\n" +" +edns=### (Set EDNS version)\n" " +[no]search (Set whether to use searchlist)\n" " +[no]defname (Ditto)\n" " +[no]recurse (Recursive mode)\n" @@ -854,6 +855,8 @@ plus_option(char *option, isc_boolean_t is_batchfile, break; case 'n': /* dnssec */ FULLCHECK("dnssec"); + if (state && lookup->edns == -1) + lookup->edns = 0; lookup->dnssec = state; break; case 'o': /* domain */ @@ -869,6 +872,16 @@ plus_option(char *option, isc_boolean_t is_batchfile, goto invalid_option; } break; + case 'e': + FULLCHECK("edns"); + if (!state) { + lookup->edns = -1; + break; + } + if (value == NULL) + goto need_value; + lookup->edns = (isc_int16_t) parse_uint(value, "edns", 255); + break; case 'f': /* fail */ FULLCHECK("fail"); lookup->servfail_stops = state; diff --git a/bin/dig/dig.docbook b/bin/dig/dig.docbook index 6b727b9895..49aa1d1da3 100644 --- a/bin/dig/dig.docbook +++ b/bin/dig/dig.docbook @@ -18,7 +18,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -695,15 +695,26 @@ Set the UDP message buffer size advertised using EDNS0 to - B bytes. The maximum and - minimum sizes of this - buffer are 65535 and 0 respectively. Values outside this range - are - rounded up or down appropriately. + B bytes. The maximum and minimum sizes + of this buffer are 65535 and 0 respectively. Values outside + this range are rounded up or down appropriately. + Values other than zero will cause a EDNS query to be sent. + + + + + Specify the EDNS version to query with. Valid values + are 0 to 255. Setting the EDNS version will cause a + EDNS query to be sent. clears the + remembered EDNS version. + + + + diff --git a/bin/dig/dighost.c b/bin/dig/dighost.c index 93b3c20870..fe7df5731f 100644 --- a/bin/dig/dighost.c +++ b/bin/dig/dighost.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dighost.c,v 1.276 2005/06/01 01:56:49 marka Exp $ */ +/* $Id: dighost.c,v 1.277 2005/06/07 00:15:58 marka Exp $ */ /*! \file * \note @@ -702,6 +702,7 @@ make_empty_lookup(void) { #endif #endif looknew->udpsize = 0; + looknew->edns = -1; looknew->recurse = ISC_TRUE; looknew->aaonly = ISC_FALSE; looknew->adflag = ISC_FALSE; @@ -778,6 +779,7 @@ clone_lookup(dig_lookup_t *lookold, isc_boolean_t servers) { #endif #endif looknew->udpsize = lookold->udpsize; + looknew->edns = lookold->edns; looknew->recurse = lookold->recurse; looknew->aaonly = lookold->aaonly; looknew->adflag = lookold->adflag; @@ -1085,7 +1087,9 @@ setup_libs(void) { * options are UDP buffer size and the DO bit. */ static void -add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_boolean_t dnssec) { +add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_uint16_t edns, + isc_boolean_t dnssec) +{ dns_rdataset_t *rdataset = NULL; dns_rdatalist_t *rdatalist = NULL; dns_rdata_t *rdata = NULL; @@ -1104,9 +1108,9 @@ add_opt(dns_message_t *msg, isc_uint16_t udpsize, isc_boolean_t dnssec) { rdatalist->type = dns_rdatatype_opt; rdatalist->covers = 0; rdatalist->rdclass = udpsize; - rdatalist->ttl = 0; + rdatalist->ttl = edns << 16; if (dnssec) - rdatalist->ttl = DNS_MESSAGEEXTFLAG_DO; + rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO; rdata->data = NULL; rdata->length = 0; ISC_LIST_INIT(rdatalist->rdata); @@ -1829,10 +1833,13 @@ setup_lookup(dig_lookup_t *lookup) { result = dns_message_renderbegin(lookup->sendmsg, &cctx, &lookup->sendbuf); check_result(result, "dns_message_renderbegin"); - if (lookup->udpsize > 0 || lookup->dnssec) { + if (lookup->udpsize > 0 || lookup->dnssec || lookup->edns > -1) { if (lookup->udpsize == 0) lookup->udpsize = 2048; - add_opt(lookup->sendmsg, lookup->udpsize, lookup->dnssec); + if (lookup->edns < 0) + lookup->edns = 0; + add_opt(lookup->sendmsg, lookup->udpsize, + lookup->edns, lookup->dnssec); } result = dns_message_rendersection(lookup->sendmsg, diff --git a/bin/dig/include/dig/dig.h b/bin/dig/include/dig/dig.h index c59636a0ab..4028ff73c5 100644 --- a/bin/dig/include/dig/dig.h +++ b/bin/dig/include/dig/dig.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: dig.h,v 1.91 2005/04/27 04:55:45 sra Exp $ */ +/* $Id: dig.h,v 1.92 2005/06/07 00:15:59 marka Exp $ */ #ifndef DIG_H #define DIG_H @@ -180,6 +180,7 @@ isc_boolean_t sigchase; isc_uint32_t retries; int nsfound; isc_uint16_t udpsize; + isc_int16_t edns; isc_uint32_t ixfr_serial; isc_buffer_t rdatabuf; char rdatastore[MXNAME]; diff --git a/bin/named/client.c b/bin/named/client.c index 067e327497..14009bf296 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.c,v 1.227 2005/06/04 05:32:46 jinmei Exp $ */ +/* $Id: client.c,v 1.228 2005/06/07 00:15:59 marka Exp $ */ #include @@ -574,6 +574,7 @@ ns_client_endrequest(ns_client_t *client) { client->udpsize = 512; client->extflags = 0; + client->ednsversion = -1; dns_message_reset(client->message, DNS_MESSAGE_INTENTPARSE); if (client->recursionquota != NULL) @@ -1363,8 +1364,6 @@ client_request(isc_task_t *task, isc_event_t *event) { */ opt = dns_message_getopt(client->message); if (opt != NULL) { - unsigned int version; - /* * Set the client's UDP buffer size. */ @@ -1382,6 +1381,19 @@ client_request(isc_task_t *task, isc_event_t *event) { */ client->extflags = (isc_uint16_t)(opt->ttl & 0xFFFF); + /* + * Do we understand this version of EDNS? + * + * XXXRTH need library support for this! + */ + client->ednsversion = (opt->ttl & 0x00FF0000) >> 16; + if (client->ednsversion > 0) { + result = client_addopt(client); + if (result == ISC_R_SUCCESS) + result = DNS_R_BADVERS; + ns_client_error(client, result); + goto cleanup; + } /* * Create an OPT for our reply. */ @@ -1390,17 +1402,6 @@ client_request(isc_task_t *task, isc_event_t *event) { ns_client_error(client, result); goto cleanup; } - - /* - * Do we understand this version of ENDS? - * - * XXXRTH need library support for this! - */ - version = (opt->ttl & 0x00FF0000) >> 16; - if (version != 0) { - ns_client_error(client, DNS_R_BADVERS); - goto cleanup; - } } if (client->message->rdclass == 0) { @@ -1776,6 +1777,7 @@ client_create(ns_clientmgr_t *manager, ns_client_t **clientp) { client->opt = NULL; client->udpsize = 512; client->extflags = 0; + client->ednsversion = -1; client->next = NULL; client->shutdown = NULL; client->shutdown_arg = NULL; diff --git a/bin/named/include/named/client.h b/bin/named/include/named/client.h index 7993fc99de..6cec4d63cd 100644 --- a/bin/named/include/named/client.h +++ b/bin/named/include/named/client.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: client.h,v 1.73 2005/04/27 04:55:56 sra Exp $ */ +/* $Id: client.h,v 1.74 2005/06/07 00:16:00 marka Exp $ */ #ifndef NAMED_CLIENT_H #define NAMED_CLIENT_H 1 @@ -116,6 +116,7 @@ struct ns_client { dns_rdataset_t * opt; isc_uint16_t udpsize; isc_uint16_t extflags; + isc_int16_t ednsversion; /* -1 noedns */ void (*next)(ns_client_t *); void (*shutdown)(void *arg, isc_result_t result); void *shutdown_arg; diff --git a/lib/dns/include/dns/resolver.h b/lib/dns/include/dns/resolver.h index 6f42c7bae0..a6555b601b 100644 --- a/lib/dns/include/dns/resolver.h +++ b/lib/dns/include/dns/resolver.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.h,v 1.44 2005/04/27 04:56:59 sra Exp $ */ +/* $Id: resolver.h,v 1.45 2005/06/07 00:16:01 marka Exp $ */ #ifndef DNS_RESOLVER_H #define DNS_RESOLVER_H 1 @@ -91,6 +91,10 @@ typedef struct dns_fetchevent { #define DNS_FETCHOPT_FORWARDONLY 0x10 /*%< Only use forwarders. */ #define DNS_FETCHOPT_NOVALIDATE 0x20 /*%< Disable validation. */ +#define DNS_FETCHOPT_EDNSVERSIONSET 0x00800000 +#define DNS_FETCHOPT_EDNSVERSIONMASK 0xff000000 +#define DNS_FETCHOPT_EDNSVERSIONSHIFT 24 + /* * XXXRTH Should this API be made semi-private? (I.e. * _dns_resolver_create()). diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 012b67e788..f03b5dd283 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: resolver.c,v 1.308 2005/06/04 05:32:47 jinmei Exp $ */ +/* $Id: resolver.c,v 1.309 2005/06/07 00:16:00 marka Exp $ */ /*! \file */ @@ -841,7 +841,7 @@ resquery_senddone(isc_task_t *task, isc_event_t *event) { } static inline isc_result_t -fctx_addopt(dns_message_t *message, dns_resolver_t *res) { +fctx_addopt(dns_message_t *message, unsigned int version, dns_resolver_t *res) { dns_rdataset_t *rdataset; dns_rdatalist_t *rdatalist; dns_rdata_t *rdata; @@ -870,9 +870,10 @@ fctx_addopt(dns_message_t *message, dns_resolver_t *res) { rdatalist->rdclass = res->udpsize; /* - * Set EXTENDED-RCODE, VERSION, and Z to 0, and the DO bit to 1. + * Set EXTENDED-RCODE and Z to 0, DO to 1. */ - rdatalist->ttl = DNS_MESSAGEEXTFLAG_DO; + rdatalist->ttl = (version << 16); + rdatalist->ttl |= DNS_MESSAGEEXTFLAG_DO; /* * No EDNS options. @@ -1233,7 +1234,14 @@ resquery_send(resquery_t *query) { if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) { if ((query->addrinfo->flags & DNS_FETCHOPT_NOEDNS0) == 0) { - result = fctx_addopt(fctx->qmessage, res); + unsigned int version = 0; /* Default version. */ + unsigned int flags; + flags = query->addrinfo->flags; + if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) { + version = flags & DNS_FETCHOPT_EDNSVERSIONMASK; + version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT; + } + result = fctx_addopt(fctx->qmessage, version, res); if (result != ISC_R_SUCCESS) { /* * We couldn't add the OPT, but we'll press on. @@ -5277,6 +5285,28 @@ resquery_response(isc_task_t *task, isc_event_t *event) { * for this fetch. */ result = DNS_R_YXDOMAIN; + } else if (message->rcode == dns_rcode_badvers) { + dns_rdataset_t *opt; + unsigned int flags, mask; + unsigned int version; + + resend = ISC_TRUE; + opt = dns_message_getopt(message); + version = (opt->ttl >> 16) & 0xff; + flags = (version << DNS_FETCHOPT_EDNSVERSIONSHIFT) | + DNS_FETCHOPT_EDNSVERSIONSET; + mask = DNS_FETCHOPT_EDNSVERSIONMASK | + DNS_FETCHOPT_EDNSVERSIONSET; + switch (version) { + case 0: + dns_adb_changeflags(fctx->adb, query->addrinfo, + flags, mask); + break; + default: + broken_server = DNS_R_BADVERS; + keep_trying = ISC_TRUE; + break; + } } else { /* * XXXRTH log.