resolved: properly handle MTU logic

This commit is contained in:
Lennart Poettering 2014-07-17 01:13:22 +02:00
parent 76f468c8ea
commit e1c959948c
6 changed files with 42 additions and 2 deletions

View File

@ -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 {

View File

@ -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)

View File

@ -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;
}

View File

@ -58,7 +58,7 @@ struct Link {
DnsScope *mdns_ipv4_scope;
DnsScope *mdns_ipv6_scope;
size_t mtu;
uint32_t mtu;
char *operational_state;

View File

@ -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;
}

View File

@ -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);