mirror of
https://github.com/systemd/systemd.git
synced 2024-10-31 16:21:26 +03:00
resolved: take fragment size into consideration when determining EDNS0 udp packet size
This commit is contained in:
parent
acbf761b5d
commit
980821f3f0
@ -617,11 +617,48 @@ int dns_server_adjust_opt(DnsServer *server, DnsPacket *packet, DnsServerFeature
|
|||||||
|
|
||||||
edns_do = level >= DNS_SERVER_FEATURE_LEVEL_DO;
|
edns_do = level >= DNS_SERVER_FEATURE_LEVEL_DO;
|
||||||
|
|
||||||
if (level == DNS_SERVER_FEATURE_LEVEL_LARGE)
|
if (level == DNS_SERVER_FEATURE_LEVEL_LARGE) {
|
||||||
packet_size = DNS_PACKET_UNICAST_SIZE_LARGE_MAX;
|
size_t udp_size;
|
||||||
else
|
|
||||||
|
/* In large mode, advertise the local MTU, in order to avoid fragmentation (for security
|
||||||
|
* reasons) – except if we are talking to localhost (where the security considerations don't
|
||||||
|
* matter). If we see fragmentation, lower the reported size to the largest fragment, to
|
||||||
|
* avoid it. */
|
||||||
|
|
||||||
|
udp_size = udp_header_size(server->family);
|
||||||
|
|
||||||
|
if (in_addr_is_localhost(server->family, &server->address) > 0)
|
||||||
|
packet_size = 65536 - udp_size; /* force linux loopback MTU if localhost address */
|
||||||
|
else {
|
||||||
|
/* Use the MTU pointing to the server, subtract the IP/UDP header size */
|
||||||
|
packet_size = LESS_BY(dns_server_get_mtu(server), udp_size);
|
||||||
|
|
||||||
|
/* On the Internet we want to avoid fragmentation for security reasons. If we saw
|
||||||
|
* fragmented packets, the above was too large, let's clamp it to the largest
|
||||||
|
* fragment we saw */
|
||||||
|
if (server->packet_fragmented)
|
||||||
|
packet_size = MIN(server->received_udp_fragment_max, packet_size);
|
||||||
|
|
||||||
|
/* Let's not pick ridiculously large sizes, i.e. not more than 4K. Noone appears to
|
||||||
|
* ever use such large sized on the Internet IRL, hence let's not either. */
|
||||||
|
packet_size = MIN(packet_size, 4096U);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Strictly speaking we quite possibly can receive larger datagrams than the MTU (since the
|
||||||
|
* MTU is for egress, not for ingress), but more often than not the value is symmetric, and
|
||||||
|
* we want something that does the right thing in the majority of cases, and not just in the
|
||||||
|
* theoretical edge case. */
|
||||||
|
} else
|
||||||
|
/* In non-large mode, let's advertise the size of the largest fragment we ever managed to accept. */
|
||||||
packet_size = server->received_udp_fragment_max;
|
packet_size = server->received_udp_fragment_max;
|
||||||
|
|
||||||
|
/* Safety clamp, never advertise less than 512 or more than 65535 */
|
||||||
|
packet_size = CLAMP(packet_size,
|
||||||
|
DNS_PACKET_UNICAST_SIZE_MAX,
|
||||||
|
DNS_PACKET_SIZE_MAX);
|
||||||
|
|
||||||
|
log_debug("Announcing packet size %zu in egress EDNS(0) packet.", packet_size);
|
||||||
|
|
||||||
return dns_packet_append_opt(packet, packet_size, edns_do, /* include_rfc6975 = */ true, NULL, 0, NULL);
|
return dns_packet_append_opt(packet, packet_size, edns_do, /* include_rfc6975 = */ true, NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,6 +750,15 @@ void dns_server_warn_downgrade(DnsServer *server) {
|
|||||||
server->warned_downgrade = true;
|
server->warned_downgrade = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t dns_server_get_mtu(DnsServer *s) {
|
||||||
|
assert(s);
|
||||||
|
|
||||||
|
if (s->link && s->link->mtu != 0)
|
||||||
|
return s->link->mtu;
|
||||||
|
|
||||||
|
return manager_find_mtu(s->manager);
|
||||||
|
}
|
||||||
|
|
||||||
static void dns_server_hash_func(const DnsServer *s, struct siphash *state) {
|
static void dns_server_hash_func(const DnsServer *s, struct siphash *state) {
|
||||||
assert(s);
|
assert(s);
|
||||||
|
|
||||||
|
@ -157,6 +157,8 @@ void manager_next_dns_server(Manager *m, DnsServer *if_current);
|
|||||||
DnssecMode dns_server_get_dnssec_mode(DnsServer *s);
|
DnssecMode dns_server_get_dnssec_mode(DnsServer *s);
|
||||||
DnsOverTlsMode dns_server_get_dns_over_tls_mode(DnsServer *s);
|
DnsOverTlsMode dns_server_get_dns_over_tls_mode(DnsServer *s);
|
||||||
|
|
||||||
|
size_t dns_server_get_mtu(DnsServer *s);
|
||||||
|
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref);
|
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsServer*, dns_server_unref);
|
||||||
|
|
||||||
extern const struct hash_ops dns_server_hash_ops;
|
extern const struct hash_ops dns_server_hash_ops;
|
||||||
|
Loading…
Reference in New Issue
Block a user