]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/resolve/resolved-dns-packet.c
resolved: rework OPT RR generation logic
[thirdparty/systemd.git] / src / resolve / resolved-dns-packet.c
index c425b890346e1dde9e3d15f92766475675e2b42f..5f7970129610e3c4708fb227d4111ed0bf2f0d5b 100644 (file)
@@ -58,6 +58,7 @@ int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
         p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
         p->allocated = a;
         p->protocol = protocol;
+        p->opt_start = p->opt_size = (size_t) -1;
         p->n_ref = 1;
 
         *ret = p;
@@ -681,7 +682,7 @@ fail:
 }
 
 /* Append the OPT pseudo-RR described in RFC6891 */
-int dns_packet_append_opt_rr(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start) {
+int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start) {
         size_t saved_size;
         int r;
 
@@ -689,6 +690,11 @@ int dns_packet_append_opt_rr(DnsPacket *p, uint16_t max_udp_size, bool edns0_do,
         /* we must never advertise supported packet size smaller than the legacy max */
         assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
 
+        if (p->opt_start != (size_t) -1)
+                return -EBUSY;
+
+        assert(p->opt_size == (size_t) -1);
+
         saved_size = p->size;
 
         /* empty name */
@@ -721,6 +727,11 @@ int dns_packet_append_opt_rr(DnsPacket *p, uint16_t max_udp_size, bool edns0_do,
         if (r < 0)
                 goto fail;
 
+        DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) + 1);
+
+        p->opt_start = saved_size;
+        p->opt_size = p->size - saved_size;
+
         if (start)
                 *start = saved_size;
 
@@ -731,6 +742,27 @@ fail:
         return r;
 }
 
+int dns_packet_truncate_opt(DnsPacket *p) {
+        assert(p);
+
+        if (p->opt_start == (size_t) -1) {
+                assert(p->opt_size == (size_t) -1);
+                return 0;
+        }
+
+        assert(p->opt_size != (size_t) -1);
+        assert(DNS_PACKET_ARCOUNT(p) > 0);
+
+        if (p->opt_start + p->opt_size != p->size)
+                return -EBUSY;
+
+        dns_packet_truncate(p, p->opt_start);
+        DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) - 1);
+        p->opt_start = p->opt_size = (size_t) -1;
+
+        return 1;
+}
+
 int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start) {
         size_t saved_size, rdlength_offset, end, rdlength, rds;
         int r;
@@ -1046,7 +1078,6 @@ fail:
         return r;
 }
 
-
 int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
         assert(p);