]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
udev: gracefully handle ENODEV or friends in opening device node
[thirdparty/systemd.git] / src / resolve / resolved-dns-packet.c
CommitLineData
db9ecf05 1/* SPDX-License-Identifier: LGPL-2.1-or-later */
74b2466e 2
b5efdb8a 3#include "alloc-util.h"
284d7641 4#include "bitmap.h"
4ad7f276 5#include "dns-domain.h"
ac684446 6#include "escape.h"
93a1f792 7#include "log.h"
0a970718 8#include "memory-util.h"
68527d30 9#include "resolved-dns-answer.h"
74b2466e 10#include "resolved-dns-packet.h"
68527d30
DDM
11#include "resolved-dns-question.h"
12#include "resolved-dns-rr.h"
2d34cf0c 13#include "set.h"
284d7641 14#include "siphash24.h"
0d609349 15#include "stdio-util.h"
8b43440b 16#include "string-table.h"
284d7641
DDM
17#include "string-util.h"
18#include "time-util.h"
8b43440b
LP
19#include "unaligned.h"
20#include "utf8.h"
74b2466e 21
7586f4d1
TG
22#define EDNS0_OPT_DO (1<<15)
23
ab1a1ba5 24assert_cc(DNS_PACKET_SIZE_START > DNS_PACKET_HEADER_SIZE);
88795538 25
e18a3c73
ZJS
26typedef struct DnsPacketRewinder {
27 DnsPacket *packet;
28 size_t saved_rindex;
29} DnsPacketRewinder;
30
31static void rewind_dns_packet(DnsPacketRewinder *rewinder) {
32 if (rewinder->packet)
33 dns_packet_rewind(rewinder->packet, rewinder->saved_rindex);
34}
35
0c4f37f0
ZJS
36#define REWINDER_INIT(p) { \
37 .packet = (p), \
38 .saved_rindex = (p)->rindex, \
39 }
40#define CANCEL_REWINDER(rewinder) do { (rewinder).packet = NULL; } while (0)
e18a3c73 41
834dc383
DDM
42uint16_t dns_packet_rcode(DnsPacket *p) {
43 uint16_t rcode;
44
45 assert(p);
46
47 if (p->opt)
48 rcode = (uint16_t) ((p->opt->ttl >> 20) & 0xFF0);
49 else
50 rcode = 0;
51
52 return rcode | (be16toh(DNS_PACKET_HEADER(p)->flags) & 0xF);
53};
54
55uint16_t dns_packet_payload_size_max(DnsPacket *p) {
56 assert(p);
57
58 /* Returns the advertised maximum size for replies, or the DNS default if there's nothing defined. */
59
60 if (p->ipproto == IPPROTO_TCP) /* we ignore EDNS(0) size data on TCP, like everybody else */
61 return DNS_PACKET_SIZE_MAX;
62
63 if (p->opt)
64 return MAX(DNS_PACKET_UNICAST_SIZE_MAX, p->opt->key->class);
65
66 return DNS_PACKET_UNICAST_SIZE_MAX;
67}
68
69bool dns_packet_do(DnsPacket *p) {
70 assert(p);
71
72 if (!p->opt)
73 return false;
74
75 return !!(p->opt->ttl & (1U << 15));
76}
77
78bool dns_packet_version_supported(DnsPacket *p) {
79 assert(p);
80
81 /* Returns true if this packet is in a version we support. Which means either non-EDNS or EDNS(0), but not EDNS
82 * of any newer versions */
83
84 if (!p->opt)
85 return true;
86
87 return DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(p->opt);
88}
89
51027656
LP
90int dns_packet_new(
91 DnsPacket **ret,
92 DnsProtocol protocol,
93 size_t min_alloc_dsize,
94 size_t max_size) {
95
74b2466e
LP
96 DnsPacket *p;
97 size_t a;
98
99 assert(ret);
51027656
LP
100 assert(max_size >= DNS_PACKET_HEADER_SIZE);
101
102 if (max_size > DNS_PACKET_SIZE_MAX)
103 max_size = DNS_PACKET_SIZE_MAX;
74b2466e 104
46a58596
BR
105 /* The caller may not check what is going to be truly allocated, so do not allow to
106 * allocate a DNS packet bigger than DNS_PACKET_SIZE_MAX.
107 */
baaa35ad
ZJS
108 if (min_alloc_dsize > DNS_PACKET_SIZE_MAX)
109 return log_error_errno(SYNTHETIC_ERRNO(EFBIG),
110 "Requested packet data size too big: %zu",
111 min_alloc_dsize);
46a58596
BR
112
113 /* When dns_packet_new() is called with min_alloc_dsize == 0, allocate more than the
88795538
ZJS
114 * absolute minimum (which is the dns packet header size), to avoid
115 * resizing immediately again after appending the first data to the packet.
116 */
46a58596 117 if (min_alloc_dsize < DNS_PACKET_HEADER_SIZE)
88795538
ZJS
118 a = DNS_PACKET_SIZE_START;
119 else
46a58596 120 a = min_alloc_dsize;
74b2466e 121
c73ce96b
LP
122 /* round up to next page size */
123 a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
124
125 /* make sure we never allocate more than useful */
51027656
LP
126 if (a > max_size)
127 a = max_size;
c73ce96b 128
74b2466e
LP
129 p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
130 if (!p)
131 return -ENOMEM;
132
1ed31408
LP
133 *p = (DnsPacket) {
134 .n_ref = 1,
135 .protocol = protocol,
136 .size = DNS_PACKET_HEADER_SIZE,
137 .rindex = DNS_PACKET_HEADER_SIZE,
138 .allocated = a,
139 .max_size = max_size,
f5fbe71d
YW
140 .opt_start = SIZE_MAX,
141 .opt_size = SIZE_MAX,
1ed31408 142 };
74b2466e
LP
143
144 *ret = p;
145
146 return 0;
147}
148
dbfbb6e7 149void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated) {
74b2466e 150
dbfbb6e7 151 DnsPacketHeader *h;
74b2466e 152
dbfbb6e7 153 assert(p);
74b2466e
LP
154
155 h = DNS_PACKET_HEADER(p);
1716f6dc 156
79893116 157 switch (p->protocol) {
dbfbb6e7
DM
158 case DNS_PROTOCOL_LLMNR:
159 assert(!truncated);
160
069360a6
LP
161 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
162 0 /* opcode */,
163 0 /* c */,
e5abebab 164 0 /* tc */,
069360a6
LP
165 0 /* t */,
166 0 /* ra */,
167 0 /* ad */,
168 0 /* cd */,
169 0 /* rcode */));
dbfbb6e7
DM
170 break;
171
172 case DNS_PROTOCOL_MDNS:
173 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
174 0 /* opcode */,
175 0 /* aa */,
176 truncated /* tc */,
177 0 /* rd (ask for recursion) */,
178 0 /* ra */,
179 0 /* ad */,
180 0 /* cd */,
181 0 /* rcode */));
182 break;
183
184 default:
185 assert(!truncated);
186
069360a6
LP
187 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
188 0 /* opcode */,
189 0 /* aa */,
190 0 /* tc */,
191 1 /* rd (ask for recursion) */,
192 0 /* ra */,
193 0 /* ad */,
24710c48 194 dnssec_checking_disabled /* cd */,
069360a6 195 0 /* rcode */));
dbfbb6e7
DM
196 }
197}
198
46a58596 199int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t min_alloc_dsize, bool dnssec_checking_disabled) {
dbfbb6e7
DM
200 DnsPacket *p;
201 int r;
202
203 assert(ret);
204
51027656 205 r = dns_packet_new(&p, protocol, min_alloc_dsize, DNS_PACKET_SIZE_MAX);
dbfbb6e7
DM
206 if (r < 0)
207 return r;
208
209 /* Always set the TC bit to 0 initially.
210 * If there are multiple packets later, we'll update the bit shortly before sending.
211 */
212 dns_packet_set_flags(p, dnssec_checking_disabled, false);
74b2466e
LP
213
214 *ret = p;
215 return 0;
216}
217
1a6cd020
LP
218int dns_packet_dup(DnsPacket **ret, DnsPacket *p) {
219 DnsPacket *c;
220 int r;
221
222 assert(ret);
223 assert(p);
224
225 r = dns_packet_validate(p);
226 if (r < 0)
227 return r;
228
229 c = malloc(ALIGN(sizeof(DnsPacket)) + p->size);
230 if (!c)
231 return -ENOMEM;
232
233 *c = (DnsPacket) {
234 .n_ref = 1,
235 .protocol = p->protocol,
236 .size = p->size,
237 .rindex = DNS_PACKET_HEADER_SIZE,
238 .allocated = p->size,
239 .max_size = p->max_size,
f5fbe71d
YW
240 .opt_start = SIZE_MAX,
241 .opt_size = SIZE_MAX,
1a6cd020
LP
242 };
243
244 memcpy(DNS_PACKET_DATA(c), DNS_PACKET_DATA(p), p->size);
245
246 *ret = c;
247 return 0;
248}
249
74b2466e
LP
250DnsPacket *dns_packet_ref(DnsPacket *p) {
251
252 if (!p)
253 return NULL;
254
a8812dd7
LP
255 assert(!p->on_stack);
256
74b2466e
LP
257 assert(p->n_ref > 0);
258 p->n_ref++;
259 return p;
260}
261
262static void dns_packet_free(DnsPacket *p) {
263 char *s;
264
265 assert(p);
266
faa133f3
LP
267 dns_question_unref(p->question);
268 dns_answer_unref(p->answer);
d75acfb0 269 dns_resource_record_unref(p->opt);
322345fd 270
74b2466e
LP
271 while ((s = hashmap_steal_first_key(p->names)))
272 free(s);
273 hashmap_free(p->names);
274
faa133f3 275 free(p->_data);
a8812dd7
LP
276
277 if (!p->on_stack)
278 free(p);
74b2466e
LP
279}
280
281DnsPacket *dns_packet_unref(DnsPacket *p) {
282 if (!p)
283 return NULL;
284
285 assert(p->n_ref > 0);
286
6728a58d 287 dns_packet_unref(p->more);
9c491563 288
74b2466e
LP
289 if (p->n_ref == 1)
290 dns_packet_free(p);
291 else
292 p->n_ref--;
293
294 return NULL;
295}
296
297int dns_packet_validate(DnsPacket *p) {
298 assert(p);
299
300 if (p->size < DNS_PACKET_HEADER_SIZE)
301 return -EBADMSG;
302
c73ce96b
LP
303 if (p->size > DNS_PACKET_SIZE_MAX)
304 return -EBADMSG;
305
623a4c97 306 return 1;
74b2466e
LP
307}
308
309int dns_packet_validate_reply(DnsPacket *p) {
74b2466e
LP
310 int r;
311
312 assert(p);
313
314 r = dns_packet_validate(p);
315 if (r < 0)
316 return r;
317
623a4c97
LP
318 if (DNS_PACKET_QR(p) != 1)
319 return 0;
320
321 if (DNS_PACKET_OPCODE(p) != 0)
74b2466e
LP
322 return -EBADMSG;
323
818ef443 324 switch (p->protocol) {
d75acfb0 325
818ef443
DM
326 case DNS_PROTOCOL_LLMNR:
327 /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
328 if (DNS_PACKET_QDCOUNT(p) != 1)
329 return -EBADMSG;
330
331 break;
332
4e5bf5e1
DM
333 case DNS_PROTOCOL_MDNS:
334 /* RFC 6762, Section 18 */
834dc383 335 if (dns_packet_rcode(p) != 0)
4e5bf5e1
DM
336 return -EBADMSG;
337
338 break;
339
818ef443 340 default:
5c9feb2d 341 ;
818ef443 342 }
ea917db9 343
623a4c97
LP
344 return 1;
345}
346
347int dns_packet_validate_query(DnsPacket *p) {
348 int r;
349
350 assert(p);
351
352 r = dns_packet_validate(p);
353 if (r < 0)
354 return r;
355
356 if (DNS_PACKET_QR(p) != 0)
357 return 0;
358
3cb10d3a 359 if (DNS_PACKET_OPCODE(p) != 0)
74b2466e
LP
360 return -EBADMSG;
361
818ef443 362 switch (p->protocol) {
d75acfb0 363
b30bf55d 364 case DNS_PROTOCOL_DNS:
ba1749f6
YW
365 if (DNS_PACKET_TC(p))
366 return -EBADMSG;
367
368 if (DNS_PACKET_QDCOUNT(p) != 1)
369 return -EBADMSG;
370
371 if (DNS_PACKET_ANCOUNT(p) > 0)
372 return -EBADMSG;
373
374 /* Note, in most cases, DNS query packet does not have authority section. But some query
375 * types, e.g. IXFR, have Authority sections. Hence, unlike the check for LLMNR, we do not
376 * check DNS_PACKET_NSCOUNT(p) here. */
377 break;
378
379 case DNS_PROTOCOL_LLMNR:
380 if (DNS_PACKET_TC(p))
6f087266
YW
381 return -EBADMSG;
382
818ef443
DM
383 /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
384 if (DNS_PACKET_QDCOUNT(p) != 1)
385 return -EBADMSG;
623a4c97 386
818ef443
DM
387 /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
388 if (DNS_PACKET_ANCOUNT(p) > 0)
389 return -EBADMSG;
623a4c97 390
818ef443
DM
391 /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
392 if (DNS_PACKET_NSCOUNT(p) > 0)
393 return -EBADMSG;
394
395 break;
396
4e5bf5e1 397 case DNS_PROTOCOL_MDNS:
ba1749f6
YW
398 /* Note, mDNS query may have truncation flag. So, unlike the check for DNS and LLMNR,
399 * we do not check DNS_PACKET_TC(p) here. */
400
2aaf3765
SB
401 /* RFC 6762, Section 18 specifies that messages with non-zero RCODE
402 * must be silently ignored, and that we must ignore the values of
403 * AA, RD, RA, AD, and CD bits. */
834dc383 404 if (dns_packet_rcode(p) != 0)
4e5bf5e1
DM
405 return -EBADMSG;
406
407 break;
408
818ef443 409 default:
5c9feb2d 410 ;
818ef443 411 }
623a4c97
LP
412
413 return 1;
74b2466e
LP
414}
415
416static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
417 assert(p);
418
c73ce96b 419 if (p->size + add > p->allocated) {
51027656 420 size_t a, ms;
c73ce96b
LP
421
422 a = PAGE_ALIGN((p->size + add) * 2);
51027656
LP
423
424 ms = dns_packet_size_max(p);
425 if (a > ms)
426 a = ms;
c73ce96b
LP
427
428 if (p->size + add > a)
429 return -EMSGSIZE;
430
faa133f3 431 if (p->_data) {
c73ce96b
LP
432 void *d;
433
faa133f3 434 d = realloc(p->_data, a);
c73ce96b
LP
435 if (!d)
436 return -ENOMEM;
437
faa133f3 438 p->_data = d;
c73ce96b 439 } else {
faa133f3
LP
440 p->_data = malloc(a);
441 if (!p->_data)
c73ce96b
LP
442 return -ENOMEM;
443
faa133f3
LP
444 memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
445 memzero((uint8_t*) p->_data + p->size, a - p->size);
c73ce96b
LP
446 }
447
448 p->allocated = a;
449 }
74b2466e
LP
450
451 if (start)
452 *start = p->size;
453
454 if (ret)
455 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
456
457 p->size += add;
458 return 0;
459}
460
9c5e12a4 461void dns_packet_truncate(DnsPacket *p, size_t sz) {
74b2466e
LP
462 char *s;
463 void *n;
464
465 assert(p);
466
467 if (p->size <= sz)
468 return;
469
90e74a66 470 HASHMAP_FOREACH_KEY(n, s, p->names) {
74b2466e
LP
471
472 if (PTR_TO_SIZE(n) < sz)
473 continue;
474
475 hashmap_remove(p->names, s);
476 free(s);
477 }
478
479 p->size = sz;
480}
481
623a4c97
LP
482int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
483 void *q;
484 int r;
485
486 assert(p);
487
488 r = dns_packet_extend(p, l, &q, start);
489 if (r < 0)
490 return r;
491
1f66559c 492 memcpy_safe(q, d, l);
623a4c97
LP
493 return 0;
494}
495
74b2466e
LP
496int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
497 void *d;
498 int r;
499
500 assert(p);
501
502 r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
503 if (r < 0)
504 return r;
505
506 ((uint8_t*) d)[0] = v;
507
508 return 0;
509}
510
511int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
512 void *d;
513 int r;
514
515 assert(p);
516
517 r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
518 if (r < 0)
519 return r;
520
725ca0e5 521 unaligned_write_be16(d, v);
623a4c97
LP
522
523 return 0;
524}
525
526int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
527 void *d;
528 int r;
529
530 assert(p);
531
532 r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
533 if (r < 0)
534 return r;
535
725ca0e5 536 unaligned_write_be32(d, v);
74b2466e
LP
537
538 return 0;
539}
540
541int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
74b2466e
LP
542 assert(p);
543 assert(s);
544
c38a52da 545 return dns_packet_append_raw_string(p, s, strlen(s), start);
74b2466e
LP
546}
547
2001c805
LP
548int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start) {
549 void *d;
550 int r;
551
552 assert(p);
553 assert(s || size == 0);
554
555 if (size > 255)
556 return -E2BIG;
557
558 r = dns_packet_extend(p, 1 + size, &d, start);
559 if (r < 0)
560 return r;
561
562 ((uint8_t*) d)[0] = (uint8_t) size;
563
75f32f04 564 memcpy_safe(((uint8_t*) d) + 1, s, size);
2001c805
LP
565
566 return 0;
567}
568
a3db237b 569int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, bool canonical_candidate, size_t *start) {
a8812dd7 570 uint8_t *w;
74b2466e
LP
571 int r;
572
a3db237b
LP
573 /* Append a label to a packet. Optionally, does this in DNSSEC
574 * canonical form, if this label is marked as a candidate for
575 * it, and the canonical form logic is enabled for the
576 * packet */
577
74b2466e
LP
578 assert(p);
579 assert(d);
580
581 if (l > DNS_LABEL_MAX)
582 return -E2BIG;
583
a8812dd7 584 r = dns_packet_extend(p, 1 + l, (void**) &w, start);
74b2466e
LP
585 if (r < 0)
586 return r;
587
a8812dd7
LP
588 *(w++) = (uint8_t) l;
589
64ea42e9 590 if (p->canonical_form && canonical_candidate)
a8812dd7
LP
591 /* Generate in canonical form, as defined by DNSSEC
592 * RFC 4034, Section 6.2, i.e. all lower-case. */
64ea42e9 593 for (size_t i = 0; i < l; i++)
b577e3d5 594 w[i] = (uint8_t) ascii_tolower(d[i]);
64ea42e9 595 else
a8812dd7
LP
596 /* Otherwise, just copy the string unaltered. This is
597 * essential for DNS-SD, where the casing of labels
598 * matters and needs to be retained. */
599 memcpy(w, d, l);
74b2466e
LP
600
601 return 0;
602}
603
f6a5fec6
LP
604int dns_packet_append_name(
605 DnsPacket *p,
606 const char *name,
607 bool allow_compression,
a3db237b 608 bool canonical_candidate,
f6a5fec6
LP
609 size_t *start) {
610
360105f1
LP
611 _cleanup_free_ char **added_entries = NULL; /* doesn't own the strings! this is just regular pointer array, not a NULL-terminated strv! */
612 size_t n_added_entries = 0, saved_size;
74b2466e
LP
613 int r;
614
615 assert(p);
616 assert(name);
617
e6378561
LP
618 r = dns_name_is_valid(name);
619 if (r < 0)
620 return r;
621 if (r == 0)
622 return -EINVAL;
623
f6a5fec6
LP
624 if (p->refuse_compression)
625 allow_compression = false;
626
74b2466e
LP
627 saved_size = p->size;
628
e48b9a64 629 while (!dns_name_is_root(name)) {
08f904fd 630 const char *z = name;
fd7e9887 631 char label[DNS_LABEL_MAX+1];
151226ab 632 size_t n = 0;
74b2466e 633
151226ab
ZJS
634 if (allow_compression)
635 n = PTR_TO_SIZE(hashmap_get(p->names, name));
74b2466e
LP
636 if (n > 0) {
637 assert(n < p->size);
638
639 if (n < 0x4000) {
640 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
641 if (r < 0)
642 goto fail;
643
644 goto done;
645 }
646 }
647
7470cc4c 648 r = dns_label_unescape(&name, label, sizeof label, 0);
74b2466e
LP
649 if (r < 0)
650 goto fail;
651
a3db237b 652 r = dns_packet_append_label(p, label, r, canonical_candidate, &n);
74b2466e
LP
653 if (r < 0)
654 goto fail;
655
151226ab 656 if (allow_compression) {
08f904fd
LP
657 _cleanup_free_ char *s = NULL;
658
360105f1
LP
659 if (!GREEDY_REALLOC(added_entries, n_added_entries + 1)) {
660 r = -ENOMEM;
661 goto fail;
662 }
663
08f904fd
LP
664 s = strdup(z);
665 if (!s) {
666 r = -ENOMEM;
667 goto fail;
668 }
669
3004fcd0 670 r = hashmap_ensure_put(&p->names, &dns_name_hash_ops, s, SIZE_TO_PTR(n));
151226ab
ZJS
671 if (r < 0)
672 goto fail;
74b2466e 673
360105f1
LP
674 /* Keep track of the entries we just added (note that the string is owned by the hashtable, not this array!) */
675 added_entries[n_added_entries++] = TAKE_PTR(s);
151226ab 676 }
74b2466e
LP
677 }
678
679 r = dns_packet_append_uint8(p, 0, NULL);
680 if (r < 0)
681 return r;
682
683done:
684 if (start)
685 *start = saved_size;
686
687 return 0;
688
689fail:
360105f1
LP
690 /* Remove all label compression names we added again */
691 FOREACH_ARRAY(s, added_entries, n_added_entries) {
692 hashmap_remove(p->names, *s);
693 free(*s);
694 }
695
74b2466e
LP
696 dns_packet_truncate(p, saved_size);
697 return r;
698}
699
58ab31d5 700int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, const DnsAnswerFlags flags, size_t *start) {
74b2466e 701 size_t saved_size;
58ab31d5 702 uint16_t class;
74b2466e
LP
703 int r;
704
705 assert(p);
706 assert(k);
707
708 saved_size = p->size;
709
1c02e7ba 710 r = dns_packet_append_name(p, dns_resource_key_name(k), true, true, NULL);
74b2466e
LP
711 if (r < 0)
712 goto fail;
713
714 r = dns_packet_append_uint16(p, k->type, NULL);
715 if (r < 0)
716 goto fail;
717
82d39576 718 class = flags & DNS_ANSWER_CACHE_FLUSH ? k->class | MDNS_RR_CACHE_FLUSH_OR_QU : k->class;
58ab31d5 719 r = dns_packet_append_uint16(p, class, NULL);
74b2466e
LP
720 if (r < 0)
721 goto fail;
722
723 if (start)
724 *start = saved_size;
725
726 return 0;
727
728fail:
729 dns_packet_truncate(p, saved_size);
730 return r;
731}
732
e1a9f1a8 733static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, const uint8_t *types, size_t *start) {
50f1e641
TG
734 size_t saved_size;
735 int r;
736
737 assert(p);
738 assert(types);
1792f223 739 assert(length > 0);
50f1e641 740
50f1e641
TG
741 saved_size = p->size;
742
1792f223
TG
743 r = dns_packet_append_uint8(p, window, NULL);
744 if (r < 0)
745 goto fail;
50f1e641 746
1792f223
TG
747 r = dns_packet_append_uint8(p, length, NULL);
748 if (r < 0)
749 goto fail;
6fa91901 750
1792f223
TG
751 r = dns_packet_append_blob(p, types, length, NULL);
752 if (r < 0)
753 goto fail;
50f1e641
TG
754
755 if (start)
756 *start = saved_size;
757
758 return 0;
759fail:
760 dns_packet_truncate(p, saved_size);
761 return r;
762}
763
764static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
765 uint8_t window = 0;
1792f223 766 uint8_t entry = 0;
50f1e641
TG
767 uint8_t bitmaps[32] = {};
768 unsigned n;
769 size_t saved_size;
770 int r;
771
772 assert(p);
50f1e641
TG
773
774 saved_size = p->size;
775
90e74a66 776 BITMAP_FOREACH(n, types) {
50f1e641
TG
777 assert(n <= 0xffff);
778
1792f223
TG
779 if ((n >> 8) != window && bitmaps[entry / 8] != 0) {
780 r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
50f1e641
TG
781 if (r < 0)
782 goto fail;
783
1792f223 784 zero(bitmaps);
50f1e641
TG
785 }
786
1792f223 787 window = n >> 8;
50f1e641
TG
788 entry = n & 255;
789
790 bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
791 }
792
d0ae14ff
LP
793 if (bitmaps[entry / 8] != 0) {
794 r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
795 if (r < 0)
796 goto fail;
797 }
50f1e641
TG
798
799 if (start)
800 *start = saved_size;
801
802 return 0;
803fail:
804 dns_packet_truncate(p, saved_size);
805 return r;
806}
807
dc913c9a 808/* Append the OPT pseudo-RR described in RFC6891 */
c36d5b5b
LP
809int dns_packet_append_opt(
810 DnsPacket *p,
811 uint16_t max_udp_size,
812 bool edns0_do,
813 bool include_rfc6975,
4a6eb824 814 const char *nsid,
c36d5b5b 815 int rcode,
4a6eb824 816 size_t *ret_start) {
c36d5b5b 817
dc913c9a
TG
818 size_t saved_size;
819 int r;
820
821 assert(p);
822 /* we must never advertise supported packet size smaller than the legacy max */
823 assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
f2ed4c69
LP
824 assert(rcode >= 0);
825 assert(rcode <= _DNS_RCODE_MAX);
dc913c9a 826
f5fbe71d 827 if (p->opt_start != SIZE_MAX)
519ef046
LP
828 return -EBUSY;
829
f5fbe71d 830 assert(p->opt_size == SIZE_MAX);
519ef046 831
dc913c9a
TG
832 saved_size = p->size;
833
834 /* empty name */
835 r = dns_packet_append_uint8(p, 0, NULL);
836 if (r < 0)
837 return r;
838
839 /* type */
840 r = dns_packet_append_uint16(p, DNS_TYPE_OPT, NULL);
841 if (r < 0)
842 goto fail;
843
f2ed4c69 844 /* class: maximum udp packet that can be received */
dc913c9a
TG
845 r = dns_packet_append_uint16(p, max_udp_size, NULL);
846 if (r < 0)
847 goto fail;
848
849 /* extended RCODE and VERSION */
f2ed4c69 850 r = dns_packet_append_uint16(p, ((uint16_t) rcode & 0x0FF0) << 4, NULL);
dc913c9a
TG
851 if (r < 0)
852 goto fail;
853
7586f4d1
TG
854 /* flags: DNSSEC OK (DO), see RFC3225 */
855 r = dns_packet_append_uint16(p, edns0_do ? EDNS0_OPT_DO : 0, NULL);
dc913c9a
TG
856 if (r < 0)
857 goto fail;
858
c36d5b5b
LP
859 if (edns0_do && include_rfc6975) {
860 /* If DO is on and this is requested, also append RFC6975 Algorithm data. This is supposed to
861 * be done on queries, not on replies, hencer callers should turn this off when finishing off
862 * replies. */
665408ac
LP
863
864 static const uint8_t rfc6975[] = {
865
980cb160 866 0, DNS_EDNS_OPT_DAU, /* OPTION_CODE */
e9d4b88b 867#if HAVE_OPENSSL
73a4cd17
MCO
868 0, 7, /* LIST_LENGTH */
869#else
665408ac 870 0, 6, /* LIST_LENGTH */
73a4cd17 871#endif
665408ac
LP
872 DNSSEC_ALGORITHM_RSASHA1,
873 DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1,
874 DNSSEC_ALGORITHM_RSASHA256,
875 DNSSEC_ALGORITHM_RSASHA512,
876 DNSSEC_ALGORITHM_ECDSAP256SHA256,
877 DNSSEC_ALGORITHM_ECDSAP384SHA384,
e9d4b88b 878#if HAVE_OPENSSL
73a4cd17
MCO
879 DNSSEC_ALGORITHM_ED25519,
880#endif
665408ac 881
980cb160 882 0, DNS_EDNS_OPT_DHU, /* OPTION_CODE */
665408ac
LP
883 0, 3, /* LIST_LENGTH */
884 DNSSEC_DIGEST_SHA1,
885 DNSSEC_DIGEST_SHA256,
886 DNSSEC_DIGEST_SHA384,
887
980cb160 888 0, DNS_EDNS_OPT_N3U, /* OPTION_CODE */
665408ac
LP
889 0, 1, /* LIST_LENGTH */
890 NSEC3_ALGORITHM_SHA1,
891 };
892
4a6eb824
LP
893 r = dns_packet_append_uint16(p, sizeof(rfc6975), NULL); /* RDLENGTH */
894 if (r < 0)
895 goto fail;
896
897 r = dns_packet_append_blob(p, rfc6975, sizeof(rfc6975), NULL); /* the payload, as defined above */
898
899 } else if (nsid) {
900
901 if (strlen(nsid) > UINT16_MAX - 4) {
902 r = -E2BIG;
903 goto fail;
904 }
905
906 r = dns_packet_append_uint16(p, 4 + strlen(nsid), NULL); /* RDLENGTH */
665408ac
LP
907 if (r < 0)
908 goto fail;
909
4a6eb824
LP
910 r = dns_packet_append_uint16(p, 3, NULL); /* OPTION-CODE: NSID */
911 if (r < 0)
912 goto fail;
913
914 r = dns_packet_append_uint16(p, strlen(nsid), NULL); /* OPTION-LENGTH */
915 if (r < 0)
916 goto fail;
917
918 r = dns_packet_append_blob(p, nsid, strlen(nsid), NULL);
665408ac
LP
919 } else
920 r = dns_packet_append_uint16(p, 0, NULL);
dc913c9a
TG
921 if (r < 0)
922 goto fail;
923
519ef046
LP
924 DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) + 1);
925
926 p->opt_start = saved_size;
927 p->opt_size = p->size - saved_size;
928
4a6eb824
LP
929 if (ret_start)
930 *ret_start = saved_size;
dc913c9a
TG
931
932 return 0;
933
934fail:
935 dns_packet_truncate(p, saved_size);
936 return r;
937}
938
519ef046
LP
939int dns_packet_truncate_opt(DnsPacket *p) {
940 assert(p);
941
f5fbe71d
YW
942 if (p->opt_start == SIZE_MAX) {
943 assert(p->opt_size == SIZE_MAX);
519ef046
LP
944 return 0;
945 }
946
f5fbe71d 947 assert(p->opt_size != SIZE_MAX);
519ef046
LP
948 assert(DNS_PACKET_ARCOUNT(p) > 0);
949
950 if (p->opt_start + p->opt_size != p->size)
951 return -EBUSY;
952
953 dns_packet_truncate(p, p->opt_start);
954 DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) - 1);
f5fbe71d 955 p->opt_start = p->opt_size = SIZE_MAX;
519ef046
LP
956
957 return 1;
958}
959
58ab31d5 960int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, const DnsAnswerFlags flags, size_t *start, size_t *rdata_start) {
f471bc11 961
a8812dd7 962 size_t saved_size, rdlength_offset, end, rdlength, rds;
c3ae4188 963 uint32_t ttl;
623a4c97
LP
964 int r;
965
966 assert(p);
967 assert(rr);
968
969 saved_size = p->size;
970
58ab31d5 971 r = dns_packet_append_key(p, rr->key, flags, NULL);
623a4c97
LP
972 if (r < 0)
973 goto fail;
974
c3ae4188
DR
975 ttl = flags & DNS_ANSWER_GOODBYE ? 0 : rr->ttl;
976 r = dns_packet_append_uint32(p, ttl, NULL);
623a4c97
LP
977 if (r < 0)
978 goto fail;
979
980 /* Initially we write 0 here */
981 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
982 if (r < 0)
983 goto fail;
984
a8812dd7
LP
985 rds = p->size - saved_size;
986
52e085af 987 switch (rr->unparsable ? _DNS_TYPE_INVALID : rr->key->type) {
623a4c97 988
9c92ce6d
LP
989 case DNS_TYPE_SRV:
990 r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
991 if (r < 0)
992 goto fail;
993
994 r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
995 if (r < 0)
996 goto fail;
997
998 r = dns_packet_append_uint16(p, rr->srv.port, NULL);
999 if (r < 0)
1000 goto fail;
1001
d9a55740
LP
1002 /* RFC 2782 states "Unless and until permitted by future standards action, name compression
1003 * is not to be used for this field." Hence we turn off compression here. */
1004 r = dns_packet_append_name(p, rr->srv.name, /* allow_compression= */ false, /* canonical_candidate= */ true, NULL);
9c92ce6d
LP
1005 break;
1006
623a4c97
LP
1007 case DNS_TYPE_PTR:
1008 case DNS_TYPE_NS:
1009 case DNS_TYPE_CNAME:
8ac4e9e1 1010 case DNS_TYPE_DNAME:
4e58741d 1011 r = dns_packet_append_name(p, rr->ptr.name, true, true, NULL);
623a4c97
LP
1012 break;
1013
1014 case DNS_TYPE_HINFO:
1015 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
1016 if (r < 0)
1017 goto fail;
1018
1019 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
1020 break;
1021
9de3e329 1022 case DNS_TYPE_SPF: /* exactly the same as TXT */
2001c805 1023 case DNS_TYPE_TXT:
2e276efc 1024
2001c805 1025 if (!rr->txt.items) {
1ccda9b7
LP
1026 /* RFC 6763, section 6.1 suggests to generate
1027 * single empty string for an empty array. */
1028
2001c805 1029 r = dns_packet_append_raw_string(p, NULL, 0, NULL);
2e276efc
ZJS
1030 if (r < 0)
1031 goto fail;
03677889 1032 } else
2001c805
LP
1033 LIST_FOREACH(items, i, rr->txt.items) {
1034 r = dns_packet_append_raw_string(p, i->data, i->length, NULL);
1ccda9b7
LP
1035 if (r < 0)
1036 goto fail;
1037 }
2e276efc 1038
6a6fc3df 1039 r = 0;
2e276efc 1040 break;
2e276efc 1041
623a4c97
LP
1042 case DNS_TYPE_A:
1043 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
1044 break;
1045
1046 case DNS_TYPE_AAAA:
1047 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
1048 break;
1049
1050 case DNS_TYPE_SOA:
4e58741d 1051 r = dns_packet_append_name(p, rr->soa.mname, true, true, NULL);
623a4c97
LP
1052 if (r < 0)
1053 goto fail;
1054
4e58741d 1055 r = dns_packet_append_name(p, rr->soa.rname, true, true, NULL);
623a4c97
LP
1056 if (r < 0)
1057 goto fail;
1058
1059 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
1060 if (r < 0)
1061 goto fail;
1062
1063 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
1064 if (r < 0)
1065 goto fail;
1066
1067 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
1068 if (r < 0)
1069 goto fail;
1070
1071 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
1072 if (r < 0)
1073 goto fail;
1074
1075 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
1076 break;
1077
1078 case DNS_TYPE_MX:
946c7094
ZJS
1079 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
1080 if (r < 0)
1081 goto fail;
1082
4e58741d 1083 r = dns_packet_append_name(p, rr->mx.exchange, true, true, NULL);
946c7094
ZJS
1084 break;
1085
0dae31d4
ZJS
1086 case DNS_TYPE_LOC:
1087 r = dns_packet_append_uint8(p, rr->loc.version, NULL);
1088 if (r < 0)
1089 goto fail;
1090
1091 r = dns_packet_append_uint8(p, rr->loc.size, NULL);
1092 if (r < 0)
1093 goto fail;
1094
1095 r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
1096 if (r < 0)
1097 goto fail;
1098
1099 r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
1100 if (r < 0)
1101 goto fail;
1102
afbc4f26 1103 r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
0dae31d4
ZJS
1104 if (r < 0)
1105 goto fail;
1106
afbc4f26 1107 r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
0dae31d4
ZJS
1108 if (r < 0)
1109 goto fail;
1110
afbc4f26 1111 r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
0dae31d4
ZJS
1112 break;
1113
abf126a3
TG
1114 case DNS_TYPE_DS:
1115 r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL);
1116 if (r < 0)
1117 goto fail;
1118
1119 r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL);
1120 if (r < 0)
1121 goto fail;
1122
1123 r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL);
1124 if (r < 0)
1125 goto fail;
1126
1127 r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL);
1128 break;
1129
623a4c97 1130 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1131 r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
1132 if (r < 0)
1133 goto fail;
8db0d2f5 1134
42cc2eeb
LP
1135 r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
1136 if (r < 0)
1137 goto fail;
1138
549c1a25 1139 r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL);
42cc2eeb
LP
1140 break;
1141
8db0d2f5 1142 case DNS_TYPE_DNSKEY:
f91dc240 1143 r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL);
8db0d2f5
ZJS
1144 if (r < 0)
1145 goto fail;
1146
f91dc240 1147 r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL);
8db0d2f5
ZJS
1148 if (r < 0)
1149 goto fail;
1150
1151 r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
1152 if (r < 0)
1153 goto fail;
1154
1155 r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
1156 break;
1157
151226ab
ZJS
1158 case DNS_TYPE_RRSIG:
1159 r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
1160 if (r < 0)
1161 goto fail;
1162
1163 r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
1164 if (r < 0)
1165 goto fail;
1166
1167 r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
1168 if (r < 0)
1169 goto fail;
1170
1171 r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
1172 if (r < 0)
1173 goto fail;
1174
1175 r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
1176 if (r < 0)
1177 goto fail;
1178
1179 r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
1180 if (r < 0)
1181 goto fail;
1182
0b1b17d3 1183 r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL);
151226ab
ZJS
1184 if (r < 0)
1185 goto fail;
1186
a3db237b 1187 r = dns_packet_append_name(p, rr->rrsig.signer, false, true, NULL);
151226ab
ZJS
1188 if (r < 0)
1189 goto fail;
1190
1191 r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
1192 break;
1193
50f1e641 1194 case DNS_TYPE_NSEC:
a3db237b 1195 r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, false, NULL);
50f1e641
TG
1196 if (r < 0)
1197 goto fail;
1198
1199 r = dns_packet_append_types(p, rr->nsec.types, NULL);
1200 if (r < 0)
1201 goto fail;
1202
5d45a880 1203 break;
d75acfb0 1204
5d45a880
TG
1205 case DNS_TYPE_NSEC3:
1206 r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL);
1207 if (r < 0)
1208 goto fail;
1209
1210 r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL);
1211 if (r < 0)
1212 goto fail;
1213
1214 r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL);
1215 if (r < 0)
1216 goto fail;
1217
1218 r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL);
1219 if (r < 0)
1220 goto fail;
1221
1222 r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL);
1223 if (r < 0)
1224 goto fail;
1225
1226 r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL);
1227 if (r < 0)
1228 goto fail;
1229
1230 r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL);
1231 if (r < 0)
1232 goto fail;
1233
1234 r = dns_packet_append_types(p, rr->nsec3.types, NULL);
1235 if (r < 0)
1236 goto fail;
1237
50f1e641 1238 break;
d75acfb0 1239
48d45d2b
ZJS
1240 case DNS_TYPE_TLSA:
1241 r = dns_packet_append_uint8(p, rr->tlsa.cert_usage, NULL);
1242 if (r < 0)
1243 goto fail;
1244
1245 r = dns_packet_append_uint8(p, rr->tlsa.selector, NULL);
1246 if (r < 0)
1247 goto fail;
1248
1249 r = dns_packet_append_uint8(p, rr->tlsa.matching_type, NULL);
1250 if (r < 0)
1251 goto fail;
1252
1253 r = dns_packet_append_blob(p, rr->tlsa.data, rr->tlsa.data_size, NULL);
1254 break;
1255
e7634d6b
RP
1256 case DNS_TYPE_SVCB:
1257 case DNS_TYPE_HTTPS:
1258 r = dns_packet_append_uint16(p, rr->svcb.priority, NULL);
1259 if (r < 0)
1260 goto fail;
1261
1262 r = dns_packet_append_name(p, rr->svcb.target_name, false, false, NULL);
1263 if (r < 0)
1264 goto fail;
1265
1266 LIST_FOREACH(params, i, rr->svcb.params) {
1267 r = dns_packet_append_uint16(p, i->key, NULL);
1268 if (r < 0)
1269 goto fail;
1270
1271 r = dns_packet_append_uint16(p, i->length, NULL);
1272 if (r < 0)
1273 goto fail;
1274
1275 r = dns_packet_append_blob(p, i->value, i->length, NULL);
1276 if (r < 0)
1277 goto fail;
1278 }
1279 break;
1280
95052df3
ZJS
1281 case DNS_TYPE_CAA:
1282 r = dns_packet_append_uint8(p, rr->caa.flags, NULL);
1283 if (r < 0)
1284 goto fail;
1285
1286 r = dns_packet_append_string(p, rr->caa.tag, NULL);
1287 if (r < 0)
1288 goto fail;
1289
1290 r = dns_packet_append_blob(p, rr->caa.value, rr->caa.value_size, NULL);
1291 break;
1292
17615676
LP
1293 case DNS_TYPE_NAPTR:
1294 r = dns_packet_append_uint16(p, rr->naptr.order, NULL);
1295 if (r < 0)
1296 goto fail;
1297
1298 r = dns_packet_append_uint16(p, rr->naptr.preference, NULL);
1299 if (r < 0)
1300 goto fail;
1301
1302 r = dns_packet_append_string(p, rr->naptr.flags, NULL);
1303 if (r < 0)
1304 goto fail;
1305
1306 r = dns_packet_append_string(p, rr->naptr.services, NULL);
1307 if (r < 0)
1308 goto fail;
1309
1310 r = dns_packet_append_string(p, rr->naptr.regexp, NULL);
1311 if (r < 0)
1312 goto fail;
1313
1314 r = dns_packet_append_name(p, rr->naptr.replacement, /* allow_compression= */ false, /* canonical_candidate= */ true, NULL);
1315 break;
1316
d75acfb0 1317 case DNS_TYPE_OPT:
d93a16b8 1318 case DNS_TYPE_OPENPGPKEY:
52e085af 1319 case _DNS_TYPE_INVALID: /* unparsable */
623a4c97 1320 default:
a43a068a 1321 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.data_size, NULL);
623a4c97
LP
1322 }
1323 if (r < 0)
1324 goto fail;
1325
1326 /* Let's calculate the actual data size and update the field */
1327 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
1328 if (rdlength > 0xFFFF) {
555f5cdc 1329 r = -ENOSPC;
623a4c97
LP
1330 goto fail;
1331 }
1332
1333 end = p->size;
1334 p->size = rdlength_offset;
1335 r = dns_packet_append_uint16(p, rdlength, NULL);
1336 if (r < 0)
1337 goto fail;
1338 p->size = end;
1339
351e6342
LP
1340 if (start)
1341 *start = saved_size;
1342
a8812dd7
LP
1343 if (rdata_start)
1344 *rdata_start = rds;
1345
623a4c97
LP
1346 return 0;
1347
1348fail:
1349 dns_packet_truncate(p, saved_size);
1350 return r;
1351}
1352
f471bc11
LP
1353int dns_packet_append_question(DnsPacket *p, DnsQuestion *q) {
1354 DnsResourceKey *key;
1355 int r;
1356
1357 assert(p);
1358
1359 DNS_QUESTION_FOREACH(key, q) {
58ab31d5 1360 r = dns_packet_append_key(p, key, 0, NULL);
f471bc11
LP
1361 if (r < 0)
1362 return r;
1363 }
1364
1365 return 0;
1366}
1367
6f76e68a 1368int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a, unsigned *completed) {
f471bc11 1369 DnsResourceRecord *rr;
58ab31d5 1370 DnsAnswerFlags flags;
f471bc11
LP
1371 int r;
1372
1373 assert(p);
1374
58ab31d5
DR
1375 DNS_ANSWER_FOREACH_FLAGS(rr, flags, a) {
1376 r = dns_packet_append_rr(p, rr, flags, NULL, NULL);
f471bc11
LP
1377 if (r < 0)
1378 return r;
6f76e68a
LP
1379
1380 if (completed)
1381 (*completed)++;
f471bc11
LP
1382 }
1383
1384 return 0;
1385}
1386
74b2466e
LP
1387int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
1388 assert(p);
370999c0 1389 assert(p->rindex <= p->size);
74b2466e 1390
370999c0 1391 if (sz > p->size - p->rindex)
74b2466e
LP
1392 return -EMSGSIZE;
1393
1394 if (ret)
1395 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
1396
1397 if (start)
1398 *start = p->rindex;
1399
1400 p->rindex += sz;
1401 return 0;
1402}
1403
8ba9fd9c 1404void dns_packet_rewind(DnsPacket *p, size_t idx) {
74b2466e
LP
1405 assert(p);
1406 assert(idx <= p->size);
1407 assert(idx >= DNS_PACKET_HEADER_SIZE);
1408
1409 p->rindex = idx;
1410}
1411
623a4c97
LP
1412int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
1413 const void *q;
1414 int r;
1415
1416 assert(p);
1417 assert(d);
1418
1419 r = dns_packet_read(p, sz, &q, start);
1420 if (r < 0)
1421 return r;
1422
1423 memcpy(d, q, sz);
1424 return 0;
1425}
1426
f5430a3e
LP
1427static int dns_packet_read_memdup(
1428 DnsPacket *p, size_t size,
1429 void **ret, size_t *ret_size,
1430 size_t *ret_start) {
1431
1432 const void *src;
1433 size_t start;
1434 int r;
1435
1436 assert(p);
1437 assert(ret);
1438
1439 r = dns_packet_read(p, size, &src, &start);
1440 if (r < 0)
1441 return r;
1442
1443 if (size <= 0)
1444 *ret = NULL;
1445 else {
1446 void *copy;
1447
1448 copy = memdup(src, size);
1449 if (!copy)
1450 return -ENOMEM;
1451
1452 *ret = copy;
1453 }
1454
1455 if (ret_size)
1456 *ret_size = size;
1457 if (ret_start)
1458 *ret_start = start;
1459
1460 return 0;
1461}
1462
74b2466e
LP
1463int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
1464 const void *d;
1465 int r;
1466
1467 assert(p);
1468
1469 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
1470 if (r < 0)
1471 return r;
1472
1473 *ret = ((uint8_t*) d)[0];
1474 return 0;
1475}
1476
1477int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
1478 const void *d;
1479 int r;
1480
1481 assert(p);
1482
1483 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
1484 if (r < 0)
1485 return r;
1486
81b4d94d
LP
1487 if (ret)
1488 *ret = unaligned_read_be16(d);
725ca0e5 1489
74b2466e
LP
1490 return 0;
1491}
1492
1493int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
1494 const void *d;
1495 int r;
1496
1497 assert(p);
1498
1499 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
1500 if (r < 0)
1501 return r;
1502
725ca0e5 1503 *ret = unaligned_read_be32(d);
74b2466e
LP
1504
1505 return 0;
1506}
1507
1508int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
0c4f37f0 1509 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = REWINDER_INIT(p);
7153213e 1510 _cleanup_free_ char *t = NULL;
74b2466e 1511 const void *d;
74b2466e
LP
1512 uint8_t c;
1513 int r;
1514
7153213e
LP
1515 assert(p);
1516
74b2466e
LP
1517 r = dns_packet_read_uint8(p, &c, NULL);
1518 if (r < 0)
e18a3c73 1519 return r;
74b2466e
LP
1520
1521 r = dns_packet_read(p, c, &d, NULL);
1522 if (r < 0)
e18a3c73 1523 return r;
74b2466e 1524
7153213e
LP
1525 r = make_cstring(d, c, MAKE_CSTRING_REFUSE_TRAILING_NUL, &t);
1526 if (r < 0)
1527 return r;
74b2466e 1528
7153213e 1529 if (!utf8_is_valid(t))
e18a3c73 1530 return -EBADMSG;
74b2466e 1531
7153213e 1532 *ret = TAKE_PTR(t);
74b2466e
LP
1533
1534 if (start)
e18a3c73
ZJS
1535 *start = rewinder.saved_rindex;
1536 CANCEL_REWINDER(rewinder);
74b2466e
LP
1537
1538 return 0;
74b2466e
LP
1539}
1540
2001c805 1541int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start) {
0c4f37f0
ZJS
1542 assert(p);
1543
1544 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = REWINDER_INIT(p);
2001c805
LP
1545 uint8_t c;
1546 int r;
1547
2001c805
LP
1548 r = dns_packet_read_uint8(p, &c, NULL);
1549 if (r < 0)
e18a3c73 1550 return r;
2001c805
LP
1551
1552 r = dns_packet_read(p, c, ret, NULL);
1553 if (r < 0)
e18a3c73 1554 return r;
2001c805
LP
1555
1556 if (size)
1557 *size = c;
1558 if (start)
e18a3c73
ZJS
1559 *start = rewinder.saved_rindex;
1560 CANCEL_REWINDER(rewinder);
2001c805
LP
1561
1562 return 0;
2001c805
LP
1563}
1564
f6a5fec6
LP
1565int dns_packet_read_name(
1566 DnsPacket *p,
81b4d94d 1567 char **ret,
f6a5fec6 1568 bool allow_compression,
81b4d94d 1569 size_t *ret_start) {
f6a5fec6 1570
0c4f37f0
ZJS
1571 assert(p);
1572
1573 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = REWINDER_INIT(p);
1574 size_t after_rindex = 0, jump_barrier = p->rindex;
81b4d94d 1575 _cleanup_free_ char *name = NULL;
74b2466e 1576 bool first = true;
87d6a9fb 1577 size_t n = 0, m = 0;
74b2466e
LP
1578 int r;
1579
f6a5fec6
LP
1580 if (p->refuse_compression)
1581 allow_compression = false;
1582
74b2466e
LP
1583 for (;;) {
1584 uint8_t c, d;
1585
1586 r = dns_packet_read_uint8(p, &c, NULL);
1587 if (r < 0)
e18a3c73 1588 return r;
74b2466e
LP
1589
1590 if (c == 0)
1591 /* End of name */
1592 break;
1593 else if (c <= 63) {
74b2466e
LP
1594 const char *label;
1595
1596 /* Literal label */
1597 r = dns_packet_read(p, c, (const void**) &label, NULL);
1598 if (r < 0)
e18a3c73 1599 return r;
74b2466e 1600
319a4f4b 1601 if (!GREEDY_REALLOC(name, n + !first + DNS_LABEL_ESCAPED_MAX))
e18a3c73 1602 return -ENOMEM;
74b2466e 1603
422baca0 1604 if (first)
74b2466e 1605 first = false;
87d6a9fb 1606 else {
81b4d94d 1607 name[n++] = '.';
87d6a9fb
LP
1608 m++;
1609 }
422baca0 1610
81b4d94d 1611 r = dns_label_escape(label, c, name + n, DNS_LABEL_ESCAPED_MAX);
422baca0 1612 if (r < 0)
e18a3c73 1613 return r;
74b2466e 1614
74b2466e 1615 n += r;
87d6a9fb
LP
1616 m += c;
1617
1618 if (m > DNS_HOSTNAME_MAX)
1619 return -EBADMSG;
1620
74b2466e 1621 continue;
d7a0f1f4 1622 } else if (allow_compression && FLAGS_SET(c, 0xc0)) {
74b2466e
LP
1623 uint16_t ptr;
1624
1625 /* Pointer */
1626 r = dns_packet_read_uint8(p, &d, NULL);
1627 if (r < 0)
e18a3c73 1628 return r;
74b2466e
LP
1629
1630 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
e18a3c73
ZJS
1631 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier)
1632 return -EBADMSG;
74b2466e
LP
1633
1634 if (after_rindex == 0)
1635 after_rindex = p->rindex;
1636
f131770b 1637 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
c75dbf9b 1638 jump_barrier = ptr;
74b2466e 1639 p->rindex = ptr;
e18a3c73
ZJS
1640 } else
1641 return -EBADMSG;
74b2466e
LP
1642 }
1643
319a4f4b 1644 if (!GREEDY_REALLOC(name, n + 1))
e18a3c73 1645 return -ENOMEM;
74b2466e 1646
81b4d94d 1647 name[n] = 0;
74b2466e
LP
1648
1649 if (after_rindex != 0)
1650 p->rindex= after_rindex;
1651
81b4d94d
LP
1652 if (ret)
1653 *ret = TAKE_PTR(name);
1654 if (ret_start)
1655 *ret_start = rewinder.saved_rindex;
74b2466e 1656
e18a3c73 1657 CANCEL_REWINDER(rewinder);
74b2466e
LP
1658
1659 return 0;
74b2466e
LP
1660}
1661
50f1e641 1662static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) {
0c4f37f0
ZJS
1663 assert(p);
1664 assert(types);
1665
1666 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = REWINDER_INIT(p);
1667 uint8_t window, length;
50f1e641 1668 const uint8_t *bitmap;
2ad613ad 1669 uint8_t bit = 0;
50f1e641 1670 bool found = false;
50f1e641
TG
1671 int r;
1672
50f1e641
TG
1673 r = bitmap_ensure_allocated(types);
1674 if (r < 0)
e18a3c73 1675 return r;
50f1e641
TG
1676
1677 r = dns_packet_read_uint8(p, &window, NULL);
1678 if (r < 0)
e18a3c73 1679 return r;
50f1e641
TG
1680
1681 r = dns_packet_read_uint8(p, &length, NULL);
1682 if (r < 0)
e18a3c73 1683 return r;
50f1e641
TG
1684
1685 if (length == 0 || length > 32)
1686 return -EBADMSG;
1687
1688 r = dns_packet_read(p, length, (const void **)&bitmap, NULL);
1689 if (r < 0)
e18a3c73 1690 return r;
50f1e641 1691
64ea42e9 1692 for (uint8_t i = 0; i < length; i++) {
50f1e641 1693 uint8_t bitmask = 1 << 7;
50f1e641
TG
1694
1695 if (!bitmap[i]) {
1696 found = false;
2ad613ad 1697 bit += 8;
50f1e641
TG
1698 continue;
1699 }
1700
1701 found = true;
1702
9f939335 1703 for (; bitmask; bit++, bitmask >>= 1)
50f1e641
TG
1704 if (bitmap[i] & bitmask) {
1705 uint16_t n;
1706
50f1e641
TG
1707 n = (uint16_t) window << 8 | (uint16_t) bit;
1708
8e6edc49
TG
1709 /* Ignore pseudo-types. see RFC4034 section 4.1.2 */
1710 if (dns_type_is_pseudo(n))
1711 continue;
1712
50f1e641
TG
1713 r = bitmap_set(*types, n);
1714 if (r < 0)
e18a3c73 1715 return r;
50f1e641 1716 }
50f1e641
TG
1717 }
1718
1719 if (!found)
1720 return -EBADMSG;
1721
1722 if (start)
e18a3c73
ZJS
1723 *start = rewinder.saved_rindex;
1724 CANCEL_REWINDER(rewinder);
50f1e641
TG
1725
1726 return 0;
50f1e641
TG
1727}
1728
89492aaf 1729static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
0c4f37f0 1730 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = REWINDER_INIT(p);
89492aaf
TG
1731 int r;
1732
370999c0 1733 while (p->rindex - rewinder.saved_rindex < size) {
89492aaf
TG
1734 r = dns_packet_read_type_window(p, types, NULL);
1735 if (r < 0)
e18a3c73 1736 return r;
89492aaf 1737
370999c0
YW
1738 assert(p->rindex >= rewinder.saved_rindex);
1739
89492aaf 1740 /* don't read past end of current RR */
370999c0 1741 if (p->rindex - rewinder.saved_rindex > size)
e18a3c73 1742 return -EBADMSG;
89492aaf
TG
1743 }
1744
370999c0 1745 if (p->rindex - rewinder.saved_rindex != size)
e18a3c73 1746 return -EBADMSG;
89492aaf
TG
1747
1748 if (start)
e18a3c73
ZJS
1749 *start = rewinder.saved_rindex;
1750 CANCEL_REWINDER(rewinder);
89492aaf
TG
1751
1752 return 0;
89492aaf
TG
1753}
1754
81b4d94d
LP
1755int dns_packet_read_key(
1756 DnsPacket *p,
1757 DnsResourceKey **ret,
82d39576 1758 bool *ret_cache_flush_or_qu,
81b4d94d
LP
1759 size_t *ret_start) {
1760
0c4f37f0
ZJS
1761 assert(p);
1762
1763 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = REWINDER_INIT(p);
faa133f3 1764 _cleanup_free_ char *name = NULL;
82d39576 1765 bool cache_flush_or_qu = false;
faa133f3 1766 uint16_t class, type;
74b2466e
LP
1767 int r;
1768
151226ab 1769 r = dns_packet_read_name(p, &name, true, NULL);
74b2466e 1770 if (r < 0)
e18a3c73 1771 return r;
74b2466e 1772
faa133f3 1773 r = dns_packet_read_uint16(p, &type, NULL);
74b2466e 1774 if (r < 0)
e18a3c73 1775 return r;
74b2466e 1776
faa133f3 1777 r = dns_packet_read_uint16(p, &class, NULL);
74b2466e 1778 if (r < 0)
e18a3c73 1779 return r;
74b2466e 1780
23502de3 1781 if (p->protocol == DNS_PROTOCOL_MDNS) {
82d39576 1782 /* See RFC6762, sections 5.4 and 10.2 */
23502de3 1783
82d39576
SB
1784 if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH_OR_QU)) {
1785 class &= ~MDNS_RR_CACHE_FLUSH_OR_QU;
1786 cache_flush_or_qu = true;
d2579eec 1787 }
23502de3
DM
1788 }
1789
81b4d94d
LP
1790 if (ret) {
1791 DnsResourceKey *key;
faa133f3 1792
81b4d94d
LP
1793 key = dns_resource_key_new_consume(class, type, name);
1794 if (!key)
1795 return -ENOMEM;
1796
1797 TAKE_PTR(name);
1798 *ret = key;
1799 }
74b2466e 1800
82d39576
SB
1801 if (ret_cache_flush_or_qu)
1802 *ret_cache_flush_or_qu = cache_flush_or_qu;
81b4d94d
LP
1803 if (ret_start)
1804 *ret_start = rewinder.saved_rindex;
74b2466e 1805
81b4d94d 1806 CANCEL_REWINDER(rewinder);
74b2466e 1807 return 0;
74b2466e
LP
1808}
1809
afbc4f26
ZJS
1810static bool loc_size_ok(uint8_t size) {
1811 uint8_t m = size >> 4, e = size & 0xF;
1812
1813 return m <= 9 && e <= 9 && (m > 0 || e == 0);
1814}
1815
e7634d6b
RP
1816static bool dns_svc_param_is_valid(DnsSvcParam *i) {
1817 if (!i)
1818 return false;
1819
1820 switch (i->key) {
1821 /* RFC 9460, section 7.1.1: alpn-ids must exactly fill SvcParamValue */
1822 case DNS_SVC_PARAM_KEY_ALPN: {
1823 size_t sz = 0;
1824 if (i->length <= 0)
1825 return false;
1826 while (sz < i->length)
1827 sz += 1 + i->value[sz]; /* N.B. will not overflow */
1828 return sz == i->length;
1829 }
1830
1831 /* RFC 9460, section 7.1.1: value must be empty */
1832 case DNS_SVC_PARAM_KEY_NO_DEFAULT_ALPN:
1833 return i->length == 0;
1834
1835 /* RFC 9460, section 7.2 */
1836 case DNS_SVC_PARAM_KEY_PORT:
1837 return i->length == 2;
1838
1839 /* RFC 9460, section 7.3: addrs must exactly fill SvcParamValue */
1840 case DNS_SVC_PARAM_KEY_IPV4HINT:
26551c0f 1841 return i->length > 0 && i->length % (sizeof (struct in_addr)) == 0;
e7634d6b 1842 case DNS_SVC_PARAM_KEY_IPV6HINT:
26551c0f 1843 return i->length > 0 && i->length % (sizeof (struct in6_addr)) == 0;
e7634d6b
RP
1844
1845 /* Otherwise, permit any value */
1846 default:
1847 return true;
1848 }
1849}
1850
81b4d94d
LP
1851int dns_packet_read_rr(
1852 DnsPacket *p,
1853 DnsResourceRecord **ret,
1854 bool *ret_cache_flush,
1855 size_t *ret_start) {
1856
0c4f37f0
ZJS
1857 assert(p);
1858
1859 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = REWINDER_INIT(p);
faa133f3
LP
1860 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1861 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
e18a3c73 1862 size_t offset;
74b2466e 1863 uint16_t rdlength;
d2579eec 1864 bool cache_flush;
74b2466e
LP
1865 int r;
1866
d2579eec 1867 r = dns_packet_read_key(p, &key, &cache_flush, NULL);
74b2466e 1868 if (r < 0)
e18a3c73 1869 return r;
74b2466e 1870
e18a3c73
ZJS
1871 if (!dns_class_is_valid_rr(key->class) || !dns_type_is_valid_rr(key->type))
1872 return -EBADMSG;
0e2bcd6a 1873
faa133f3 1874 rr = dns_resource_record_new(key);
e18a3c73
ZJS
1875 if (!rr)
1876 return -ENOMEM;
faa133f3 1877
74b2466e
LP
1878 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1879 if (r < 0)
e18a3c73 1880 return r;
74b2466e 1881
13178797 1882 /* RFC 2181, Section 8, suggests to treat a TTL with the MSB set as a zero TTL. We avoid doing this
d7306348 1883 * for OPT records so that all 8 bits of the extended RCODE may be used. */
13178797 1884 if (key->type != DNS_TYPE_OPT && rr->ttl & UINT32_C(0x80000000))
0d0b52d7
LP
1885 rr->ttl = 0;
1886
74b2466e
LP
1887 r = dns_packet_read_uint16(p, &rdlength, NULL);
1888 if (r < 0)
e18a3c73 1889 return r;
74b2466e 1890
370999c0 1891 if (rdlength > p->size - p->rindex)
e18a3c73 1892 return -EBADMSG;
74b2466e
LP
1893
1894 offset = p->rindex;
1895
faa133f3 1896 switch (rr->key->type) {
74b2466e 1897
9c92ce6d
LP
1898 case DNS_TYPE_SRV:
1899 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1900 if (r < 0)
e18a3c73 1901 return r;
9c92ce6d
LP
1902 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1903 if (r < 0)
e18a3c73 1904 return r;
9c92ce6d
LP
1905 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1906 if (r < 0)
e18a3c73 1907 return r;
d9a55740
LP
1908
1909 /* RFC 2782 states "Unless and until permitted by future standards action, name compression
1910 * is not to be used for this field." Nonetheless, we support it here, in the interest of
1911 * increasing compatibility with implementations that do not implement this correctly. After
1912 * all we didn't do this right once upon a time ourselves (see
1913 * https://github.com/systemd/systemd/issues/9793). */
1914 r = dns_packet_read_name(p, &rr->srv.name, /* allow_compression= */ true, NULL);
9c92ce6d
LP
1915 break;
1916
74b2466e
LP
1917 case DNS_TYPE_PTR:
1918 case DNS_TYPE_NS:
1919 case DNS_TYPE_CNAME:
8ac4e9e1 1920 case DNS_TYPE_DNAME:
151226ab 1921 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1922 break;
1923
1924 case DNS_TYPE_HINFO:
1925 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1926 if (r < 0)
e18a3c73 1927 return r;
74b2466e
LP
1928
1929 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1930 break;
1931
9de3e329 1932 case DNS_TYPE_SPF: /* exactly the same as TXT */
1ccda9b7
LP
1933 case DNS_TYPE_TXT:
1934 if (rdlength <= 0) {
ebb779dc
DR
1935 r = dns_txt_item_new_empty(&rr->txt.items);
1936 if (r < 0)
1937 return r;
1ccda9b7 1938 } else {
2001c805
LP
1939 DnsTxtItem *last = NULL;
1940
370999c0 1941 while (p->rindex - offset < rdlength) {
2001c805
LP
1942 DnsTxtItem *i;
1943 const void *data;
1944 size_t sz;
2e276efc 1945
2001c805 1946 r = dns_packet_read_raw_string(p, &data, &sz, NULL);
1ccda9b7 1947 if (r < 0)
2001c805 1948 return r;
1ccda9b7 1949
2001c805
LP
1950 i = malloc0(offsetof(DnsTxtItem, data) + sz + 1); /* extra NUL byte at the end */
1951 if (!i)
1952 return -ENOMEM;
1953
1954 memcpy(i->data, data, sz);
1955 i->length = sz;
1956
1957 LIST_INSERT_AFTER(items, rr->txt.items, last, i);
1958 last = i;
1ccda9b7 1959 }
6a6fc3df
LP
1960 }
1961
1962 r = 0;
2e276efc 1963 break;
2e276efc 1964
74b2466e 1965 case DNS_TYPE_A:
623a4c97 1966 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1967 break;
1968
1969 case DNS_TYPE_AAAA:
623a4c97 1970 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1971 break;
1972
7e8e0422 1973 case DNS_TYPE_SOA:
151226ab 1974 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422 1975 if (r < 0)
e18a3c73 1976 return r;
7e8e0422 1977
151226ab 1978 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422 1979 if (r < 0)
e18a3c73 1980 return r;
7e8e0422
LP
1981
1982 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1983 if (r < 0)
e18a3c73 1984 return r;
7e8e0422
LP
1985
1986 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1987 if (r < 0)
e18a3c73 1988 return r;
7e8e0422
LP
1989
1990 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1991 if (r < 0)
e18a3c73 1992 return r;
7e8e0422
LP
1993
1994 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1995 if (r < 0)
e18a3c73 1996 return r;
7e8e0422
LP
1997
1998 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1999 break;
2000
623a4c97 2001 case DNS_TYPE_MX:
946c7094
ZJS
2002 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
2003 if (r < 0)
e18a3c73 2004 return r;
946c7094 2005
151226ab 2006 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
2007 break;
2008
0dae31d4
ZJS
2009 case DNS_TYPE_LOC: {
2010 uint8_t t;
2011 size_t pos;
2012
2013 r = dns_packet_read_uint8(p, &t, &pos);
2014 if (r < 0)
e18a3c73 2015 return r;
0dae31d4
ZJS
2016
2017 if (t == 0) {
2018 rr->loc.version = t;
2019
2020 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
2021 if (r < 0)
e18a3c73 2022 return r;
0dae31d4 2023
e18a3c73
ZJS
2024 if (!loc_size_ok(rr->loc.size))
2025 return -EBADMSG;
afbc4f26 2026
0dae31d4
ZJS
2027 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
2028 if (r < 0)
e18a3c73 2029 return r;
0dae31d4 2030
e18a3c73
ZJS
2031 if (!loc_size_ok(rr->loc.horiz_pre))
2032 return -EBADMSG;
afbc4f26 2033
0dae31d4
ZJS
2034 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
2035 if (r < 0)
e18a3c73 2036 return r;
0dae31d4 2037
e18a3c73
ZJS
2038 if (!loc_size_ok(rr->loc.vert_pre))
2039 return -EBADMSG;
afbc4f26 2040
0dae31d4
ZJS
2041 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
2042 if (r < 0)
e18a3c73 2043 return r;
0dae31d4
ZJS
2044
2045 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
2046 if (r < 0)
e18a3c73 2047 return r;
0dae31d4
ZJS
2048
2049 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
2050 if (r < 0)
e18a3c73 2051 return r;
0dae31d4
ZJS
2052
2053 break;
2054 } else {
2055 dns_packet_rewind(p, pos);
52e085af
ZJS
2056 rr->unparsable = true;
2057 goto unparsable;
0dae31d4
ZJS
2058 }
2059 }
2060
abf126a3
TG
2061 case DNS_TYPE_DS:
2062 r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
2063 if (r < 0)
e18a3c73 2064 return r;
abf126a3
TG
2065
2066 r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
2067 if (r < 0)
e18a3c73 2068 return r;
abf126a3
TG
2069
2070 r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
2071 if (r < 0)
e18a3c73 2072 return r;
abf126a3 2073
8a0f6d1f
SL
2074 if (rdlength < 4)
2075 return -EBADMSG;
2076
f5430a3e
LP
2077 r = dns_packet_read_memdup(p, rdlength - 4,
2078 &rr->ds.digest, &rr->ds.digest_size,
2079 NULL);
abf126a3 2080 if (r < 0)
e18a3c73 2081 return r;
abf126a3 2082
e18a3c73 2083 if (rr->ds.digest_size <= 0)
f1d178cc
TG
2084 /* the accepted size depends on the algorithm, but for now
2085 just ensure that the value is greater than zero */
e18a3c73 2086 return -EBADMSG;
f1d178cc 2087
abf126a3 2088 break;
d75acfb0 2089
623a4c97 2090 case DNS_TYPE_SSHFP:
42cc2eeb
LP
2091 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
2092 if (r < 0)
e18a3c73 2093 return r;
42cc2eeb
LP
2094
2095 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
2096 if (r < 0)
e18a3c73 2097 return r;
42cc2eeb 2098
8a0f6d1f
SL
2099 if (rdlength < 2)
2100 return -EBADMSG;
2101
f5430a3e 2102 r = dns_packet_read_memdup(p, rdlength - 2,
549c1a25 2103 &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size,
f5430a3e 2104 NULL);
f1d178cc 2105
e18a3c73 2106 if (rr->sshfp.fingerprint_size <= 0)
f1d178cc
TG
2107 /* the accepted size depends on the algorithm, but for now
2108 just ensure that the value is greater than zero */
e18a3c73 2109 return -EBADMSG;
f1d178cc 2110
8db0d2f5
ZJS
2111 break;
2112
f91dc240
LP
2113 case DNS_TYPE_DNSKEY:
2114 r = dns_packet_read_uint16(p, &rr->dnskey.flags, NULL);
8db0d2f5 2115 if (r < 0)
e18a3c73 2116 return r;
8db0d2f5 2117
f91dc240 2118 r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL);
8db0d2f5 2119 if (r < 0)
e18a3c73 2120 return r;
8db0d2f5 2121
8db0d2f5
ZJS
2122 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
2123 if (r < 0)
e18a3c73 2124 return r;
8db0d2f5 2125
8a0f6d1f
SL
2126 if (rdlength < 4)
2127 return -EBADMSG;
2128
f5430a3e
LP
2129 r = dns_packet_read_memdup(p, rdlength - 4,
2130 &rr->dnskey.key, &rr->dnskey.key_size,
2131 NULL);
f1d178cc 2132
e18a3c73 2133 if (rr->dnskey.key_size <= 0)
f1d178cc
TG
2134 /* the accepted size depends on the algorithm, but for now
2135 just ensure that the value is greater than zero */
e18a3c73 2136 return -EBADMSG;
f1d178cc 2137
42cc2eeb
LP
2138 break;
2139
151226ab
ZJS
2140 case DNS_TYPE_RRSIG:
2141 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
2142 if (r < 0)
e18a3c73 2143 return r;
151226ab
ZJS
2144
2145 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
2146 if (r < 0)
e18a3c73 2147 return r;
151226ab
ZJS
2148
2149 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
2150 if (r < 0)
e18a3c73 2151 return r;
151226ab
ZJS
2152
2153 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
2154 if (r < 0)
e18a3c73 2155 return r;
151226ab
ZJS
2156
2157 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
2158 if (r < 0)
e18a3c73 2159 return r;
151226ab
ZJS
2160
2161 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
2162 if (r < 0)
e18a3c73 2163 return r;
151226ab
ZJS
2164
2165 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
2166 if (r < 0)
e18a3c73 2167 return r;
151226ab
ZJS
2168
2169 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
2170 if (r < 0)
e18a3c73 2171 return r;
151226ab 2172
370999c0 2173 if (rdlength < p->rindex - offset)
8a0f6d1f
SL
2174 return -EBADMSG;
2175
f5430a3e
LP
2176 r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
2177 &rr->rrsig.signature, &rr->rrsig.signature_size,
2178 NULL);
f1d178cc 2179
e18a3c73 2180 if (rr->rrsig.signature_size <= 0)
f1d178cc
TG
2181 /* the accepted size depends on the algorithm, but for now
2182 just ensure that the value is greater than zero */
e18a3c73 2183 return -EBADMSG;
f1d178cc 2184
151226ab
ZJS
2185 break;
2186
d84e543d
DM
2187 case DNS_TYPE_NSEC: {
2188
2189 /*
5238e957 2190 * RFC6762, section 18.14 explicitly states mDNS should use name compression.
d84e543d
DM
2191 * This contradicts RFC3845, section 2.1.1
2192 */
2193
2194 bool allow_compressed = p->protocol == DNS_PROTOCOL_MDNS;
2195
2196 r = dns_packet_read_name(p, &rr->nsec.next_domain_name, allow_compressed, NULL);
50f1e641 2197 if (r < 0)
e18a3c73 2198 return r;
50f1e641 2199
370999c0
YW
2200 if (rdlength < p->rindex - offset)
2201 return -EBADMSG;
2202
89492aaf 2203 r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
89492aaf 2204
09eaf68c
TG
2205 /* We accept empty NSEC bitmaps. The bit indicating the presence of the NSEC record itself
2206 * is redundant and in e.g., RFC4956 this fact is used to define a use for NSEC records
2207 * without the NSEC bit set. */
50f1e641
TG
2208
2209 break;
d84e543d 2210 }
5d45a880
TG
2211 case DNS_TYPE_NSEC3: {
2212 uint8_t size;
2213
2214 r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
2215 if (r < 0)
e18a3c73 2216 return r;
5d45a880
TG
2217
2218 r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
2219 if (r < 0)
e18a3c73 2220 return r;
5d45a880
TG
2221
2222 r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
2223 if (r < 0)
e18a3c73 2224 return r;
5d45a880 2225
f1d178cc 2226 /* this may be zero */
5d45a880
TG
2227 r = dns_packet_read_uint8(p, &size, NULL);
2228 if (r < 0)
e18a3c73 2229 return r;
5d45a880 2230
f5430a3e 2231 r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
5d45a880 2232 if (r < 0)
e18a3c73 2233 return r;
5d45a880 2234
5d45a880
TG
2235 r = dns_packet_read_uint8(p, &size, NULL);
2236 if (r < 0)
e18a3c73 2237 return r;
5d45a880 2238
e18a3c73
ZJS
2239 if (size <= 0)
2240 return -EBADMSG;
f1d178cc 2241
e18a3c73
ZJS
2242 r = dns_packet_read_memdup(p, size,
2243 &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size,
2244 NULL);
5d45a880 2245 if (r < 0)
e18a3c73 2246 return r;
5d45a880 2247
370999c0
YW
2248 if (rdlength < p->rindex - offset)
2249 return -EBADMSG;
2250
6b9308d1 2251 r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL);
5d45a880 2252
0bbd72b2
TG
2253 /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
2254
5d45a880
TG
2255 break;
2256 }
d75acfb0 2257
48d45d2b
ZJS
2258 case DNS_TYPE_TLSA:
2259 r = dns_packet_read_uint8(p, &rr->tlsa.cert_usage, NULL);
2260 if (r < 0)
e18a3c73 2261 return r;
48d45d2b
ZJS
2262
2263 r = dns_packet_read_uint8(p, &rr->tlsa.selector, NULL);
2264 if (r < 0)
e18a3c73 2265 return r;
48d45d2b
ZJS
2266
2267 r = dns_packet_read_uint8(p, &rr->tlsa.matching_type, NULL);
2268 if (r < 0)
e18a3c73 2269 return r;
48d45d2b 2270
8a0f6d1f
SL
2271 if (rdlength < 3)
2272 return -EBADMSG;
2273
48d45d2b
ZJS
2274 r = dns_packet_read_memdup(p, rdlength - 3,
2275 &rr->tlsa.data, &rr->tlsa.data_size,
2276 NULL);
e18a3c73
ZJS
2277
2278 if (rr->tlsa.data_size <= 0)
48d45d2b
ZJS
2279 /* the accepted size depends on the algorithm, but for now
2280 just ensure that the value is greater than zero */
e18a3c73 2281 return -EBADMSG;
48d45d2b
ZJS
2282
2283 break;
2284
e7634d6b
RP
2285 case DNS_TYPE_SVCB:
2286 case DNS_TYPE_HTTPS:
2287 r = dns_packet_read_uint16(p, &rr->svcb.priority, NULL);
2288 if (r < 0)
2289 return r;
2290
2291 r = dns_packet_read_name(p, &rr->svcb.target_name, false /* uncompressed */, NULL);
2292 if (r < 0)
2293 return r;
2294
2295 DnsSvcParam *last = NULL;
2296 while (p->rindex - offset < rdlength) {
2297 _cleanup_free_ DnsSvcParam *i = NULL;
2298 uint16_t svc_param_key;
2299 uint16_t sz;
2300
2301 r = dns_packet_read_uint16(p, &svc_param_key, NULL);
2302 if (r < 0)
2303 return r;
2304 /* RFC 9460, section 2.2 says we must consider an RR malformed if SvcParamKeys are
2305 * not in strictly increasing order */
2306 if (last && last->key >= svc_param_key)
2307 return -EBADMSG;
2308
2309 r = dns_packet_read_uint16(p, &sz, NULL);
2310 if (r < 0)
2311 return r;
2312
2313 i = malloc0(offsetof(DnsSvcParam, value) + sz);
2314 if (!i)
2315 return -ENOMEM;
2316
2317 i->key = svc_param_key;
2318 i->length = sz;
2319 r = dns_packet_read_blob(p, &i->value, sz, NULL);
2320 if (r < 0)
2321 return r;
2322 if (!dns_svc_param_is_valid(i))
2323 return -EBADMSG;
2324
2325 LIST_INSERT_AFTER(params, rr->svcb.params, last, i);
2326 last = TAKE_PTR(i);
2327 }
2328
2329 break;
2330
95052df3
ZJS
2331 case DNS_TYPE_CAA:
2332 r = dns_packet_read_uint8(p, &rr->caa.flags, NULL);
2333 if (r < 0)
2334 return r;
2335
2336 r = dns_packet_read_string(p, &rr->caa.tag, NULL);
2337 if (r < 0)
2338 return r;
2339
370999c0 2340 if (rdlength < p->rindex - offset)
8a0f6d1f
SL
2341 return -EBADMSG;
2342
95052df3
ZJS
2343 r = dns_packet_read_memdup(p,
2344 rdlength + offset - p->rindex,
2345 &rr->caa.value, &rr->caa.value_size, NULL);
48d45d2b
ZJS
2346
2347 break;
2348
17615676
LP
2349 case DNS_TYPE_NAPTR:
2350 r = dns_packet_read_uint16(p, &rr->naptr.order, NULL);
2351 if (r < 0)
2352 return r;
2353
2354 r = dns_packet_read_uint16(p, &rr->naptr.preference, NULL);
2355 if (r < 0)
2356 return r;
2357
2358 r = dns_packet_read_string(p, &rr->naptr.flags, NULL);
2359 if (r < 0)
2360 return r;
2361
2362 r = dns_packet_read_string(p, &rr->naptr.services, NULL);
2363 if (r < 0)
2364 return r;
2365
2366 r = dns_packet_read_string(p, &rr->naptr.regexp, NULL);
2367 if (r < 0)
2368 return r;
2369
160159a7 2370 r = dns_packet_read_name(p, &rr->naptr.replacement, /* allow_compression= */ false, NULL);
17615676
LP
2371 break;
2372
d75acfb0 2373 case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */
d93a16b8 2374 case DNS_TYPE_OPENPGPKEY:
74b2466e 2375 default:
52e085af 2376 unparsable:
a43a068a 2377 r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.data_size, NULL);
74b2466e
LP
2378 }
2379 if (r < 0)
e18a3c73 2380 return r;
370999c0 2381 if (p->rindex - offset != rdlength)
e18a3c73 2382 return -EBADMSG;
74b2466e 2383
81b4d94d
LP
2384 if (ret)
2385 *ret = TAKE_PTR(rr);
d2579eec
LP
2386 if (ret_cache_flush)
2387 *ret_cache_flush = cache_flush;
81b4d94d
LP
2388 if (ret_start)
2389 *ret_start = rewinder.saved_rindex;
74b2466e 2390
81b4d94d 2391 CANCEL_REWINDER(rewinder);
74b2466e 2392 return 0;
74b2466e
LP
2393}
2394
c3f7000e
LP
2395static bool opt_is_good(DnsResourceRecord *rr, bool *rfc6975) {
2396 const uint8_t* p;
2397 bool found_dau_dhu_n3u = false;
2398 size_t l;
2399
2400 /* Checks whether the specified OPT RR is well-formed and whether it contains RFC6975 data (which is not OK in
2401 * a reply). */
2402
2403 assert(rr);
2404 assert(rr->key->type == DNS_TYPE_OPT);
2405
2406 /* Check that the version is 0 */
b30bf55d
LP
2407 if (((rr->ttl >> 16) & UINT32_C(0xFF)) != 0) {
2408 *rfc6975 = false;
2409 return true; /* if it's not version 0, it's OK, but we will ignore the OPT field contents */
2410 }
c3f7000e
LP
2411
2412 p = rr->opt.data;
a43a068a 2413 l = rr->opt.data_size;
c3f7000e
LP
2414 while (l > 0) {
2415 uint16_t option_code, option_length;
2416
2417 /* At least four bytes for OPTION-CODE and OPTION-LENGTH are required */
2418 if (l < 4U)
2419 return false;
2420
2421 option_code = unaligned_read_be16(p);
2422 option_length = unaligned_read_be16(p + 2);
2423
2424 if (l < option_length + 4U)
2425 return false;
2426
2427 /* RFC 6975 DAU, DHU or N3U fields found. */
980cb160 2428 if (IN_SET(option_code, DNS_EDNS_OPT_DAU, DNS_EDNS_OPT_DHU, DNS_EDNS_OPT_N3U))
c3f7000e
LP
2429 found_dau_dhu_n3u = true;
2430
2431 p += option_length + 4U;
2432 l -= option_length + 4U;
2433 }
2434
2435 *rfc6975 = found_dau_dhu_n3u;
2436 return true;
2437}
2438
4a49e560 2439static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question) {
faa133f3 2440 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
64ea42e9 2441 unsigned n;
74b2466e
LP
2442 int r;
2443
3cb10d3a 2444 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
2445 if (n > 0) {
2446 question = dns_question_new(n);
e18a3c73
ZJS
2447 if (!question)
2448 return -ENOMEM;
74b2466e 2449
2d34cf0c
ZJS
2450 _cleanup_set_free_ Set *keys = NULL; /* references to keys are kept by Question */
2451
2452 keys = set_new(&dns_resource_key_hash_ops);
2453 if (!keys)
2454 return log_oom();
2455
2456 r = set_reserve(keys, n * 2); /* Higher multipliers give slightly higher efficiency through
e9665ac2 2457 * hash collisions, but the gains quickly drop off after 2. */
2d34cf0c
ZJS
2458 if (r < 0)
2459 return r;
2460
64ea42e9 2461 for (unsigned i = 0; i < n; i++) {
faa133f3 2462 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
82d39576 2463 bool qu;
74b2466e 2464
82d39576 2465 r = dns_packet_read_key(p, &key, &qu, NULL);
faa133f3 2466 if (r < 0)
e18a3c73 2467 return r;
74b2466e 2468
e18a3c73
ZJS
2469 if (!dns_type_is_valid_query(key->type))
2470 return -EBADMSG;
c463eb78 2471
2d34cf0c
ZJS
2472 r = set_put(keys, key);
2473 if (r < 0)
2474 return r;
2475 if (r == 0)
2476 /* Already in the Question, let's skip */
2477 continue;
2478
82d39576 2479 r = dns_question_add_raw(question, key, qu ? DNS_QUESTION_WANTS_UNICAST_REPLY : 0);
faa133f3 2480 if (r < 0)
e18a3c73 2481 return r;
faa133f3
LP
2482 }
2483 }
322345fd 2484
1cc6c93a
YW
2485 *ret_question = TAKE_PTR(question);
2486
4a49e560
ZJS
2487 return 0;
2488}
2489
2490static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
2491 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
64ea42e9 2492 unsigned n;
4a49e560
ZJS
2493 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *previous = NULL;
2494 bool bad_opt = false;
2495 int r;
2496
faa133f3 2497 n = DNS_PACKET_RRCOUNT(p);
4a49e560
ZJS
2498 if (n == 0)
2499 return 0;
c3f7000e 2500
4a49e560
ZJS
2501 answer = dns_answer_new(n);
2502 if (!answer)
2503 return -ENOMEM;
322345fd 2504
64ea42e9 2505 for (unsigned i = 0; i < n; i++) {
4a49e560
ZJS
2506 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
2507 bool cache_flush = false;
93748b26 2508 size_t start;
322345fd 2509
729c5deb 2510 if (p->rindex == p->size && p->opt) {
18674159
LP
2511 /* If we reached the end of the packet already, but there are still more RRs
2512 * declared, then that's a corrupt packet. Let's accept the packet anyway, since it's
2513 * apparently a common bug in routers. Let's however suppress OPT support in this
2514 * case, so that we force the rest of the logic into lowest DNS baseline support. Or
2515 * to say this differently: if the DNS server doesn't even get the RR counts right,
2516 * it's highly unlikely it gets EDNS right. */
2517 log_debug("More resource records declared in packet than included, suppressing OPT.");
2518 bad_opt = true;
2519 break;
2520 }
2521
93748b26 2522 r = dns_packet_read_rr(p, &rr, &cache_flush, &start);
4a49e560
ZJS
2523 if (r < 0)
2524 return r;
322345fd 2525
4a49e560
ZJS
2526 /* Try to reduce memory usage a bit */
2527 if (previous)
2528 dns_resource_key_reduce(&rr->key, &previous->key);
f57e3cd5 2529
4a49e560
ZJS
2530 if (rr->key->type == DNS_TYPE_OPT) {
2531 bool has_rfc6975;
c3f7000e 2532
4a49e560
ZJS
2533 if (p->opt || bad_opt) {
2534 /* Multiple OPT RRs? if so, let's ignore all, because there's
2535 * something wrong with the server, and if one is valid we wouldn't
2536 * know which one. */
2537 log_debug("Multiple OPT RRs detected, ignoring all.");
2538 bad_opt = true;
2539 continue;
2540 }
e6b57b37 2541
4a49e560
ZJS
2542 if (!dns_name_is_root(dns_resource_key_name(rr->key))) {
2543 /* If the OPT RR is not owned by the root domain, then it is bad,
2544 * let's ignore it. */
2545 log_debug("OPT RR is not owned by root domain, ignoring.");
2546 bad_opt = true;
2547 continue;
2548 }
c3f7000e 2549
4a49e560
ZJS
2550 if (i < DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)) {
2551 /* OPT RR is in the wrong section? Some Belkin routers do this. This
2552 * is a hint the EDNS implementation is borked, like the Belkin one
2553 * is, hence ignore it. */
2554 log_debug("OPT RR in wrong section, ignoring.");
2555 bad_opt = true;
2556 continue;
2557 }
2558
2559 if (!opt_is_good(rr, &has_rfc6975)) {
2560 log_debug("Malformed OPT RR, ignoring.");
2561 bad_opt = true;
2562 continue;
2563 }
2564
2565 if (DNS_PACKET_QR(p)) {
2566 /* Additional checks for responses */
2567
d7a0f1f4 2568 if (!DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(rr))
4a49e560
ZJS
2569 /* If this is a reply and we don't know the EDNS version
2570 * then something is weird... */
d7a0f1f4
FS
2571 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
2572 "EDNS version newer that our request, bad server.");
ff7febd5 2573
4a49e560
ZJS
2574 if (has_rfc6975) {
2575 /* If the OPT RR contains RFC6975 algorithm data, then this
2576 * is indication that the server just copied the OPT it got
2577 * from us (which contained that data) back into the reply.
2578 * If so, then it doesn't properly support EDNS, as RFC6975
2579 * makes it very clear that the algorithm data should only
2580 * be contained in questions, never in replies. Crappy
2581 * Belkin routers copy the OPT data for example, hence let's
2582 * detect this so that we downgrade early. */
dffb8277 2583 log_debug("OPT RR contains RFC6975 data, ignoring.");
c3f7000e
LP
2584 bad_opt = true;
2585 continue;
2586 }
4a49e560 2587 }
e6b57b37 2588
4a49e560 2589 p->opt = dns_resource_record_ref(rr);
93748b26
LP
2590 p->opt_start = start;
2591 assert(p->rindex >= start);
2592 p->opt_size = p->rindex - start;
4a49e560 2593 } else {
fa4e74b8
LP
2594 DnsAnswerFlags flags = 0;
2595
8ec951e8
BP
2596 if (p->protocol == DNS_PROTOCOL_MDNS) {
2597 flags |= DNS_ANSWER_REFUSE_TTL_NO_MATCH;
2598 if (!cache_flush)
2599 flags |= DNS_ANSWER_SHARED_OWNER;
2600 }
fa4e74b8
LP
2601
2602 /* According to RFC 4795, section 2.9. only the RRs from the Answer section shall be
2603 * cached. Hence mark only those RRs as cacheable by default, but not the ones from
82af03c2
VCS
2604 * the Additional or Authority sections.
2605 * This restriction does not apply to mDNS records (RFC 6762). */
fa4e74b8
LP
2606 if (i < DNS_PACKET_ANCOUNT(p))
2607 flags |= DNS_ANSWER_CACHEABLE|DNS_ANSWER_SECTION_ANSWER;
2608 else if (i < DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p))
2609 flags |= DNS_ANSWER_SECTION_AUTHORITY;
82af03c2 2610 else {
fa4e74b8 2611 flags |= DNS_ANSWER_SECTION_ADDITIONAL;
82af03c2
VCS
2612 if (p->protocol == DNS_PROTOCOL_MDNS)
2613 flags |= DNS_ANSWER_CACHEABLE;
2614 }
4a49e560 2615
04617bf8 2616 r = dns_answer_add(answer, rr, p->ifindex, flags, NULL);
4a49e560
ZJS
2617 if (r < 0)
2618 return r;
2619 }
d75acfb0 2620
b87fbe5f 2621 /* Remember this RR, so that we can potentially merge its ->key object with the
4a49e560
ZJS
2622 * next RR. Note that we only do this if we actually decided to keep the RR around.
2623 */
7daeec3e 2624 DNS_RR_REPLACE(previous, dns_resource_record_ref(rr));
4a49e560 2625 }
105e1512 2626
18674159 2627 if (bad_opt) {
4a49e560 2628 p->opt = dns_resource_record_unref(p->opt);
18674159
LP
2629 p->opt_start = p->opt_size = SIZE_MAX;
2630 }
105e1512 2631
1cc6c93a
YW
2632 *ret_answer = TAKE_PTR(answer);
2633
4a49e560
ZJS
2634 return 0;
2635}
ebc8a106 2636
4a49e560 2637int dns_packet_extract(DnsPacket *p) {
0c4f37f0 2638 assert(p);
c3f7000e 2639
4a49e560
ZJS
2640 if (p->extracted)
2641 return 0;
2642
0c4f37f0
ZJS
2643 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2644 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
fc44acc0 2645 _unused_ _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = REWINDER_INIT(p);
0c4f37f0
ZJS
2646 int r;
2647
4a49e560
ZJS
2648 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
2649
2650 r = dns_packet_extract_question(p, &question);
2651 if (r < 0)
2652 return r;
2653
2654 r = dns_packet_extract_answer(p, &answer);
2655 if (r < 0)
2656 return r;
322345fd 2657
894c7b77
LP
2658 if (p->rindex < p->size) {
2659 log_debug("Trailing garbage in packet, suppressing OPT.");
2660 p->opt = dns_resource_record_unref(p->opt);
2661 p->opt_start = p->opt_size = SIZE_MAX;
2662 }
2663
1cc6c93a
YW
2664 p->question = TAKE_PTR(question);
2665 p->answer = TAKE_PTR(answer);
a4076574
LP
2666 p->extracted = true;
2667
e18a3c73
ZJS
2668 /* no CANCEL, always rewind */
2669 return 0;
322345fd
LP
2670}
2671
8af5b883
LP
2672int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
2673 int r;
2674
2675 assert(p);
2676 assert(key);
2677
2678 /* Checks if the specified packet is a reply for the specified
2679 * key and the specified key is the only one in the question
2680 * section. */
2681
2682 if (DNS_PACKET_QR(p) != 1)
2683 return 0;
2684
2685 /* Let's unpack the packet, if that hasn't happened yet. */
2686 r = dns_packet_extract(p);
2687 if (r < 0)
2688 return r;
2689
a924f43f
EV
2690 if (!p->question)
2691 return 0;
2692
8af5b883
LP
2693 if (p->question->n_keys != 1)
2694 return 0;
2695
ab715ddb 2696 return dns_resource_key_equal(dns_question_first_key(p->question), key);
8af5b883
LP
2697}
2698
93748b26
LP
2699int dns_packet_patch_max_udp_size(DnsPacket *p, uint16_t max_udp_size) {
2700 assert(p);
2701 assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
2702
f5fbe71d 2703 if (p->opt_start == SIZE_MAX) /* No OPT section, nothing to patch */
93748b26
LP
2704 return 0;
2705
f5fbe71d 2706 assert(p->opt_size != SIZE_MAX);
93748b26
LP
2707 assert(p->opt_size >= 5);
2708
2709 unaligned_write_be16(DNS_PACKET_DATA(p) + p->opt_start + 3, max_udp_size);
2710 return 1;
2711}
2712
81b4d94d 2713static int patch_rr(DnsPacket *p, usec_t age) {
0c4f37f0 2714 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = REWINDER_INIT(p);
81b4d94d
LP
2715 size_t ttl_index;
2716 uint32_t ttl;
2717 uint16_t type, rdlength;
2718 int r;
2719
0f1f933b 2720 /* Patches the RR at the current rindex, subtracts the specified time from the TTL */
81b4d94d
LP
2721
2722 r = dns_packet_read_name(p, NULL, true, NULL);
2723 if (r < 0)
2724 return r;
2725
2726 r = dns_packet_read_uint16(p, &type, NULL);
2727 if (r < 0)
2728 return r;
2729
2730 r = dns_packet_read_uint16(p, NULL, NULL);
2731 if (r < 0)
2732 return r;
2733
2734 r = dns_packet_read_uint32(p, &ttl, &ttl_index);
2735 if (r < 0)
2736 return r;
2737
2738 if (type != DNS_TYPE_OPT) { /* The TTL of the OPT field is not actually a TTL, skip it */
2739 ttl = LESS_BY(ttl * USEC_PER_SEC, age) / USEC_PER_SEC;
2740 unaligned_write_be32(DNS_PACKET_DATA(p) + ttl_index, ttl);
2741 }
2742
2743 r = dns_packet_read_uint16(p, &rdlength, NULL);
2744 if (r < 0)
2745 return r;
2746
2747 r = dns_packet_read(p, rdlength, NULL, NULL);
2748 if (r < 0)
2749 return r;
2750
2751 CANCEL_REWINDER(rewinder);
2752 return 0;
2753}
2754
2755int dns_packet_patch_ttls(DnsPacket *p, usec_t timestamp) {
81b4d94d
LP
2756 assert(p);
2757 assert(timestamp_is_set(timestamp));
2758
2759 /* Adjusts all TTLs in the packet by subtracting the time difference between now and the specified timestamp */
2760
fc44acc0 2761 _unused_ _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = REWINDER_INIT(p);
64ea42e9 2762 unsigned n;
0c4f37f0
ZJS
2763 usec_t k;
2764 int r;
2765
ba4e0427 2766 k = now(CLOCK_BOOTTIME);
81b4d94d
LP
2767 assert(k >= timestamp);
2768 k -= timestamp;
2769
81b4d94d
LP
2770 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
2771
2772 n = DNS_PACKET_QDCOUNT(p);
64ea42e9 2773 for (unsigned i = 0; i < n; i++) {
81b4d94d
LP
2774 r = dns_packet_read_key(p, NULL, NULL, NULL);
2775 if (r < 0)
2776 return r;
2777 }
2778
2779 n = DNS_PACKET_RRCOUNT(p);
64ea42e9 2780 for (unsigned i = 0; i < n; i++) {
81b4d94d
LP
2781
2782 /* DNS servers suck, hence the RR count is in many servers off. If we reached the end
2783 * prematurely, accept that, exit early */
2784 if (p->rindex == p->size)
2785 break;
2786
2787 r = patch_rr(p, k);
2788 if (r < 0)
2789 return r;
2790 }
2791
2792 return 0;
2793}
2794
7a08d314 2795static void dns_packet_hash_func(const DnsPacket *s, struct siphash *state) {
98767d75
IT
2796 assert(s);
2797
c01a5c05 2798 siphash24_compress_typesafe(s->size, state);
98767d75
IT
2799 siphash24_compress(DNS_PACKET_DATA((DnsPacket*) s), s->size, state);
2800}
2801
7a08d314 2802static int dns_packet_compare_func(const DnsPacket *x, const DnsPacket *y) {
a0edd02e 2803 int r;
98767d75 2804
a0edd02e
FB
2805 r = CMP(x->size, y->size);
2806 if (r != 0)
2807 return r;
98767d75
IT
2808
2809 return memcmp(DNS_PACKET_DATA((DnsPacket*) x), DNS_PACKET_DATA((DnsPacket*) y), x->size);
2810}
2811
7a08d314 2812DEFINE_HASH_OPS(dns_packet_hash_ops, DnsPacket, dns_packet_hash_func, dns_packet_compare_func);
98767d75 2813
a9fd8837
LP
2814bool dns_packet_equal(const DnsPacket *a, const DnsPacket *b) {
2815 return dns_packet_compare_func(a, b) == 0;
2816}
2817
71682ac6 2818int dns_packet_ede_rcode(DnsPacket *p, int *ret_ede_rcode, char **ret_ede_msg) {
ac684446
RP
2819 const uint8_t *d;
2820 size_t l;
71682ac6
YW
2821 int r;
2822
2823 assert(p);
ac684446
RP
2824
2825 if (!p->opt)
71682ac6 2826 return -ENOENT;
ac684446
RP
2827
2828 d = p->opt->opt.data;
2829 l = p->opt->opt.data_size;
2830
2831 while (l > 0) {
2832 uint16_t code, length;
2833
2834 if (l < 4U)
2835 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
2836 "EDNS0 variable part has invalid size.");
2837
2838 code = unaligned_read_be16(d);
2839 length = unaligned_read_be16(d + 2);
2840
2841 if (l < 4U + length)
2842 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
2843 "Truncated option in EDNS0 variable part.");
2844
2845 if (code == DNS_EDNS_OPT_EXT_ERROR) {
71682ac6
YW
2846 _cleanup_free_ char *msg = NULL;
2847
ac684446
RP
2848 if (length < 2U)
2849 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
71682ac6
YW
2850 "EDNS0 truncated EDE info code.");
2851
2852 r = make_cstring((char *) d + 6, length - 2U, MAKE_CSTRING_ALLOW_TRAILING_NUL, &msg);
ac684446 2853 if (r < 0)
71682ac6
YW
2854 return log_debug_errno(r, "Invalid EDE text in opt.");
2855
2856 if (ret_ede_msg) {
2857 if (!utf8_is_valid(msg)) {
2858 _cleanup_free_ char *msg_escaped = NULL;
2859
2860 msg_escaped = cescape(msg);
2861 if (!msg_escaped)
2862 return log_oom_debug();
2863
2864 *ret_ede_msg = TAKE_PTR(msg_escaped);
2865 } else
2866 *ret_ede_msg = TAKE_PTR(msg);
ac684446 2867 }
71682ac6
YW
2868
2869 if (ret_ede_rcode)
2870 *ret_ede_rcode = unaligned_read_be16(d + 4);
2871
2872 return 0;
ac684446
RP
2873 }
2874
2875 d += 4U + length;
2876 l -= 4U + length;
2877 }
2878
71682ac6 2879 return -ENOENT;
ac684446
RP
2880}
2881
2882bool dns_ede_rcode_is_dnssec(int ede_rcode) {
2883 return IN_SET(ede_rcode,
2884 DNS_EDE_RCODE_UNSUPPORTED_DNSKEY_ALG,
2885 DNS_EDE_RCODE_UNSUPPORTED_DS_DIGEST,
2886 DNS_EDE_RCODE_DNSSEC_INDETERMINATE,
2887 DNS_EDE_RCODE_DNSSEC_BOGUS,
2888 DNS_EDE_RCODE_SIG_EXPIRED,
2889 DNS_EDE_RCODE_SIG_NOT_YET_VALID,
2890 DNS_EDE_RCODE_DNSKEY_MISSING,
2891 DNS_EDE_RCODE_RRSIG_MISSING,
2892 DNS_EDE_RCODE_NO_ZONE_KEY_BIT,
2893 DNS_EDE_RCODE_NSEC_MISSING
2894 );
2895}
2896
4a6eb824
LP
2897int dns_packet_has_nsid_request(DnsPacket *p) {
2898 bool has_nsid = false;
2899 const uint8_t *d;
2900 size_t l;
2901
2902 assert(p);
2903
2904 if (!p->opt)
2905 return false;
2906
2907 d = p->opt->opt.data;
2908 l = p->opt->opt.data_size;
2909
2910 while (l > 0) {
2911 uint16_t code, length;
2912
2913 if (l < 4U)
2914 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
2915 "EDNS0 variable part has invalid size.");
2916
2917 code = unaligned_read_be16(d);
2918 length = unaligned_read_be16(d + 2);
2919
2920 if (l < 4U + length)
2921 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
2922 "Truncated option in EDNS0 variable part.");
2923
980cb160 2924 if (code == DNS_EDNS_OPT_NSID) {
4a6eb824
LP
2925 if (has_nsid)
2926 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
2927 "Duplicate NSID option in EDNS0 variable part.");
2928
2929 if (length != 0)
2930 return log_debug_errno(SYNTHETIC_ERRNO(EBADMSG),
2931 "Non-empty NSID option in DNS request.");
2932
2933 has_nsid = true;
2934 }
2935
2936 d += 4U + length;
2937 l -= 4U + length;
2938 }
2939
2940 return has_nsid;
2941}
2942
acbf761b
LP
2943size_t dns_packet_size_unfragmented(DnsPacket *p) {
2944 assert(p);
2945
2946 if (p->fragsize == 0) /* Wasn't fragmented */
2947 return p->size;
2948
2949 /* The fragment size (p->fragsize) covers the whole (fragmented) IP packet, while the regular packet
2950 * size (p->size) only covers the DNS part. Thus, subtract the UDP header from the largest fragment
2951 * size, in order to determine which size of DNS packet would have gone through without
2952 * fragmenting. */
2953
2954 return LESS_BY(p->fragsize, udp_header_size(p->family));
2955}
2956
ee2108dc
RP
2957static const char* const dns_svc_param_key_table[_DNS_SVC_PARAM_KEY_MAX_DEFINED] = {
2958 [DNS_SVC_PARAM_KEY_MANDATORY] = "mandatory",
2959 [DNS_SVC_PARAM_KEY_ALPN] = "alpn",
2960 [DNS_SVC_PARAM_KEY_NO_DEFAULT_ALPN] = "no-default-alpn",
2961 [DNS_SVC_PARAM_KEY_PORT] = "port",
2962 [DNS_SVC_PARAM_KEY_IPV4HINT] = "ipv4hint",
2963 [DNS_SVC_PARAM_KEY_ECH] = "ech",
2964 [DNS_SVC_PARAM_KEY_IPV6HINT] = "ipv6hint",
2965 [DNS_SVC_PARAM_KEY_DOHPATH] = "dohpath",
2966 [DNS_SVC_PARAM_KEY_OHTTP] = "ohttp",
2967};
2968DEFINE_STRING_TABLE_LOOKUP_TO_STRING(dns_svc_param_key, int);
2969
2970const char* format_dns_svc_param_key(uint16_t i, char buf[static DECIMAL_STR_MAX(uint16_t)+3]) {
2971 const char *p = dns_svc_param_key_to_string(i);
2972 if (p)
2973 return p;
2974
2975 return snprintf_ok(buf, DECIMAL_STR_MAX(uint16_t)+3, "key%i", i);
2976}
2977
74b2466e 2978static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
e3e64a1a
ZJS
2979 [DNS_RCODE_SUCCESS] = "SUCCESS",
2980 [DNS_RCODE_FORMERR] = "FORMERR",
2981 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
2982 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
2983 [DNS_RCODE_NOTIMP] = "NOTIMP",
2984 [DNS_RCODE_REFUSED] = "REFUSED",
2985 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
2986 [DNS_RCODE_YXRRSET] = "YRRSET",
2987 [DNS_RCODE_NXRRSET] = "NXRRSET",
2988 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
2989 [DNS_RCODE_NOTZONE] = "NOTZONE",
a92ea352 2990 [DNS_RCODE_DSOTYPENI] = "DSOTYPENI",
e3e64a1a
ZJS
2991 [DNS_RCODE_BADVERS] = "BADVERS",
2992 [DNS_RCODE_BADKEY] = "BADKEY",
2993 [DNS_RCODE_BADTIME] = "BADTIME",
2994 [DNS_RCODE_BADMODE] = "BADMODE",
2995 [DNS_RCODE_BADNAME] = "BADNAME",
2996 [DNS_RCODE_BADALG] = "BADALG",
2997 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
6f21e066 2998 [DNS_RCODE_BADCOOKIE] = "BADCOOKIE",
74b2466e
LP
2999};
3000DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc 3001
bfd5a068 3002const char* format_dns_rcode(int i, char buf[static DECIMAL_STR_MAX(int)]) {
0d609349
YW
3003 const char *p = dns_rcode_to_string(i);
3004 if (p)
3005 return p;
3006
3007 return snprintf_ok(buf, DECIMAL_STR_MAX(int), "%i", i);
3008}
3009
056db786
RP
3010static const char* const dns_ede_rcode_table[_DNS_EDE_RCODE_MAX_DEFINED] = {
3011 [DNS_EDE_RCODE_OTHER] = "Other",
3012 [DNS_EDE_RCODE_UNSUPPORTED_DNSKEY_ALG] = "Unsupported DNSKEY Algorithm",
3013 [DNS_EDE_RCODE_UNSUPPORTED_DS_DIGEST] = "Unsupported DS Digest Type",
3014 [DNS_EDE_RCODE_STALE_ANSWER] = "Stale Answer",
3015 [DNS_EDE_RCODE_FORGED_ANSWER] = "Forged Answer",
3016 [DNS_EDE_RCODE_DNSSEC_INDETERMINATE] = "DNSSEC Indeterminate",
3017 [DNS_EDE_RCODE_DNSSEC_BOGUS] = "DNSSEC Bogus",
3018 [DNS_EDE_RCODE_SIG_EXPIRED] = "Signature Expired",
3019 [DNS_EDE_RCODE_SIG_NOT_YET_VALID] = "Signature Not Yet Valid",
3020 [DNS_EDE_RCODE_DNSKEY_MISSING] = "DNSKEY Missing",
3021 [DNS_EDE_RCODE_RRSIG_MISSING] = "RRSIG Missing",
3022 [DNS_EDE_RCODE_NO_ZONE_KEY_BIT] = "No Zone Key Bit Set",
3023 [DNS_EDE_RCODE_NSEC_MISSING] = "NSEC Missing",
3024 [DNS_EDE_RCODE_CACHED_ERROR] = "Cached Error",
3025 [DNS_EDE_RCODE_NOT_READY] = "Not Ready",
3026 [DNS_EDE_RCODE_BLOCKED] = "Blocked",
3027 [DNS_EDE_RCODE_CENSORED] = "Censored",
3028 [DNS_EDE_RCODE_FILTERED] = "Filtered",
9379b23b 3029 [DNS_EDE_RCODE_PROHIBITED] = "Prohibited",
056db786
RP
3030 [DNS_EDE_RCODE_STALE_NXDOMAIN_ANSWER] = "Stale NXDOMAIN Answer",
3031 [DNS_EDE_RCODE_NOT_AUTHORITATIVE] = "Not Authoritative",
3032 [DNS_EDE_RCODE_NOT_SUPPORTED] = "Not Supported",
3033 [DNS_EDE_RCODE_UNREACH_AUTHORITY] = "No Reachable Authority",
3034 [DNS_EDE_RCODE_NET_ERROR] = "Network Error",
3035 [DNS_EDE_RCODE_INVALID_DATA] = "Invalid Data",
3036 [DNS_EDE_RCODE_SIG_NEVER] = "Signature Never Valid",
3037 [DNS_EDE_RCODE_TOO_EARLY] = "Too Early",
3038 [DNS_EDE_RCODE_UNSUPPORTED_NSEC3_ITER] = "Unsupported NSEC3 Iterations",
3039 [DNS_EDE_RCODE_TRANSPORT_POLICY] = "Impossible Transport Policy",
3040 [DNS_EDE_RCODE_SYNTHESIZED] = "Synthesized",
3041};
ac684446 3042DEFINE_STRING_TABLE_LOOKUP_TO_STRING(dns_ede_rcode, int);
056db786 3043
bfd5a068 3044const char* format_dns_ede_rcode(int i, char buf[static DECIMAL_STR_MAX(int)]) {
056db786
RP
3045 const char *p = dns_ede_rcode_to_string(i);
3046 if (p)
3047 return p;
3048
3049 return snprintf_ok(buf, DECIMAL_STR_MAX(int), "%i", i);
3050}
3051
1716f6dc 3052static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
e3e64a1a
ZJS
3053 [DNS_PROTOCOL_DNS] = "dns",
3054 [DNS_PROTOCOL_MDNS] = "mdns",
1716f6dc
LP
3055 [DNS_PROTOCOL_LLMNR] = "llmnr",
3056};
3057DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);