resolved: add more linked packets for overlong known answers
authorDaniel Mack <daniel@zonque.org>
Wed, 9 Dec 2015 12:09:35 +0000 (13:09 +0100)
committerDaniel Mack <daniel@zonque.org>
Thu, 10 Dec 2015 09:21:50 +0000 (10:21 +0100)
For mDNS, if we're unable to stuff all known answers into the given packet,
allocate a new one, push the RR into that one and link it to the current
one.

src/resolve/resolved-dns-cache.c
src/resolve/resolved-dns-scope.c

index 6124ff6..1774ae6 100644 (file)
@@ -738,6 +738,7 @@ int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) {
         int r;
 
         assert(cache);
+        assert(p);
 
         HASHMAP_FOREACH(i, cache->by_key, iterator) {
                 DnsCacheItem *j;
@@ -752,6 +753,23 @@ int dns_cache_export_shared_to_packet(DnsCache *cache, DnsPacket *p) {
                                 continue;
 
                         r = dns_packet_append_rr(p, j->rr, NULL, NULL);
+                        if (r == -EMSGSIZE && p->protocol == DNS_PROTOCOL_MDNS) {
+                                /* For mDNS, if we're unable to stuff all known answers into the given packet,
+                                 * allocate a new one, push the RR into that one and link it to the current one.
+                                 */
+
+                                DNS_PACKET_HEADER(p)->ancount = htobe16(ancount);
+                                ancount = 0;
+
+                                r = dns_packet_new_query(&p->more, p->protocol, 0, true);
+                                if (r < 0)
+                                        return r;
+
+                                /* continue with new packet */
+                                p = p->more;
+                                r = dns_packet_append_rr(p, j->rr, NULL, NULL);
+                        }
+
                         if (r < 0)
                                 return r;
 
index 11c3294..4d83ac5 100644 (file)
@@ -290,7 +290,7 @@ int dns_scope_emit(DnsScope *s, int fd, DnsServer *server, DnsPacket *p) {
                 /* If there are multiple linked packets, set the TC bit in all but the last of them */
                 if (p->more) {
                         assert(p->protocol == DNS_PROTOCOL_MDNS);
-                        dns_packet_set_truncated_flag(p, true);
+                        dns_packet_set_flags(p, true, true);
                 }
 
                 r = dns_scope_emit_one(s, fd, server, p);