diff options
-rw-r--r-- | src/resolve/resolved-dns-packet.h | 3 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.c | 8 | ||||
-rw-r--r-- | src/resolve/resolved-dns-server.c | 20 | ||||
-rw-r--r-- | src/resolve/resolved-dns-server.h | 4 | ||||
-rw-r--r-- | src/resolve/resolved-dns-transaction.c | 2 |
5 files changed, 32 insertions, 5 deletions
diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index feded09db3..25dfb2642f 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -65,6 +65,9 @@ struct DnsPacketHeader { /* RFC 1035 say 512 is the maximum, for classic unicast DNS */ #define DNS_PACKET_UNICAST_SIZE_MAX 512 +/* With EDNS0 we can use larger packets, default to 4096, which is what is commonly used */ +#define DNS_PACKET_UNICAST_SIZE_LARGE_MAX 4096 + #define DNS_PACKET_SIZE_START 512 struct DnsPacket { diff --git a/src/resolve/resolved-dns-scope.c b/src/resolve/resolved-dns-scope.c index 80070da2b9..09e6872d26 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -186,10 +186,16 @@ int dns_scope_emit(DnsScope *s, int fd, DnsServer *server, DnsPacket *p) { if (server->possible_features >= DNS_SERVER_FEATURE_LEVEL_EDNS0) { bool edns_do; + size_t packet_size; edns_do = server->possible_features >= DNS_SERVER_FEATURE_LEVEL_DO; - r = dns_packet_append_opt_rr(p, DNS_PACKET_UNICAST_SIZE_MAX, edns_do, &saved_size); + if (server->possible_features >= DNS_SERVER_FEATURE_LEVEL_LARGE) + packet_size = DNS_PACKET_UNICAST_SIZE_LARGE_MAX; + else + packet_size = server->received_udp_packet_max; + + r = dns_packet_append_opt_rr(p, packet_size, edns_do, &saved_size); if (r < 0) return r; diff --git a/src/resolve/resolved-dns-server.c b/src/resolve/resolved-dns-server.c index 916f5dadb8..d565f99c09 100644 --- a/src/resolve/resolved-dns-server.c +++ b/src/resolve/resolved-dns-server.c @@ -71,6 +71,7 @@ int dns_server_new( s->verified_features = _DNS_SERVER_FEATURE_LEVEL_INVALID; s->possible_features = DNS_SERVER_FEATURE_LEVEL_BEST; s->features_grace_period_usec = DNS_SERVER_FEATURE_GRACE_PERIOD_MIN_USEC; + s->received_udp_packet_max = DNS_PACKET_UNICAST_SIZE_MAX; s->type = type; s->family = family; s->address = *in_addr; @@ -223,10 +224,18 @@ void dns_server_move_back_and_unmark(DnsServer *s) { } } -void dns_server_packet_received(DnsServer *s, DnsServerFeatureLevel features, usec_t rtt) { +void dns_server_packet_received(DnsServer *s, DnsServerFeatureLevel features, usec_t rtt, size_t size) { assert(s); - if (s->verified_features < features) { + if (features == DNS_SERVER_FEATURE_LEVEL_LARGE) { + /* even if we successfully receive a reply to a request announcing + support for large packets, that does not mean we can necessarily + receive large packets. */ + if (s->verified_features < DNS_SERVER_FEATURE_LEVEL_LARGE - 1) { + s->verified_features = DNS_SERVER_FEATURE_LEVEL_LARGE - 1; + assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &s->verified_usec) >= 0); + } + } else if (s->verified_features < features) { s->verified_features = features; assert_se(sd_event_now(s->manager->event, clock_boottime_or_monotonic(), &s->verified_usec) >= 0); } @@ -234,6 +243,12 @@ void dns_server_packet_received(DnsServer *s, DnsServerFeatureLevel features, us if (s->possible_features == features) s->n_failed_attempts = 0; + /* Remember the size of the largest UDP packet we received from a server, + we know that we can always announce support for packets with at least + this size. */ + if (s->received_udp_packet_max < size) + s->received_udp_packet_max = size; + if (s->max_rtt < rtt) { s->max_rtt = rtt; s->resend_timeout = MIN(MAX(DNS_TIMEOUT_MIN_USEC, s->max_rtt * 2), DNS_TIMEOUT_MAX_USEC); @@ -480,5 +495,6 @@ static const char* const dns_server_feature_level_table[_DNS_SERVER_FEATURE_LEVE [DNS_SERVER_FEATURE_LEVEL_UDP] = "UDP", [DNS_SERVER_FEATURE_LEVEL_EDNS0] = "UDP+EDNS0", [DNS_SERVER_FEATURE_LEVEL_DO] = "UDP+EDNS0+DO", + [DNS_SERVER_FEATURE_LEVEL_LARGE] = "UDP+EDNS0+DO+LARGE", }; DEFINE_STRING_TABLE_LOOKUP(dns_server_feature_level, DnsServerFeatureLevel); diff --git a/src/resolve/resolved-dns-server.h b/src/resolve/resolved-dns-server.h index 9dd4961d5f..00366a48c9 100644 --- a/src/resolve/resolved-dns-server.h +++ b/src/resolve/resolved-dns-server.h @@ -36,6 +36,7 @@ typedef enum DnsServerFeatureLevel { DNS_SERVER_FEATURE_LEVEL_UDP, DNS_SERVER_FEATURE_LEVEL_EDNS0, DNS_SERVER_FEATURE_LEVEL_DO, + DNS_SERVER_FEATURE_LEVEL_LARGE, _DNS_SERVER_FEATURE_LEVEL_MAX, _DNS_SERVER_FEATURE_LEVEL_INVALID = -1 } DnsServerFeatureLevel; @@ -66,6 +67,7 @@ struct DnsServer { bool marked:1; DnsServerFeatureLevel verified_features; DnsServerFeatureLevel possible_features; + size_t received_udp_packet_max; unsigned n_failed_attempts; usec_t verified_usec; usec_t features_grace_period_usec; @@ -89,7 +91,7 @@ DnsServer* dns_server_unref(DnsServer *s); void dns_server_unlink(DnsServer *s); void dns_server_move_back_and_unmark(DnsServer *s); -void dns_server_packet_received(DnsServer *s, DnsServerFeatureLevel features, usec_t rtt); +void dns_server_packet_received(DnsServer *s, DnsServerFeatureLevel features, usec_t rtt, size_t size); void dns_server_packet_lost(DnsServer *s, DnsServerFeatureLevel features, usec_t usec); void dns_server_packet_failed(DnsServer *s, DnsServerFeatureLevel features); diff --git a/src/resolve/resolved-dns-transaction.c b/src/resolve/resolved-dns-transaction.c index f81461a4fe..90133cb332 100644 --- a/src/resolve/resolved-dns-transaction.c +++ b/src/resolve/resolved-dns-transaction.c @@ -433,7 +433,7 @@ void dns_transaction_process_reply(DnsTransaction *t, DnsPacket *p) { return; } else - dns_server_packet_received(t->server, t->current_features, ts - t->start_usec); + dns_server_packet_received(t->server, t->current_features, ts - t->start_usec, p->size); break; case DNS_PROTOCOL_LLMNR: |