chiark / gitweb /
resolved: properly handle MTU logic
authorLennart Poettering <lennart@poettering.net>
Wed, 16 Jul 2014 23:13:22 +0000 (01:13 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 16 Jul 2014 23:41:52 +0000 (01:41 +0200)
src/resolve/resolved-dns-packet.h
src/resolve/resolved-dns-scope.c
src/resolve/resolved-link.c
src/resolve/resolved-link.h
src/resolve/resolved-manager.c
src/resolve/resolved.h

index 99f60a15569526c2c9024279170c2e516e2b1647..de3a789a783eb8abd483232f7b00e0d209afaebf 100644 (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
 
 /* 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
 #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 {
 #define DNS_PACKET_SIZE_START 512
 
 struct DnsPacket {
index 0a70cb1f0f6486ff9e79fcc91069d305b09cb0e0..a39e705a3ba60c39df5d30bf13d3beab231fc6f5 100644 (file)
@@ -102,8 +102,19 @@ int dns_scope_send(DnsScope *s, DnsPacket *p) {
                         return -EMSGSIZE;
 
                 ifindex = s->link->ifindex;
                         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)
         if (srv->family == AF_INET)
                 r = manager_dns_ipv4_send(s->manager, srv, ifindex, p);
         else if (srv->family == AF_INET6)
index 9c886a26b5a4ee480813bb2d19105bcbab2e8b85..61b112cb05091213553cf95919c1f1211e341701 100644 (file)
@@ -91,6 +91,10 @@ int link_update_rtnl(Link *l, sd_rtnl_message *m) {
         if (r < 0)
                 return r;
 
         if (r < 0)
                 return r;
 
+        r = sd_rtnl_message_read_u32(m, IFLA_MTU, &l->mtu);
+        if (r < 0)
+                return r;
+
         return 0;
 }
 
         return 0;
 }
 
index 07f68ab41ca0c86d3aca0deb7c84d227216b5509..c0ea2362abb39ef01325867b4510375aceee6849 100644 (file)
@@ -58,7 +58,7 @@ struct Link {
         DnsScope *mdns_ipv4_scope;
         DnsScope *mdns_ipv6_scope;
 
         DnsScope *mdns_ipv4_scope;
         DnsScope *mdns_ipv6_scope;
 
-        size_t mtu;
+        uint32_t mtu;
 
         char *operational_state;
 
 
         char *operational_state;
 
index 5fbb500fd0530dd57c2ab73a79c9d15b02a0cf0e..fed9a7797359020bb2c30d62289a7a494f257637 100644 (file)
@@ -878,3 +878,23 @@ void manager_next_dns_server(Manager *m) {
 
         m->current_dns_server = m->dns_servers;
 }
 
         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;
+}
index 438730be6e3c7df6c4e86e715af1baf1b60c824a..c592a7e8335cba2edbccaf9cf1d8a8000bb05b8c 100644 (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);
 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);
 
 int manager_dns_ipv4_fd(Manager *m);
 int manager_dns_ipv4_send(Manager *m, DnsServer *srv, int ifindex, DnsPacket *p);