diff options
author | Lennart Poettering <lennart@poettering.net> | 2014-07-17 01:13:22 +0200 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2014-07-17 01:41:52 +0200 |
commit | e1c959948c0e31d6997bcdfbabfbd077784b2bae (patch) | |
tree | 20110fde60bc894123285e77c329c22ec3a0d8b4 | |
parent | 76f468c8ea568fce98fa75d7f1d540256eb0940a (diff) |
resolved: properly handle MTU logic
-rw-r--r-- | src/resolve/resolved-dns-packet.h | 6 | ||||
-rw-r--r-- | src/resolve/resolved-dns-scope.c | 11 | ||||
-rw-r--r-- | src/resolve/resolved-link.c | 4 | ||||
-rw-r--r-- | src/resolve/resolved-link.h | 2 | ||||
-rw-r--r-- | src/resolve/resolved-manager.c | 20 | ||||
-rw-r--r-- | src/resolve/resolved.h | 1 |
6 files changed, 42 insertions, 2 deletions
diff --git a/src/resolve/resolved-dns-packet.h b/src/resolve/resolved-dns-packet.h index 99f60a1556..de3a789a78 100644 --- a/src/resolve/resolved-dns-packet.h +++ b/src/resolve/resolved-dns-packet.h @@ -44,8 +44,12 @@ struct DnsPacketHeader { /* The various DNS protocols deviate in how large a packet can grow, but the TCP transport has a 16bit size field, hence that appears to - be the maximum. */ + be the absolute maximum. */ #define DNS_PACKET_SIZE_MAX 0xFFFF + +/* RFC 1035 say 512 is the maximum, for classic unicast DNS */ +#define DNS_PACKET_UNICAST_SIZE_MAX 512 + #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 0a70cb1f0f..a39e705a3b 100644 --- a/src/resolve/resolved-dns-scope.c +++ b/src/resolve/resolved-dns-scope.c @@ -102,8 +102,19 @@ int dns_scope_send(DnsScope *s, DnsPacket *p) { return -EMSGSIZE; ifindex = s->link->ifindex; + } else { + uint32_t mtu; + + mtu = manager_find_mtu(s->manager); + if (mtu > 0) { + if (p->size > mtu) + return -EMSGSIZE; + } } + if (p->size > DNS_PACKET_UNICAST_SIZE_MAX) + return -EMSGSIZE; + if (srv->family == AF_INET) r = manager_dns_ipv4_send(s->manager, srv, ifindex, p); else if (srv->family == AF_INET6) diff --git a/src/resolve/resolved-link.c b/src/resolve/resolved-link.c index 9c886a26b5..61b112cb05 100644 --- a/src/resolve/resolved-link.c +++ b/src/resolve/resolved-link.c @@ -91,6 +91,10 @@ int link_update_rtnl(Link *l, sd_rtnl_message *m) { if (r < 0) return r; + r = sd_rtnl_message_read_u32(m, IFLA_MTU, &l->mtu); + if (r < 0) + return r; + return 0; } diff --git a/src/resolve/resolved-link.h b/src/resolve/resolved-link.h index 07f68ab41c..c0ea2362ab 100644 --- a/src/resolve/resolved-link.h +++ b/src/resolve/resolved-link.h @@ -58,7 +58,7 @@ struct Link { DnsScope *mdns_ipv4_scope; DnsScope *mdns_ipv6_scope; - size_t mtu; + uint32_t mtu; char *operational_state; diff --git a/src/resolve/resolved-manager.c b/src/resolve/resolved-manager.c index 5fbb500fd0..fed9a77973 100644 --- a/src/resolve/resolved-manager.c +++ b/src/resolve/resolved-manager.c @@ -878,3 +878,23 @@ void manager_next_dns_server(Manager *m) { m->current_dns_server = m->dns_servers; } + +uint32_t manager_find_mtu(Manager *m) { + uint32_t mtu = 0; + Link *l; + Iterator i; + + /* If we don't know on which link a DNS packet would be + * delivered, let's find the largest MTU that works on all + * interfaces we know of */ + + HASHMAP_FOREACH(l, m->links, i) { + if (l->mtu <= 0) + continue; + + if (mtu <= 0 || l->mtu < mtu) + mtu = l->mtu; + } + + return mtu; +} diff --git a/src/resolve/resolved.h b/src/resolve/resolved.h index 438730be6e..c592a7e833 100644 --- a/src/resolve/resolved.h +++ b/src/resolve/resolved.h @@ -79,6 +79,7 @@ int manager_write_resolv_conf(Manager *m); DnsServer* manager_find_dns_server(Manager *m, unsigned char family, union in_addr_union *in_addr); DnsServer *manager_get_dns_server(Manager *m); void manager_next_dns_server(Manager *m); +uint32_t manager_find_mtu(Manager *m); int manager_dns_ipv4_fd(Manager *m); int manager_dns_ipv4_send(Manager *m, DnsServer *srv, int ifindex, DnsPacket *p); |