2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-28 13:08:06 +00:00

Simplify the EDNS buffer size logic for DNS Flag Day 2020

The DNS Flag Day 2020 aims to remove the IP fragmentation problem from
the UDP DNS communication.  In this commit, we implement the required
changes and simplify the logic for picking the EDNS Buffer Size.

1. The defaults for `edns-udp-size`, `max-udp-size` and
   `nocookie-udp-size` have been changed to `1232` (the value picked by
   DNS Flag Day 2020).

2. The probing heuristics that would try 512->4096->1432->1232 buffer
   sizes has been removed and the resolver will always use just the
   `edns-udp-size` value.

3. Instead of just disabling the PMTUD mechanism on the UDP sockets, we
   now set IP_DONTFRAG (IPV6_DONTFRAG) flag.  That means that the UDP
   packets won't get ever fragmented.  If the ICMP packets are lost the
   UDP will just timeout and eventually be retried over TCP.
This commit is contained in:
Ondřej Surý 2020-09-23 14:47:26 +02:00
parent d51f09a8d0
commit bb990030d3
9 changed files with 75 additions and 336 deletions

View File

@ -59,7 +59,7 @@ options {\n\
# directory <none>\n\ # directory <none>\n\
dnssec-policy \"none\";\n\ dnssec-policy \"none\";\n\
dump-file \"named_dump.db\";\n\ dump-file \"named_dump.db\";\n\
edns-udp-size 4096;\n\ edns-udp-size 1232;\n\
# fake-iquery <obsolete>;\n" # fake-iquery <obsolete>;\n"
#ifndef WIN32 #ifndef WIN32
" files unlimited;\n" " files unlimited;\n"
@ -83,11 +83,11 @@ options {\n\
match-mapped-addresses no;\n\ match-mapped-addresses no;\n\
max-ixfr-ratio 100%;\n\ max-ixfr-ratio 100%;\n\
max-rsa-exponent-size 0; /* no limit */\n\ max-rsa-exponent-size 0; /* no limit */\n\
max-udp-size 4096;\n\ max-udp-size 1232;\n\
memstatistics-file \"named.memstats\";\n\ memstatistics-file \"named.memstats\";\n\
# multiple-cnames <obsolete>;\n\ # multiple-cnames <obsolete>;\n\
# named-xfer <obsolete>;\n\ # named-xfer <obsolete>;\n\
nocookie-udp-size 4096;\n\ nocookie-udp-size 1232;\n\
notify-rate 20;\n\ notify-rate 20;\n\
nta-lifetime 3600;\n\ nta-lifetime 3600;\n\
nta-recheck 300;\n\ nta-recheck 300;\n\

View File

@ -1842,7 +1842,7 @@ Boolean Options
``nocookie-udp-size`` ``nocookie-udp-size``
This sets the maximum size of UDP responses that are sent to queries This sets the maximum size of UDP responses that are sent to queries
without a valid server COOKIE. A value below 128 is silently without a valid server COOKIE. A value below 128 is silently
raised to 128. The default value is 4096, but the ``max-udp-size`` raised to 128. The default value is 1232, but the ``max-udp-size``
option may further limit the response size. option may further limit the response size.
``sit-secret`` ``sit-secret``
@ -3399,7 +3399,7 @@ Tuning
the size of packets received from authoritative servers in response the size of packets received from authoritative servers in response
to recursive queries. Valid values are 512 to 4096; values outside to recursive queries. Valid values are 512 to 4096; values outside
this range are silently adjusted to the nearest value within it. this range are silently adjusted to the nearest value within it.
The default value is 4096. The default value is 1232.
The usual reason for setting ``edns-udp-size`` to a non-default value The usual reason for setting ``edns-udp-size`` to a non-default value
is to get UDP answers to pass through broken firewalls that block is to get UDP answers to pass through broken firewalls that block
@ -3407,26 +3407,12 @@ Tuning
512 bytes. 512 bytes.
When ``named`` first queries a remote server, it advertises a UDP When ``named`` first queries a remote server, it advertises a UDP
buffer size of 512, as this has the greatest chance of success on the buffer size of 1232.
first try.
If the initial query is successful with EDNS advertising a buffer Query timeouts observed for any given server affect the buffer size
size of 512, then ``named`` switches to advertising a buffer size advertised in queries sent to that server. Depending on observed packet
of 4096 bytes (unless ``edns-udp-size`` is lower, in which case the dropping patterns, the query is retried over TCP. Per-server EDNS statistics
latter will be used). are only retained in memory for the lifetime of a given server's ADB entry.
Query timeouts observed for any given server affect the buffer
size advertised in queries sent to that server. Depending on
observed packet dropping patterns, the advertised buffer size is
lowered to 1432 bytes, 1232 bytes, 512 bytes, or the size of the
largest UDP response ever received from a given server, and then
clamped to the ``<512, edns-udp-size>`` range. Per-server EDNS
statistics are only retained in memory for the lifetime of a given
server's ADB entry.
(The values 1232 and 1432 are chosen to allow for an
IPv4-/IPv6-encapsulated UDP message to be sent without fragmentation at the
minimum MTU sizes for Ethernet and IPv6 networks.)
Any server-specific ``edns-udp-size`` setting has precedence over all Any server-specific ``edns-udp-size`` setting has precedence over all
the above rules. the above rules.
@ -3435,7 +3421,7 @@ Tuning
This sets the maximum EDNS UDP message size that ``named`` sends, in bytes. This sets the maximum EDNS UDP message size that ``named`` sends, in bytes.
Valid values are 512 to 4096; values outside this range are Valid values are 512 to 4096; values outside this range are
silently adjusted to the nearest value within it. The default value silently adjusted to the nearest value within it. The default value
is 4096. is 1232.
This value applies to responses sent by a server; to set the This value applies to responses sent by a server; to set the
advertised buffer size in queries, see ``edns-udp-size``. advertised buffer size in queries, see ``edns-udp-size``.

View File

@ -249,20 +249,13 @@ struct dns_adbentry {
unsigned char plain; unsigned char plain;
unsigned char plainto; unsigned char plainto;
unsigned char edns; unsigned char edns;
unsigned char to4096; /* Our max. */ unsigned char ednsto;
uint8_t mode; uint8_t mode;
atomic_uint_fast32_t quota; atomic_uint_fast32_t quota;
atomic_uint_fast32_t active; atomic_uint_fast32_t active;
double atr; double atr;
/*
* Allow for encapsulated IPv4/IPv6 UDP packet over ethernet.
* Ethernet 1500 - IP(20) - IP6(40) - UDP(8) = 1432.
*/
unsigned char to1432; /* Ethernet */
unsigned char to1232; /* IPv6 nofrag */
unsigned char to512; /* plain DNS */
isc_sockaddr_t sockaddr; isc_sockaddr_t sockaddr;
unsigned char *cookie; unsigned char *cookie;
uint16_t cookielen; uint16_t cookielen;
@ -1893,14 +1886,11 @@ new_adbentry(dns_adb_t *adb) {
e->flags = 0; e->flags = 0;
e->udpsize = 0; e->udpsize = 0;
e->edns = 0; e->edns = 0;
e->ednsto = 0;
e->completed = 0; e->completed = 0;
e->timeouts = 0; e->timeouts = 0;
e->plain = 0; e->plain = 0;
e->plainto = 0; e->plainto = 0;
e->to4096 = 0;
e->to1432 = 0;
e->to1232 = 0;
e->to512 = 0;
e->cookie = NULL; e->cookie = NULL;
e->cookielen = 0; e->cookielen = 0;
e->srtt = (isc_random_uniform(0x1f)) + 1; e->srtt = (isc_random_uniform(0x1f)) + 1;
@ -3529,8 +3519,7 @@ dump_adb(dns_adb_t *adb, FILE *f, bool debug, isc_stdtime_t now) {
dns_adbentry_t *entry; dns_adbentry_t *entry;
fprintf(f, ";\n; Address database dump\n;\n"); fprintf(f, ";\n; Address database dump\n;\n");
fprintf(f, "; [edns success/4096 timeout/1432 timeout/1232 timeout/" fprintf(f, "; [edns success/timeout]\n");
"512 timeout]\n");
fprintf(f, "; [plain success/timeout]\n;\n"); fprintf(f, "; [plain success/timeout]\n;\n");
if (debug) { if (debug) {
LOCK(&adb->reflock); LOCK(&adb->reflock);
@ -3656,11 +3645,10 @@ dump_entry(FILE *f, dns_adb_t *adb, dns_adbentry_t *entry, bool debug,
} }
fprintf(f, fprintf(f,
";\t%s [srtt %u] [flags %08x] [edns %u/%u/%u/%u/%u] " ";\t%s [srtt %u] [flags %08x] [edns %u/%u] "
"[plain %u/%u]", "[plain %u/%u]",
addrbuf, entry->srtt, entry->flags, entry->edns, entry->to4096, addrbuf, entry->srtt, entry->flags, entry->edns, entry->ednsto,
entry->to1432, entry->to1232, entry->to512, entry->plain, entry->plain, entry->plainto);
entry->plainto);
if (entry->udpsize != 0U) { if (entry->udpsize != 0U) {
fprintf(f, " [udpsize %u]", entry->udpsize); fprintf(f, " [udpsize %u]", entry->udpsize);
} }
@ -4437,41 +4425,6 @@ maybe_adjust_quota(dns_adb_t *adb, dns_adbaddrinfo_t *addr, bool timeout) {
} }
#define EDNSTOS 3U #define EDNSTOS 3U
bool
dns_adb_noedns(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
int bucket;
bool noedns = false;
REQUIRE(DNS_ADB_VALID(adb));
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
bucket = addr->entry->lock_bucket;
LOCK(&adb->entrylocks[bucket]);
if (addr->entry->edns == 0U &&
(addr->entry->plain > EDNSTOS || addr->entry->to4096 > EDNSTOS))
{
if (((addr->entry->plain + addr->entry->to4096) & 0x3f) != 0) {
noedns = true;
} else {
/*
* Increment plain so we don't get stuck.
*/
addr->entry->plain++;
if (addr->entry->plain == 0xff) {
addr->entry->edns >>= 1;
addr->entry->to4096 >>= 1;
addr->entry->to1432 >>= 1;
addr->entry->to1232 >>= 1;
addr->entry->to512 >>= 1;
addr->entry->plain >>= 1;
addr->entry->plainto >>= 1;
}
}
}
UNLOCK(&adb->entrylocks[bucket]);
return (noedns);
}
void void
dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr) { dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
@ -4488,10 +4441,7 @@ dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
addr->entry->plain++; addr->entry->plain++;
if (addr->entry->plain == 0xff) { if (addr->entry->plain == 0xff) {
addr->entry->edns >>= 1; addr->entry->edns >>= 1;
addr->entry->to4096 >>= 1; addr->entry->ednsto >>= 1;
addr->entry->to1432 >>= 1;
addr->entry->to1232 >>= 1;
addr->entry->to512 >>= 1;
addr->entry->plain >>= 1; addr->entry->plain >>= 1;
addr->entry->plainto >>= 1; addr->entry->plainto >>= 1;
} }
@ -4510,25 +4460,10 @@ dns_adb_timeout(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
maybe_adjust_quota(adb, addr, true); maybe_adjust_quota(adb, addr, true);
/*
* If we have not had a successful query then clear all
* edns timeout information.
*/
if (addr->entry->edns == 0 && addr->entry->plain == 0) {
addr->entry->to512 = 0;
addr->entry->to1232 = 0;
addr->entry->to1432 = 0;
addr->entry->to4096 = 0;
} else {
addr->entry->to512 >>= 1;
addr->entry->to1232 >>= 1;
addr->entry->to1432 >>= 1;
addr->entry->to4096 >>= 1;
}
addr->entry->plainto++; addr->entry->plainto++;
if (addr->entry->plainto == 0xff) { if (addr->entry->plainto == 0xff) {
addr->entry->edns >>= 1; addr->entry->edns >>= 1;
addr->entry->ednsto >>= 1;
addr->entry->plain >>= 1; addr->entry->plain >>= 1;
addr->entry->plainto >>= 1; addr->entry->plainto >>= 1;
} }
@ -4536,7 +4471,7 @@ dns_adb_timeout(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
} }
void void
dns_adb_ednsto(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size) { dns_adb_ednsto(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
int bucket; int bucket;
REQUIRE(DNS_ADB_VALID(adb)); REQUIRE(DNS_ADB_VALID(adb));
@ -4547,36 +4482,10 @@ dns_adb_ednsto(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size) {
maybe_adjust_quota(adb, addr, true); maybe_adjust_quota(adb, addr, true);
if (size <= 512U) { addr->entry->ednsto++;
if (addr->entry->to512 <= EDNSTOS) { if (addr->entry->ednsto == 0xff) {
addr->entry->to512++;
addr->entry->to1232++;
addr->entry->to1432++;
addr->entry->to4096++;
}
} else if (size <= 1232U) {
if (addr->entry->to1232 <= EDNSTOS) {
addr->entry->to1232++;
addr->entry->to1432++;
addr->entry->to4096++;
}
} else if (size <= 1432U) {
if (addr->entry->to1432 <= EDNSTOS) {
addr->entry->to1432++;
addr->entry->to4096++;
}
} else {
if (addr->entry->to4096 <= EDNSTOS) {
addr->entry->to4096++;
}
}
if (addr->entry->to4096 == 0xff) {
addr->entry->edns >>= 1; addr->entry->edns >>= 1;
addr->entry->to4096 >>= 1; addr->entry->ednsto >>= 1;
addr->entry->to1432 >>= 1;
addr->entry->to1232 >>= 1;
addr->entry->to512 >>= 1;
addr->entry->plain >>= 1; addr->entry->plain >>= 1;
addr->entry->plainto >>= 1; addr->entry->plainto >>= 1;
} }
@ -4604,10 +4513,7 @@ dns_adb_setudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size) {
addr->entry->edns++; addr->entry->edns++;
if (addr->entry->edns == 0xff) { if (addr->entry->edns == 0xff) {
addr->entry->edns >>= 1; addr->entry->edns >>= 1;
addr->entry->to4096 >>= 1; addr->entry->ednsto >>= 1;
addr->entry->to1432 >>= 1;
addr->entry->to1232 >>= 1;
addr->entry->to512 >>= 1;
addr->entry->plain >>= 1; addr->entry->plain >>= 1;
addr->entry->plainto >>= 1; addr->entry->plainto >>= 1;
} }
@ -4630,38 +4536,6 @@ dns_adb_getudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr) {
return (size); return (size);
} }
unsigned int
dns_adb_probesize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, int lookups) {
int bucket;
unsigned int size;
REQUIRE(DNS_ADB_VALID(adb));
REQUIRE(DNS_ADBADDRINFO_VALID(addr));
bucket = addr->entry->lock_bucket;
LOCK(&adb->entrylocks[bucket]);
if (addr->entry->to1232 > EDNSTOS || lookups >= 2) {
size = 512;
} else if (addr->entry->to1432 > EDNSTOS || lookups >= 1) {
size = 1232;
} else if (addr->entry->to4096 > EDNSTOS) {
size = 1432;
} else {
size = 4096;
}
/*
* Don't shrink probe size below what we have seen due to multiple
* lookups.
*/
if (lookups > 0 && size < addr->entry->udpsize &&
addr->entry->udpsize < 4096) {
size = addr->entry->udpsize;
}
UNLOCK(&adb->entrylocks[bucket]);
return (size);
}
void void
dns_adb_setcookie(dns_adb_t *adb, dns_adbaddrinfo_t *addr, dns_adb_setcookie(dns_adb_t *adb, dns_adbaddrinfo_t *addr,
const unsigned char *cookie, size_t len) { const unsigned char *cookie, size_t len) {

View File

@ -606,19 +606,6 @@ dns_adb_getudpsize(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
*\li addr be valid. *\li addr be valid.
*/ */
unsigned int
dns_adb_probesize(dns_adb_t *adb, dns_adbaddrinfo_t *addr, int lookups);
/*%
* Return suggested EDNS UDP size based on observed responses / failures.
* 'lookups' is the number of times the current lookup has been attempted.
*
* Requires:
*
*\li adb be valid.
*
*\li addr be valid.
*/
void void
dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr); dns_adb_plainresponse(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
/*% /*%
@ -644,22 +631,9 @@ dns_adb_timeout(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
*/ */
void void
dns_adb_ednsto(dns_adb_t *adb, dns_adbaddrinfo_t *addr, unsigned int size); dns_adb_ednsto(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
/*% /*%
* Record a failed EDNS UDP response and the advertised EDNS UDP buffer size * Record a EDNS UDP query failed.
* used.
*
* Requires:
*
*\li adb be valid.
*
*\li addr be valid.
*/
bool
dns_adb_noedns(dns_adb_t *adb, dns_adbaddrinfo_t *addr);
/*%
* Return whether EDNS should be disabled for this server.
* *
* Requires: * Requires:
* *

View File

@ -94,13 +94,11 @@ typedef enum { dns_quotatype_zone = 0, dns_quotatype_server } dns_quotatype_t;
#define DNS_FETCHOPT_NOEDNS0 0x00000008 /*%< Do not use EDNS. */ #define DNS_FETCHOPT_NOEDNS0 0x00000008 /*%< Do not use EDNS. */
#define DNS_FETCHOPT_FORWARDONLY 0x00000010 /*%< Only use forwarders. */ #define DNS_FETCHOPT_FORWARDONLY 0x00000010 /*%< Only use forwarders. */
#define DNS_FETCHOPT_NOVALIDATE 0x00000020 /*%< Disable validation. */ #define DNS_FETCHOPT_NOVALIDATE 0x00000020 /*%< Disable validation. */
#define DNS_FETCHOPT_EDNS512 \ #define DNS_FETCHOPT_OBSOLETE1 0x00000040 /*%< Obsolete */
0x00000040 /*%< Advertise a 512 byte \ #define DNS_FETCHOPT_WANTNSID 0x00000080 /*%< Request NSID */
* UDP buffer. */ #define DNS_FETCHOPT_PREFETCH 0x00000100 /*%< Do prefetch */
#define DNS_FETCHOPT_WANTNSID 0x00000080 /*%< Request NSID */ #define DNS_FETCHOPT_NOCDFLAG 0x00000200 /*%< Don't set CD flag. */
#define DNS_FETCHOPT_PREFETCH 0x00000100 /*%< Do prefetch */ #define DNS_FETCHOPT_NONTA 0x00000400 /*%< Ignore NTA table. */
#define DNS_FETCHOPT_NOCDFLAG 0x00000200 /*%< Don't set CD flag. */
#define DNS_FETCHOPT_NONTA 0x00000400 /*%< Ignore NTA table. */
/* RESERVED ECS 0x00000000 */ /* RESERVED ECS 0x00000000 */
/* RESERVED ECS 0x00001000 */ /* RESERVED ECS 0x00001000 */
/* RESERVED ECS 0x00002000 */ /* RESERVED ECS 0x00002000 */

View File

@ -203,6 +203,11 @@
*/ */
#define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */ #define RECV_BUFFER_SIZE 4096 /* XXXRTH Constant. */
/*%
* Default EDNS0 buffer size
*/
#define DEFAULT_EDNS_BUFSIZE 1232
/*% /*%
* This defines the maximum number of timeouts we will permit before we * This defines the maximum number of timeouts we will permit before we
* disable EDNS0 on the query. * disable EDNS0 on the query.
@ -316,7 +321,6 @@ struct fetchctx {
dns_fwdpolicy_t fwdpolicy; dns_fwdpolicy_t fwdpolicy;
isc_sockaddrlist_t bad; isc_sockaddrlist_t bad;
ISC_LIST(struct tried) edns; ISC_LIST(struct tried) edns;
ISC_LIST(struct tried) edns512;
isc_sockaddrlist_t bad_edns; isc_sockaddrlist_t bad_edns;
dns_validator_t *validator; dns_validator_t *validator;
ISC_LIST(dns_validator_t) validators; ISC_LIST(dns_validator_t) validators;
@ -1215,7 +1219,7 @@ update_edns_stats(resquery_t *query) {
} }
if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) { if ((query->options & DNS_FETCHOPT_NOEDNS0) == 0) {
dns_adb_ednsto(fctx->adb, query->addrinfo, query->udpsize); dns_adb_ednsto(fctx->adb, query->addrinfo);
} else { } else {
dns_adb_timeout(fctx->adb, query->addrinfo); dns_adb_timeout(fctx->adb, query->addrinfo);
} }
@ -2321,38 +2325,6 @@ add_triededns(fetchctx_t *fctx, isc_sockaddr_t *address) {
ISC_LIST_INITANDAPPEND(fctx->edns, tried, link); ISC_LIST_INITANDAPPEND(fctx->edns, tried, link);
} }
static struct tried *
triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
struct tried *tried;
for (tried = ISC_LIST_HEAD(fctx->edns512); tried != NULL;
tried = ISC_LIST_NEXT(tried, link))
{
if (isc_sockaddr_equal(&tried->addr, address)) {
return (tried);
}
}
return (NULL);
}
static void
add_triededns512(fetchctx_t *fctx, isc_sockaddr_t *address) {
struct tried *tried;
tried = triededns512(fctx, address);
if (tried != NULL) {
tried->count++;
return;
}
tried = isc_mem_get(fctx->mctx, sizeof(*tried));
tried->addr = *address;
tried->count = 1;
ISC_LIST_INITANDAPPEND(fctx->edns512, tried, link);
}
static inline size_t static inline size_t
addr2buf(void *buf, const size_t bufsize, const isc_sockaddr_t *sockaddr) { addr2buf(void *buf, const size_t bufsize, const isc_sockaddr_t *sockaddr) {
isc_netaddr_t netaddr; isc_netaddr_t netaddr;
@ -2607,15 +2579,14 @@ resquery_send(resquery_t *query) {
* response size we have seen from this server so far. * response size we have seen from this server so far.
* *
* If this server has already timed out twice or more in this * If this server has already timed out twice or more in this
* fetch context, force setting the advertised UDP buffer size * fetch context, force TCP.
* to 512 bytes.
*/ */
if ((tried = triededns(fctx, sockaddr)) != NULL) { if ((tried = triededns(fctx, sockaddr)) != NULL) {
if (tried->count == 1U) { if (tried->count == 1U) {
hint = dns_adb_getudpsize(fctx->adb, hint = dns_adb_getudpsize(fctx->adb,
query->addrinfo); query->addrinfo);
} else if (tried->count >= 2U) { } else if (tried->count >= 2U) {
query->options |= DNS_FETCHOPT_EDNS512; query->options |= DNS_FETCHOPT_TCP;
} }
} }
} }
@ -2637,23 +2608,10 @@ resquery_send(resquery_t *query) {
uint16_t padding = 0; uint16_t padding = 0;
/* /*
* If we ever received an EDNS response from this * Set the default UDP size to what was configured as
* server, initialize 'udpsize' with a value between * 'edns-buffer-size'
* 512 and 4096, based on any potential EDNS timeouts
* observed for this particular server in the past and
* the total number of query timeouts observed for this
* fetch context so far. Clamp 'udpsize' to the global
* 'edns-udp-size' value (if unset, the latter defaults
* to 4096 bytes).
*/ */
if ((flags & FCTX_ADDRINFO_EDNSOK) != 0) { udpsize = res->udpsize;
udpsize = dns_adb_probesize(fctx->adb,
query->addrinfo,
fctx->timeouts);
if (udpsize > res->udpsize) {
udpsize = res->udpsize;
}
}
/* /*
* This server timed out for the first time in this * This server timed out for the first time in this
@ -2667,17 +2625,6 @@ resquery_send(resquery_t *query) {
udpsize = hint; udpsize = hint;
} }
/*
* If we have not received any responses from this
* server before or if this server has already timed
* out twice or more in this fetch context, use an EDNS
* UDP buffer size of 512 bytes.
*/
if (udpsize == 0U ||
(query->options & DNS_FETCHOPT_EDNS512) != 0) {
udpsize = 512;
}
/* /*
* If a fixed EDNS UDP buffer size is configured for * If a fixed EDNS UDP buffer size is configured for
* this server, make sure we obey that. * this server, make sure we obey that.
@ -2805,13 +2752,7 @@ resquery_send(resquery_t *query) {
goto cleanup_message; goto cleanup_message;
} }
if (udpsize > 512U) { add_triededns(fctx, &query->addrinfo->sockaddr);
add_triededns(fctx, &query->addrinfo->sockaddr);
}
if (udpsize == 512U) {
add_triededns512(fctx, &query->addrinfo->sockaddr);
}
/* /*
* Clear CD if EDNS is not in use. * Clear CD if EDNS is not in use.
@ -3101,17 +3042,10 @@ resquery_connected(isc_task_t *task, isc_event_t *event) {
isc_socket_detach(&query->tcpsocket); isc_socket_detach(&query->tcpsocket);
/* /*
* Do not query this server again in this fetch context * Do not query this server again in this fetch context
* if we already tried reducing the advertised EDNS UDP * if the server is unavailable over TCP.
* payload size to 512 bytes and the server is
* unavailable over TCP. This prevents query loops
* lasting until the fetch context restart limit is
* reached when attempting to get answers whose size
* exceeds 512 bytes from broken servers.
*/ */
if ((query->options & DNS_FETCHOPT_EDNS512) != 0) { add_bad(fctx, query->rmessage, query->addrinfo,
add_bad(fctx, query->rmessage, query->addrinfo, sevent->result, badns_unreachable);
sevent->result, badns_unreachable);
}
fctx_cancelquery(&query, NULL, NULL, true, false); fctx_cancelquery(&query, NULL, NULL, true, false);
retry = true; retry = true;
break; break;
@ -4556,13 +4490,6 @@ fctx_destroy(fetchctx_t *fctx) {
isc_mem_put(fctx->mctx, tried, sizeof(*tried)); isc_mem_put(fctx->mctx, tried, sizeof(*tried));
} }
for (tried = ISC_LIST_HEAD(fctx->edns512); tried != NULL;
tried = ISC_LIST_HEAD(fctx->edns512))
{
ISC_LIST_UNLINK(fctx->edns512, tried, link);
isc_mem_put(fctx->mctx, tried, sizeof(*tried));
}
for (sa = ISC_LIST_HEAD(fctx->bad_edns); sa != NULL; sa = next_sa) { for (sa = ISC_LIST_HEAD(fctx->bad_edns); sa != NULL; sa = next_sa) {
next_sa = ISC_LIST_NEXT(sa, link); next_sa = ISC_LIST_NEXT(sa, link);
ISC_LIST_UNLINK(fctx->bad_edns, sa, link); ISC_LIST_UNLINK(fctx->bad_edns, sa, link);
@ -4993,7 +4920,6 @@ fctx_create(dns_resolver_t *res, const dns_name_t *name, dns_rdatatype_t type,
fctx->fwdpolicy = dns_fwdpolicy_none; fctx->fwdpolicy = dns_fwdpolicy_none;
ISC_LIST_INIT(fctx->bad); ISC_LIST_INIT(fctx->bad);
ISC_LIST_INIT(fctx->edns); ISC_LIST_INIT(fctx->edns);
ISC_LIST_INIT(fctx->edns512);
ISC_LIST_INIT(fctx->bad_edns); ISC_LIST_INIT(fctx->bad_edns);
ISC_LIST_INIT(fctx->validators); ISC_LIST_INIT(fctx->validators);
fctx->validator = NULL; fctx->validator = NULL;
@ -10190,7 +10116,7 @@ dns_resolver_create(dns_view_t *view, isc_taskmgr_t *taskmgr,
res->options = options; res->options = options;
res->lame_ttl = 0; res->lame_ttl = 0;
ISC_LIST_INIT(res->alternates); ISC_LIST_INIT(res->alternates);
res->udpsize = RECV_BUFFER_SIZE; res->udpsize = DEFAULT_EDNS_BUFSIZE;
res->algorithms = NULL; res->algorithms = NULL;
res->digests = NULL; res->digests = NULL;
res->badcache = NULL; res->badcache = NULL;

View File

@ -49,9 +49,7 @@ dns_adb_freeaddrinfo
dns_adb_getcookie dns_adb_getcookie
dns_adb_getudpsize dns_adb_getudpsize
dns_adb_marklame dns_adb_marklame
dns_adb_noedns
dns_adb_plainresponse dns_adb_plainresponse
dns_adb_probesize
dns_adb_setadbsize dns_adb_setadbsize
dns_adb_setcookie dns_adb_setcookie
dns_adb_setquota dns_adb_setquota

View File

@ -2102,6 +2102,32 @@ set_tcp_maxseg(isc__socket_t *sock, int size) {
#endif /* ifdef TCP_MAXSEG */ #endif /* ifdef TCP_MAXSEG */
} }
static void
set_ip_dontfrag(isc__socket_t *sock) {
/*
* Set the Don't Fragment flag on IP packets
*/
if (sock->pf == AF_INET6) {
#if defined(IPV6_DONTFRAG)
(void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_DONTFRAG,
&(int){ 1 }, sizeof(int));
#endif
#if defined(IPV6_MTU_DISCOVER)
(void)setsockopt(sock->fd, IPPROTO_IPV6, IPV6_MTU_DISCOVER,
&(int){ IP_PMTUDISC_DO }, sizeof(int));
#endif
} else if (sock->pf == AF_INET) {
#if defined(IP_DONTFRAG)
(void)setsockopt(sock->fd, IPPROTO_IP, IP_DONTFRAG, &(int){ 1 },
sizeof(int));
#endif
#if defined(IP_MTU_DISCOVER)
(void)setsockopt(sock->fd, IPPROTO_IP, IP_MTU_DISCOVER,
&(int){ IP_PMTUDISC_DO }, sizeof(int));
#endif
}
}
static isc_result_t static isc_result_t
opensocket(isc__socketmgr_t *manager, isc__socket_t *sock, opensocket(isc__socketmgr_t *manager, isc__socket_t *sock,
isc__socket_t *dup_socket) { isc__socket_t *dup_socket) {
@ -2320,52 +2346,9 @@ again:
sock->fd, strbuf); sock->fd, strbuf);
} }
#endif /* IPV6_RECVPKTINFO */ #endif /* IPV6_RECVPKTINFO */
#if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT)
/*
* Turn off Path MTU discovery on IPv6/UDP sockets.
*/
if (sock->pf == AF_INET6) {
int action = IPV6_PMTUDISC_DONT;
(void)setsockopt(sock->fd, IPPROTO_IPV6,
IPV6_MTU_DISCOVER, &action,
sizeof(action));
}
#endif /* if defined(IPV6_MTU_DISCOVER) && defined(IPV6_PMTUDISC_DONT) */
#endif /* defined(USE_CMSG) */ #endif /* defined(USE_CMSG) */
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) set_ip_dontfrag(sock);
/*
* Turn off Path MTU discovery on IPv4/UDP sockets.
* Prefer IP_PMTUDISC_OMIT over IP_PMTUDISC_DONT
* if it available.
*/
if (sock->pf == AF_INET) {
int action;
#if defined(IP_PMTUDISC_OMIT)
action = IP_PMTUDISC_OMIT;
if (setsockopt(sock->fd, IPPROTO_IP, IP_MTU_DISCOVER,
&action, sizeof(action)) < 0)
{
#endif /* if defined(IP_PMTUDISC_OMIT) */
action = IP_PMTUDISC_DONT;
(void)setsockopt(sock->fd, IPPROTO_IP,
IP_MTU_DISCOVER, &action,
sizeof(action));
#if defined(IP_PMTUDISC_OMIT)
}
#endif /* if defined(IP_PMTUDISC_OMIT) */
}
#endif /* if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) */
#if defined(IP_DONTFRAG)
/*
* Turn off Path MTU discovery on IPv4/UDP sockets.
*/
if (sock->pf == AF_INET) {
int off = 0;
(void)setsockopt(sock->fd, IPPROTO_IP, IP_DONTFRAG,
&off, sizeof(off));
}
#endif /* if defined(IP_DONTFRAG) */
#if defined(SET_RCVBUF) #if defined(SET_RCVBUF)
optlen = sizeof(size); optlen = sizeof(size);

View File

@ -87,7 +87,7 @@ ns_server_create(isc_mem_t *mctx, ns_matchview_t matchingview,
CHECKFATAL(isc_stats_create(mctx, &sctx->tcpoutstats6, CHECKFATAL(isc_stats_create(mctx, &sctx->tcpoutstats6,
dns_sizecounter_out_max)); dns_sizecounter_out_max));
sctx->udpsize = 4096; sctx->udpsize = 1232;
sctx->transfer_tcp_message_size = 20480; sctx->transfer_tcp_message_size = 20480;
sctx->fuzztype = isc_fuzz_none; sctx->fuzztype = isc_fuzz_none;