]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
resolved: add logic for patching OPT max udp size of existing packet
authorLennart Poettering <lennart@poettering.net>
Wed, 28 Oct 2020 14:03:55 +0000 (15:03 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 9 Feb 2021 16:52:24 +0000 (17:52 +0100)
src/resolve/resolved-dns-packet.c
src/resolve/resolved-dns-packet.h

index 394b843544c2b9f4d1ad84525f315059bca7fd6a..0d2cf8c520778f8aff0a8300f50bc0d02ac40805 100644 (file)
@@ -2235,8 +2235,9 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
         for (i = 0; i < n; i++) {
                 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
                 bool cache_flush = false;
+                size_t start;
 
-                r = dns_packet_read_rr(p, &rr, &cache_flush, NULL);
+                r = dns_packet_read_rr(p, &rr, &cache_flush, &start);
                 if (r < 0)
                         return r;
 
@@ -2304,6 +2305,9 @@ static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
                         }
 
                         p->opt = dns_resource_record_ref(rr);
+                        p->opt_start = start;
+                        assert(p->rindex >= start);
+                        p->opt_size = p->rindex - start;
                 } else {
                         /* According to RFC 4795, section 2.9. only the RRs from the Answer section
                          * shall be cached. Hence mark only those RRs as cacheable by default, but
@@ -2388,6 +2392,20 @@ int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
         return dns_resource_key_equal(p->question->keys[0], key);
 }
 
+int dns_packet_patch_max_udp_size(DnsPacket *p, uint16_t max_udp_size) {
+        assert(p);
+        assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
+
+        if (p->opt_start == (size_t) -1) /* No OPT section, nothing to patch */
+                return 0;
+
+        assert(p->opt_size != (size_t) -1);
+        assert(p->opt_size >= 5);
+
+        unaligned_write_be16(DNS_PACKET_DATA(p) + p->opt_start + 3, max_udp_size);
+        return 1;
+}
+
 static void dns_packet_hash_func(const DnsPacket *s, struct siphash *state) {
         assert(s);
 
index c33ca8c999b6fd230fafc526cbfa5f089e6cfb97..4822aabf9fb4a70c3670db2e5879ec75e73e34e1 100644 (file)
@@ -205,6 +205,8 @@ int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, bo
 int dns_packet_append_question(DnsPacket *p, DnsQuestion *q);
 int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a);
 
+int dns_packet_patch_max_udp_size(DnsPacket *p, uint16_t max_udp_size);
+
 void dns_packet_truncate(DnsPacket *p, size_t sz);
 int dns_packet_truncate_opt(DnsPacket *p);