|
|
|
@@ -24,6 +24,7 @@
|
|
|
|
|
#include <isc/counter.h>
|
|
|
|
|
#include <isc/hash.h>
|
|
|
|
|
#include <isc/hashmap.h>
|
|
|
|
|
#include <isc/hex.h>
|
|
|
|
|
#include <isc/log.h>
|
|
|
|
|
#include <isc/loop.h>
|
|
|
|
|
#include <isc/mutex.h>
|
|
|
|
@@ -269,6 +270,9 @@ typedef struct query {
|
|
|
|
|
unsigned int options;
|
|
|
|
|
unsigned int attributes;
|
|
|
|
|
unsigned int udpsize;
|
|
|
|
|
unsigned char *grease_nsid;
|
|
|
|
|
uint16_t grease_ednsflags;
|
|
|
|
|
uint16_t grease_nsid_len;
|
|
|
|
|
unsigned char data[512];
|
|
|
|
|
} resquery_t;
|
|
|
|
|
|
|
|
|
@@ -293,7 +297,10 @@ struct tried {
|
|
|
|
|
#define QUERY_MAGIC ISC_MAGIC('Q', '!', '!', '!')
|
|
|
|
|
#define VALID_QUERY(query) ISC_MAGIC_VALID(query, QUERY_MAGIC)
|
|
|
|
|
|
|
|
|
|
#define RESQUERY_ATTR_CANCELED 0x02
|
|
|
|
|
#define RESQUERY_ATTR_CANCELED (1U << 0)
|
|
|
|
|
#define RESQUERY_ATTR_DNS_FLAGS (1U << 1)
|
|
|
|
|
#define RESQUERY_ATTR_EDNS_FLAGS (1U << 2)
|
|
|
|
|
#define RESQUERY_ATTR_EDNS_NEG (1U << 3)
|
|
|
|
|
|
|
|
|
|
#define RESQUERY_CONNECTING(q) ((q)->connects > 0)
|
|
|
|
|
#define RESQUERY_CANCELED(q) (((q)->attributes & RESQUERY_ATTR_CANCELED) != 0)
|
|
|
|
@@ -1811,12 +1818,13 @@ detach:
|
|
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
|
fctx_addopt(dns_message_t *message, unsigned int version, uint16_t udpsize,
|
|
|
|
|
dns_ednsopt_t *ednsopts, size_t count) {
|
|
|
|
|
unsigned int flags, dns_ednsopt_t *ednsopts, size_t count) {
|
|
|
|
|
dns_rdataset_t *rdataset = NULL;
|
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
|
|
result = dns_message_buildopt(message, &rdataset, version, udpsize,
|
|
|
|
|
DNS_MESSAGEEXTFLAG_DO, ednsopts, count);
|
|
|
|
|
flags | DNS_MESSAGEEXTFLAG_DO, ednsopts,
|
|
|
|
|
count);
|
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
@@ -2361,6 +2369,16 @@ resquery_send(resquery_t *query) {
|
|
|
|
|
isc_region_t zr;
|
|
|
|
|
isc_buffer_t zb;
|
|
|
|
|
#endif /* HAVE_DNSTAP */
|
|
|
|
|
bool grease_dns_flags = res->view->grease_dns_flags;
|
|
|
|
|
bool grease_edns_flags = res->view->grease_edns_flags;
|
|
|
|
|
bool grease_edns_neg = res->view->grease_edns_neg;
|
|
|
|
|
bool grease_nsid = false;
|
|
|
|
|
bool reqnsid = res->view->requestnsid;
|
|
|
|
|
unsigned int grease_rate = res->view->grease_rate;
|
|
|
|
|
time_t grease_until = res->view->grease_until;
|
|
|
|
|
#define GREASE \
|
|
|
|
|
(grease_rate > 0 ? (grease_rate >= isc_random_uniform(99) + 1) : false)
|
|
|
|
|
time_t now = time(NULL);
|
|
|
|
|
|
|
|
|
|
QTRACE("send");
|
|
|
|
|
|
|
|
|
@@ -2444,6 +2462,22 @@ resquery_send(resquery_t *query) {
|
|
|
|
|
isc_netaddr_fromsockaddr(&ipaddr, &query->addrinfo->sockaddr);
|
|
|
|
|
(void)dns_peerlist_peerbyaddr(fctx->res->view->peers, &ipaddr, &peer);
|
|
|
|
|
|
|
|
|
|
if (peer != NULL) {
|
|
|
|
|
dns_peer_getdnsflags(peer, &grease_dns_flags);
|
|
|
|
|
dns_peer_getednsflags(peer, &grease_edns_flags);
|
|
|
|
|
dns_peer_getednsneg(peer, &grease_edns_neg);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* GREASE: Set the final reserved DNS header bit.
|
|
|
|
|
*/
|
|
|
|
|
query->attributes &= ~RESQUERY_ATTR_DNS_FLAGS;
|
|
|
|
|
if (grease_dns_flags && now < grease_until && GREASE) {
|
|
|
|
|
fctx->qmessage->flags |= 0x40;
|
|
|
|
|
query->attributes |= RESQUERY_ATTR_DNS_FLAGS;
|
|
|
|
|
grease_nsid = res->view->grease_nsid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The ADB does not know about servers with "edns no". Check
|
|
|
|
|
* this, and then inform the ADB for future use.
|
|
|
|
@@ -2506,11 +2540,46 @@ resquery_send(resquery_t *query) {
|
|
|
|
|
uint16_t peerudpsize = 0;
|
|
|
|
|
unsigned int version = DNS_EDNS_VERSION;
|
|
|
|
|
unsigned int flags = query->addrinfo->flags;
|
|
|
|
|
bool reqnsid = res->view->requestnsid;
|
|
|
|
|
bool sendcookie = res->view->sendcookie;
|
|
|
|
|
bool tcpkeepalive = false;
|
|
|
|
|
unsigned char cookie[COOKIE_BUFFER_SIZE];
|
|
|
|
|
uint16_t padding = 0;
|
|
|
|
|
uint16_t ednsflags = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* GREASE: EDNS version negotiation by sending a
|
|
|
|
|
* large EDNS version. We should get back BADVERS
|
|
|
|
|
* if there is an OPT record present with the version
|
|
|
|
|
* set to 0 as EDNS(1) is currently undefined.
|
|
|
|
|
*/
|
|
|
|
|
query->attributes &= ~RESQUERY_ATTR_EDNS_NEG;
|
|
|
|
|
if (grease_edns_neg && GREASE) {
|
|
|
|
|
version = 100;
|
|
|
|
|
query->attributes |= RESQUERY_ATTR_EDNS_NEG;
|
|
|
|
|
grease_nsid = res->view->grease_nsid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* GREASE: Unknown EDNS flags must be zero on
|
|
|
|
|
* transmission and be ignored on reception.
|
|
|
|
|
* Choose a random unallocated flag bit.
|
|
|
|
|
* Disable test Jan 1, 2026.
|
|
|
|
|
*/
|
|
|
|
|
query->attributes &= ~RESQUERY_ATTR_EDNS_FLAGS;
|
|
|
|
|
if (grease_edns_flags && now < grease_until && GREASE) {
|
|
|
|
|
/*
|
|
|
|
|
* Set one of the reserved EDNS flag bits.
|
|
|
|
|
*/
|
|
|
|
|
ednsflags = 1 << isc_random_uniform(14);
|
|
|
|
|
ednsflags &=
|
|
|
|
|
~res->view->grease_edns_known_flags;
|
|
|
|
|
if (ednsflags != 0) {
|
|
|
|
|
query->attributes |=
|
|
|
|
|
RESQUERY_ATTR_EDNS_FLAGS;
|
|
|
|
|
query->grease_ednsflags = ednsflags;
|
|
|
|
|
grease_nsid = res->view->grease_nsid;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Set the default UDP size to what was
|
|
|
|
@@ -2544,6 +2613,7 @@ resquery_send(resquery_t *query) {
|
|
|
|
|
if ((flags & DNS_FETCHOPT_EDNSVERSIONSET) != 0) {
|
|
|
|
|
version = flags & DNS_FETCHOPT_EDNSVERSIONMASK;
|
|
|
|
|
version >>= DNS_FETCHOPT_EDNSVERSIONSHIFT;
|
|
|
|
|
query->attributes &= ~RESQUERY_ATTR_EDNS_NEG;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Request NSID/COOKIE/VERSION for current peer?
|
|
|
|
@@ -2551,6 +2621,8 @@ resquery_send(resquery_t *query) {
|
|
|
|
|
if (peer != NULL) {
|
|
|
|
|
uint8_t ednsversion;
|
|
|
|
|
(void)dns_peer_getrequestnsid(peer, &reqnsid);
|
|
|
|
|
(void)dns_peer_getrequestnsid(peer,
|
|
|
|
|
&grease_nsid);
|
|
|
|
|
(void)dns_peer_getsendcookie(peer, &sendcookie);
|
|
|
|
|
result = dns_peer_getednsversion(peer,
|
|
|
|
|
&ednsversion);
|
|
|
|
@@ -2558,12 +2630,14 @@ resquery_send(resquery_t *query) {
|
|
|
|
|
ednsversion < version)
|
|
|
|
|
{
|
|
|
|
|
version = ednsversion;
|
|
|
|
|
query->attributes &=
|
|
|
|
|
~RESQUERY_ATTR_EDNS_NEG;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (NOCOOKIE(query->addrinfo)) {
|
|
|
|
|
sendcookie = false;
|
|
|
|
|
}
|
|
|
|
|
if (reqnsid) {
|
|
|
|
|
if (reqnsid || grease_nsid) {
|
|
|
|
|
INSIST(ednsopt < DNS_EDNSOPTIONS);
|
|
|
|
|
ednsopts[ednsopt].code = DNS_OPT_NSID;
|
|
|
|
|
ednsopts[ednsopt].length = 0;
|
|
|
|
@@ -2623,7 +2697,7 @@ resquery_send(resquery_t *query) {
|
|
|
|
|
|
|
|
|
|
query->ednsversion = version;
|
|
|
|
|
result = fctx_addopt(fctx->qmessage, version, udpsize,
|
|
|
|
|
ednsopts, ednsopt);
|
|
|
|
|
ednsflags, ednsopts, ednsopt);
|
|
|
|
|
if (reqnsid && result == ISC_R_SUCCESS) {
|
|
|
|
|
query->options |= DNS_FETCHOPT_WANTNSID;
|
|
|
|
|
} else if (result != ISC_R_SUCCESS) {
|
|
|
|
@@ -4912,6 +4986,9 @@ log_lame(fetchctx_t *fctx, dns_adbaddrinfo_t *addrinfo) {
|
|
|
|
|
namebuf, domainbuf, addrbuf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
log_formerr(fetchctx_t *fctx, const char *format, ...) ISC_FORMAT_PRINTF(2, 3);
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
log_formerr(fetchctx_t *fctx, const char *format, ...) {
|
|
|
|
|
char nsbuf[ISC_SOCKADDR_FORMATSIZE];
|
|
|
|
@@ -4930,6 +5007,27 @@ log_formerr(fetchctx_t *fctx, const char *format, ...) {
|
|
|
|
|
fctx->info, fctx->clientstr, msgbuf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
log_grease(fetchctx_t *fctx, const char *test, const char *format, ...)
|
|
|
|
|
ISC_FORMAT_PRINTF(3, 4);
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
log_grease(fetchctx_t *fctx, const char *test, const char *format, ...) {
|
|
|
|
|
char nsbuf[ISC_SOCKADDR_FORMATSIZE];
|
|
|
|
|
char msgbuf[2048];
|
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
|
|
va_start(args, format);
|
|
|
|
|
vsnprintf(msgbuf, sizeof(msgbuf), format, args);
|
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
|
|
isc_sockaddr_format(&fctx->addrinfo->sockaddr, nsbuf, sizeof(nsbuf));
|
|
|
|
|
|
|
|
|
|
isc_log_write(DNS_LOGCATEGORY_GREASE, DNS_LOGMODULE_RESOLVER,
|
|
|
|
|
ISC_LOG_NOTICE, "%s: %s %s: %s", test, nsbuf, fctx->info,
|
|
|
|
|
msgbuf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
|
same_question(fetchctx_t *fctx, dns_message_t *message) {
|
|
|
|
|
isc_result_t result;
|
|
|
|
@@ -7270,17 +7368,38 @@ checknames(dns_message_t *message) {
|
|
|
|
|
checknamessection(message, DNS_SECTION_ADDITIONAL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
make_hex(unsigned char *src, size_t srclen, char *buf, size_t buflen) {
|
|
|
|
|
isc_buffer_t b;
|
|
|
|
|
isc_region_t r;
|
|
|
|
|
isc_result_t result;
|
|
|
|
|
|
|
|
|
|
r.base = src;
|
|
|
|
|
r.length = srclen;
|
|
|
|
|
isc_buffer_init(&b, buf, buflen);
|
|
|
|
|
result = isc_hex_totext(&r, 0, "", &b);
|
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
|
isc_buffer_putuint8(&b, '\0');
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
make_printable(unsigned char *src, size_t srclen, char *buf, size_t buflen) {
|
|
|
|
|
INSIST(buflen > srclen);
|
|
|
|
|
while (srclen-- > 0) {
|
|
|
|
|
unsigned char c = *src++;
|
|
|
|
|
*buf++ = isprint(c) ? c : '.';
|
|
|
|
|
}
|
|
|
|
|
*buf = '\0';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Log server NSID at log level 'level'
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
log_nsid(isc_buffer_t *opt, size_t nsid_len, resquery_t *query, int level,
|
|
|
|
|
isc_mem_t *mctx) {
|
|
|
|
|
static const char hex[17] = "0123456789abcdef";
|
|
|
|
|
char addrbuf[ISC_SOCKADDR_FORMATSIZE];
|
|
|
|
|
char addrbuf[ISC_SOCKADDR_FORMATSIZE], *buf = NULL, *pbuf = NULL;
|
|
|
|
|
size_t buflen;
|
|
|
|
|
unsigned char *p, *nsid;
|
|
|
|
|
unsigned char *buf = NULL, *pbuf = NULL;
|
|
|
|
|
|
|
|
|
|
REQUIRE(nsid_len <= UINT16_MAX);
|
|
|
|
|
|
|
|
|
@@ -7290,20 +7409,10 @@ log_nsid(isc_buffer_t *opt, size_t nsid_len, resquery_t *query, int level,
|
|
|
|
|
pbuf = isc_mem_get(mctx, nsid_len + 1);
|
|
|
|
|
|
|
|
|
|
/* Convert to hex */
|
|
|
|
|
p = buf;
|
|
|
|
|
nsid = isc_buffer_current(opt);
|
|
|
|
|
for (size_t i = 0; i < nsid_len; i++) {
|
|
|
|
|
*p++ = hex[(nsid[i] >> 4) & 0xf];
|
|
|
|
|
*p++ = hex[nsid[i] & 0xf];
|
|
|
|
|
}
|
|
|
|
|
*p = '\0';
|
|
|
|
|
make_hex(isc_buffer_current(opt), nsid_len, buf, buflen);
|
|
|
|
|
|
|
|
|
|
/* Make printable version */
|
|
|
|
|
p = pbuf;
|
|
|
|
|
for (size_t i = 0; i < nsid_len; i++) {
|
|
|
|
|
*p++ = isprint(nsid[i]) ? nsid[i] : '.';
|
|
|
|
|
}
|
|
|
|
|
*p = '\0';
|
|
|
|
|
make_printable(isc_buffer_current(opt), nsid_len, pbuf, nsid_len + 1);
|
|
|
|
|
|
|
|
|
|
isc_sockaddr_format(&query->addrinfo->sockaddr, addrbuf,
|
|
|
|
|
sizeof(addrbuf));
|
|
|
|
@@ -8108,6 +8217,10 @@ rctx_opt(respctx_t *rctx) {
|
|
|
|
|
}
|
|
|
|
|
seen_nsid = true;
|
|
|
|
|
|
|
|
|
|
/* Save pointer to the NSID for log_grease. */
|
|
|
|
|
query->grease_nsid = isc_buffer_current(&optbuf);
|
|
|
|
|
query->grease_nsid_len = optlen;
|
|
|
|
|
|
|
|
|
|
if ((query->options & DNS_FETCHOPT_WANTNSID) != 0) {
|
|
|
|
|
log_nsid(&optbuf, optlen, query, ISC_LOG_INFO,
|
|
|
|
|
fctx->mctx);
|
|
|
|
@@ -8160,8 +8273,16 @@ rctx_opt(respctx_t *rctx) {
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
rctx_edns(respctx_t *rctx) {
|
|
|
|
|
resquery_t *query = rctx->query;
|
|
|
|
|
fetchctx_t *fctx = rctx->fctx;
|
|
|
|
|
resquery_t *query = rctx->query;
|
|
|
|
|
char *nsid_buf = NULL;
|
|
|
|
|
char *nsid_pbuf = NULL;
|
|
|
|
|
const char *grease_sep_1 = "";
|
|
|
|
|
const char *grease_sep_2 = "";
|
|
|
|
|
const char *grease_sep_3 = "";
|
|
|
|
|
const char *nsid_hex = "";
|
|
|
|
|
const char *nsid_print = "";
|
|
|
|
|
size_t nsid_buflen = 0;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We have an affirmative response to the query and we have
|
|
|
|
@@ -8211,6 +8332,120 @@ rctx_edns(respctx_t *rctx) {
|
|
|
|
|
FCTX_ADDRINFO_NOEDNS0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define GREASE_NSID_FMT "%s%s%s%s%s"
|
|
|
|
|
#define GREASE_NSID_INFO \
|
|
|
|
|
grease_sep_1, nsid_hex, grease_sep_2, nsid_print, grease_sep_3
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Turn NSID into printable forms.
|
|
|
|
|
*/
|
|
|
|
|
if (query->grease_nsid != NULL && query->grease_nsid_len != 0) {
|
|
|
|
|
nsid_buflen = query->grease_nsid_len * 2 + 1;
|
|
|
|
|
nsid_hex = nsid_buf = isc_mem_get(fctx->mctx, nsid_buflen);
|
|
|
|
|
nsid_print = nsid_pbuf =
|
|
|
|
|
isc_mem_get(fctx->mctx, query->grease_nsid_len + 1);
|
|
|
|
|
|
|
|
|
|
/* Convert to hex */
|
|
|
|
|
make_hex(query->grease_nsid, query->grease_nsid_len, nsid_buf,
|
|
|
|
|
nsid_buflen);
|
|
|
|
|
|
|
|
|
|
/* Convert to printable */
|
|
|
|
|
make_printable(query->grease_nsid, query->grease_nsid_len,
|
|
|
|
|
nsid_pbuf, query->grease_nsid_len + 1);
|
|
|
|
|
|
|
|
|
|
grease_sep_1 = " (NSID ";
|
|
|
|
|
grease_sep_2 = " (";
|
|
|
|
|
grease_sep_3 = "))";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* GREASE: Check that the final DNS header flag is not
|
|
|
|
|
* echoed back.
|
|
|
|
|
*/
|
|
|
|
|
if ((query->attributes & RESQUERY_ATTR_DNS_FLAGS) != 0) {
|
|
|
|
|
/*
|
|
|
|
|
* The last DNS header flag should be ignored
|
|
|
|
|
* by the received and be zero when transmitted.
|
|
|
|
|
*/
|
|
|
|
|
if ((query->rmessage->flags & 0x40) != 0) {
|
|
|
|
|
log_grease(
|
|
|
|
|
fctx, "grease-dns-flags",
|
|
|
|
|
"DNS header flag 0x40 not zero" GREASE_NSID_FMT,
|
|
|
|
|
GREASE_NSID_INFO);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* GREASE: Check that the unknown EDNS flags bit are not
|
|
|
|
|
* echoed back.
|
|
|
|
|
*/
|
|
|
|
|
if ((query->attributes & RESQUERY_ATTR_EDNS_FLAGS) != 0 &&
|
|
|
|
|
rctx->opt != NULL)
|
|
|
|
|
{
|
|
|
|
|
uint16_t ednsflags = rctx->opt->ttl & 0xffff;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Ignore known flags.
|
|
|
|
|
*/
|
|
|
|
|
ednsflags &= ~fctx->res->view->grease_edns_known_flags;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Was our unspecified EDNS flag echoed back?
|
|
|
|
|
*/
|
|
|
|
|
if ((ednsflags & query->grease_ednsflags) != 0) {
|
|
|
|
|
log_grease(fctx, "grease-edns-flags",
|
|
|
|
|
"Unspecified EDNS flags not zero: "
|
|
|
|
|
"%04x" GREASE_NSID_FMT,
|
|
|
|
|
ednsflags, GREASE_NSID_INFO);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* GREASE: Check that we have the expected rcode (BADVERS)
|
|
|
|
|
* and version(s) (0).
|
|
|
|
|
*/
|
|
|
|
|
if ((query->attributes & RESQUERY_ATTR_EDNS_NEG) != 0 &&
|
|
|
|
|
rctx->opt != NULL)
|
|
|
|
|
{
|
|
|
|
|
uint8_t version = (rctx->opt->ttl >> 16) & 0xff;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* We expect the rcode to be BADVERS because we sent EDNS
|
|
|
|
|
* version 100.
|
|
|
|
|
*/
|
|
|
|
|
if (query->rmessage->rcode != dns_rcode_badvers) {
|
|
|
|
|
log_grease(fctx, "grease-edns-negotiation",
|
|
|
|
|
"EDNS version negotiation: rcode != "
|
|
|
|
|
"BADVERS(16): %u" GREASE_NSID_FMT,
|
|
|
|
|
query->rmessage->rcode, GREASE_NSID_INFO);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Only EDNS(0) is currently specified.
|
|
|
|
|
*/
|
|
|
|
|
if (version > fctx->res->view->grease_edns_max_version) {
|
|
|
|
|
log_grease(fctx, "grease-edns-negotiation",
|
|
|
|
|
"EDNS version negotiation: version > %u: "
|
|
|
|
|
"%u" GREASE_NSID_FMT,
|
|
|
|
|
fctx->res->view->grease_edns_max_version,
|
|
|
|
|
version, GREASE_NSID_INFO);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Cleanup NSID buffers.
|
|
|
|
|
*/
|
|
|
|
|
if (nsid_pbuf != NULL) {
|
|
|
|
|
isc_mem_put(fctx->mctx, nsid_pbuf, query->grease_nsid_len + 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nsid_buf != NULL) {
|
|
|
|
|
isc_mem_put(fctx->mctx, nsid_buf, nsid_buflen);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#undef GREASE_NSID_FMT
|
|
|
|
|
#undef GREASE_NSID_INFO
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we get a non error EDNS response record the fact so we
|
|
|
|
|
* won't fallback to plain DNS in the future for this server.
|
|
|
|
@@ -9844,18 +10079,14 @@ rctx_badserver(respctx_t *rctx, isc_result_t result) {
|
|
|
|
|
}
|
|
|
|
|
} else if (rcode == dns_rcode_badvers) {
|
|
|
|
|
unsigned int version;
|
|
|
|
|
#if DNS_EDNS_VERSION > 0
|
|
|
|
|
unsigned int flags, mask;
|
|
|
|
|
#endif /* if DNS_EDNS_VERSION > 0 */
|
|
|
|
|
|
|
|
|
|
INSIST(rctx->opt != NULL);
|
|
|
|
|
version = (rctx->opt->ttl >> 16) & 0xff;
|
|
|
|
|
#if DNS_EDNS_VERSION > 0
|
|
|
|
|
flags = (version << DNS_FETCHOPT_EDNSVERSIONSHIFT) |
|
|
|
|
|
DNS_FETCHOPT_EDNSVERSIONSET;
|
|
|
|
|
mask = DNS_FETCHOPT_EDNSVERSIONMASK |
|
|
|
|
|
DNS_FETCHOPT_EDNSVERSIONSET;
|
|
|
|
|
#endif /* if DNS_EDNS_VERSION > 0 */
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Record that we got a good EDNS response.
|
|
|
|
@@ -9876,7 +10107,6 @@ rctx_badserver(respctx_t *rctx, isc_result_t result) {
|
|
|
|
|
* version checking of badvers responses. We won't
|
|
|
|
|
* be sending COOKIE etc. in that case.
|
|
|
|
|
*/
|
|
|
|
|
#if DNS_EDNS_VERSION > 0
|
|
|
|
|
if ((int)version < query->ednsversion) {
|
|
|
|
|
dns_adb_changeflags(fctx->adb, query->addrinfo, flags,
|
|
|
|
|
mask);
|
|
|
|
@@ -9885,10 +10115,6 @@ rctx_badserver(respctx_t *rctx, isc_result_t result) {
|
|
|
|
|
rctx->broken_server = DNS_R_BADVERS;
|
|
|
|
|
rctx->next_server = true;
|
|
|
|
|
}
|
|
|
|
|
#else /* if DNS_EDNS_VERSION > 0 */
|
|
|
|
|
rctx->broken_server = DNS_R_BADVERS;
|
|
|
|
|
rctx->next_server = true;
|
|
|
|
|
#endif /* if DNS_EDNS_VERSION > 0 */
|
|
|
|
|
} else if (rcode == dns_rcode_badcookie && rctx->query->rmessage->cc_ok)
|
|
|
|
|
{
|
|
|
|
|
/*
|
|
|
|
@@ -9904,10 +10130,12 @@ rctx_badserver(respctx_t *rctx, isc_result_t result) {
|
|
|
|
|
rctx->next_server = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
isc_buffer_init(&b, code, sizeof(code) - 1);
|
|
|
|
|
dns_rcode_totext(rcode, &b);
|
|
|
|
|
code[isc_buffer_usedlength(&b)] = '\0';
|
|
|
|
|
FCTXTRACE2("remote server broken: returned ", code);
|
|
|
|
|
if (rctx->broken_server != ISC_R_SUCCESS) {
|
|
|
|
|
isc_buffer_init(&b, code, sizeof(code) - 1);
|
|
|
|
|
dns_rcode_totext(rcode, &b);
|
|
|
|
|
code[isc_buffer_usedlength(&b)] = '\0';
|
|
|
|
|
FCTXTRACE2("remote server broken: returned ", code);
|
|
|
|
|
}
|
|
|
|
|
rctx_done(rctx, result);
|
|
|
|
|
|
|
|
|
|
return ISC_R_COMPLETE;
|
|
|
|
|