]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
resolve: split the RR comparison function in two
[thirdparty/systemd.git] / src / resolve / resolved-dns-packet.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
74b2466e 2
73a4cd17
MCO
3#if HAVE_GCRYPT
4#include <gcrypt.h>
5#endif
6
b5efdb8a 7#include "alloc-util.h"
4ad7f276 8#include "dns-domain.h"
74b2466e 9#include "resolved-dns-packet.h"
2d34cf0c 10#include "set.h"
8b43440b
LP
11#include "string-table.h"
12#include "strv.h"
13#include "unaligned.h"
14#include "utf8.h"
15#include "util.h"
74b2466e 16
7586f4d1
TG
17#define EDNS0_OPT_DO (1<<15)
18
46a58596 19assert_cc(DNS_PACKET_SIZE_START > DNS_PACKET_HEADER_SIZE)
88795538 20
e18a3c73
ZJS
21typedef struct DnsPacketRewinder {
22 DnsPacket *packet;
23 size_t saved_rindex;
24} DnsPacketRewinder;
25
26static void rewind_dns_packet(DnsPacketRewinder *rewinder) {
27 if (rewinder->packet)
28 dns_packet_rewind(rewinder->packet, rewinder->saved_rindex);
29}
30
9ed794a3
VC
31#define INIT_REWINDER(rewinder, p) do { rewinder.packet = p; rewinder.saved_rindex = p->rindex; } while (0)
32#define CANCEL_REWINDER(rewinder) do { rewinder.packet = NULL; } while (0)
e18a3c73 33
51027656
LP
34int dns_packet_new(
35 DnsPacket **ret,
36 DnsProtocol protocol,
37 size_t min_alloc_dsize,
38 size_t max_size) {
39
74b2466e
LP
40 DnsPacket *p;
41 size_t a;
42
43 assert(ret);
51027656
LP
44 assert(max_size >= DNS_PACKET_HEADER_SIZE);
45
46 if (max_size > DNS_PACKET_SIZE_MAX)
47 max_size = DNS_PACKET_SIZE_MAX;
74b2466e 48
46a58596
BR
49 /* The caller may not check what is going to be truly allocated, so do not allow to
50 * allocate a DNS packet bigger than DNS_PACKET_SIZE_MAX.
51 */
baaa35ad
ZJS
52 if (min_alloc_dsize > DNS_PACKET_SIZE_MAX)
53 return log_error_errno(SYNTHETIC_ERRNO(EFBIG),
54 "Requested packet data size too big: %zu",
55 min_alloc_dsize);
46a58596
BR
56
57 /* When dns_packet_new() is called with min_alloc_dsize == 0, allocate more than the
88795538
ZJS
58 * absolute minimum (which is the dns packet header size), to avoid
59 * resizing immediately again after appending the first data to the packet.
60 */
46a58596 61 if (min_alloc_dsize < DNS_PACKET_HEADER_SIZE)
88795538
ZJS
62 a = DNS_PACKET_SIZE_START;
63 else
46a58596 64 a = min_alloc_dsize;
74b2466e 65
c73ce96b
LP
66 /* round up to next page size */
67 a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
68
69 /* make sure we never allocate more than useful */
51027656
LP
70 if (a > max_size)
71 a = max_size;
c73ce96b 72
74b2466e
LP
73 p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
74 if (!p)
75 return -ENOMEM;
76
77 p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
78 p->allocated = a;
51027656 79 p->max_size = max_size;
1716f6dc 80 p->protocol = protocol;
519ef046 81 p->opt_start = p->opt_size = (size_t) -1;
74b2466e
LP
82 p->n_ref = 1;
83
84 *ret = p;
85
86 return 0;
87}
88
dbfbb6e7 89void dns_packet_set_flags(DnsPacket *p, bool dnssec_checking_disabled, bool truncated) {
74b2466e 90
dbfbb6e7 91 DnsPacketHeader *h;
74b2466e 92
dbfbb6e7 93 assert(p);
74b2466e
LP
94
95 h = DNS_PACKET_HEADER(p);
1716f6dc 96
dbfbb6e7
DM
97 switch(p->protocol) {
98 case DNS_PROTOCOL_LLMNR:
99 assert(!truncated);
100
069360a6
LP
101 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
102 0 /* opcode */,
103 0 /* c */,
e5abebab 104 0 /* tc */,
069360a6
LP
105 0 /* t */,
106 0 /* ra */,
107 0 /* ad */,
108 0 /* cd */,
109 0 /* rcode */));
dbfbb6e7
DM
110 break;
111
112 case DNS_PROTOCOL_MDNS:
113 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
114 0 /* opcode */,
115 0 /* aa */,
116 truncated /* tc */,
117 0 /* rd (ask for recursion) */,
118 0 /* ra */,
119 0 /* ad */,
120 0 /* cd */,
121 0 /* rcode */));
122 break;
123
124 default:
125 assert(!truncated);
126
069360a6
LP
127 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
128 0 /* opcode */,
129 0 /* aa */,
130 0 /* tc */,
131 1 /* rd (ask for recursion) */,
132 0 /* ra */,
133 0 /* ad */,
24710c48 134 dnssec_checking_disabled /* cd */,
069360a6 135 0 /* rcode */));
dbfbb6e7
DM
136 }
137}
138
46a58596 139int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t min_alloc_dsize, bool dnssec_checking_disabled) {
dbfbb6e7
DM
140 DnsPacket *p;
141 int r;
142
143 assert(ret);
144
51027656 145 r = dns_packet_new(&p, protocol, min_alloc_dsize, DNS_PACKET_SIZE_MAX);
dbfbb6e7
DM
146 if (r < 0)
147 return r;
148
149 /* Always set the TC bit to 0 initially.
150 * If there are multiple packets later, we'll update the bit shortly before sending.
151 */
152 dns_packet_set_flags(p, dnssec_checking_disabled, false);
74b2466e
LP
153
154 *ret = p;
155 return 0;
156}
157
158DnsPacket *dns_packet_ref(DnsPacket *p) {
159
160 if (!p)
161 return NULL;
162
a8812dd7
LP
163 assert(!p->on_stack);
164
74b2466e
LP
165 assert(p->n_ref > 0);
166 p->n_ref++;
167 return p;
168}
169
170static void dns_packet_free(DnsPacket *p) {
171 char *s;
172
173 assert(p);
174
faa133f3
LP
175 dns_question_unref(p->question);
176 dns_answer_unref(p->answer);
d75acfb0 177 dns_resource_record_unref(p->opt);
322345fd 178
74b2466e
LP
179 while ((s = hashmap_steal_first_key(p->names)))
180 free(s);
181 hashmap_free(p->names);
182
faa133f3 183 free(p->_data);
a8812dd7
LP
184
185 if (!p->on_stack)
186 free(p);
74b2466e
LP
187}
188
189DnsPacket *dns_packet_unref(DnsPacket *p) {
190 if (!p)
191 return NULL;
192
193 assert(p->n_ref > 0);
194
6728a58d 195 dns_packet_unref(p->more);
9c491563 196
74b2466e
LP
197 if (p->n_ref == 1)
198 dns_packet_free(p);
199 else
200 p->n_ref--;
201
202 return NULL;
203}
204
205int dns_packet_validate(DnsPacket *p) {
206 assert(p);
207
208 if (p->size < DNS_PACKET_HEADER_SIZE)
209 return -EBADMSG;
210
c73ce96b
LP
211 if (p->size > DNS_PACKET_SIZE_MAX)
212 return -EBADMSG;
213
623a4c97 214 return 1;
74b2466e
LP
215}
216
217int dns_packet_validate_reply(DnsPacket *p) {
74b2466e
LP
218 int r;
219
220 assert(p);
221
222 r = dns_packet_validate(p);
223 if (r < 0)
224 return r;
225
623a4c97
LP
226 if (DNS_PACKET_QR(p) != 1)
227 return 0;
228
229 if (DNS_PACKET_OPCODE(p) != 0)
74b2466e
LP
230 return -EBADMSG;
231
818ef443 232 switch (p->protocol) {
d75acfb0 233
818ef443
DM
234 case DNS_PROTOCOL_LLMNR:
235 /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
236 if (DNS_PACKET_QDCOUNT(p) != 1)
237 return -EBADMSG;
238
239 break;
240
4e5bf5e1
DM
241 case DNS_PROTOCOL_MDNS:
242 /* RFC 6762, Section 18 */
243 if (DNS_PACKET_RCODE(p) != 0)
244 return -EBADMSG;
245
246 break;
247
818ef443
DM
248 default:
249 break;
250 }
ea917db9 251
623a4c97
LP
252 return 1;
253}
254
255int dns_packet_validate_query(DnsPacket *p) {
256 int r;
257
258 assert(p);
259
260 r = dns_packet_validate(p);
261 if (r < 0)
262 return r;
263
264 if (DNS_PACKET_QR(p) != 0)
265 return 0;
266
3cb10d3a 267 if (DNS_PACKET_OPCODE(p) != 0)
74b2466e
LP
268 return -EBADMSG;
269
623a4c97
LP
270 if (DNS_PACKET_TC(p))
271 return -EBADMSG;
272
818ef443 273 switch (p->protocol) {
d75acfb0 274
818ef443 275 case DNS_PROTOCOL_LLMNR:
b30bf55d 276 case DNS_PROTOCOL_DNS:
818ef443
DM
277 /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
278 if (DNS_PACKET_QDCOUNT(p) != 1)
279 return -EBADMSG;
623a4c97 280
818ef443
DM
281 /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
282 if (DNS_PACKET_ANCOUNT(p) > 0)
283 return -EBADMSG;
623a4c97 284
818ef443
DM
285 /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
286 if (DNS_PACKET_NSCOUNT(p) > 0)
287 return -EBADMSG;
288
289 break;
290
4e5bf5e1
DM
291 case DNS_PROTOCOL_MDNS:
292 /* RFC 6762, Section 18 */
293 if (DNS_PACKET_AA(p) != 0 ||
294 DNS_PACKET_RD(p) != 0 ||
295 DNS_PACKET_RA(p) != 0 ||
296 DNS_PACKET_AD(p) != 0 ||
297 DNS_PACKET_CD(p) != 0 ||
298 DNS_PACKET_RCODE(p) != 0)
299 return -EBADMSG;
300
301 break;
302
818ef443
DM
303 default:
304 break;
305 }
623a4c97
LP
306
307 return 1;
74b2466e
LP
308}
309
310static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
311 assert(p);
312
c73ce96b 313 if (p->size + add > p->allocated) {
51027656 314 size_t a, ms;
c73ce96b
LP
315
316 a = PAGE_ALIGN((p->size + add) * 2);
51027656
LP
317
318 ms = dns_packet_size_max(p);
319 if (a > ms)
320 a = ms;
c73ce96b
LP
321
322 if (p->size + add > a)
323 return -EMSGSIZE;
324
faa133f3 325 if (p->_data) {
c73ce96b
LP
326 void *d;
327
faa133f3 328 d = realloc(p->_data, a);
c73ce96b
LP
329 if (!d)
330 return -ENOMEM;
331
faa133f3 332 p->_data = d;
c73ce96b 333 } else {
faa133f3
LP
334 p->_data = malloc(a);
335 if (!p->_data)
c73ce96b
LP
336 return -ENOMEM;
337
faa133f3
LP
338 memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
339 memzero((uint8_t*) p->_data + p->size, a - p->size);
c73ce96b
LP
340 }
341
342 p->allocated = a;
343 }
74b2466e
LP
344
345 if (start)
346 *start = p->size;
347
348 if (ret)
349 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
350
351 p->size += add;
352 return 0;
353}
354
9c5e12a4 355void dns_packet_truncate(DnsPacket *p, size_t sz) {
74b2466e
LP
356 Iterator i;
357 char *s;
358 void *n;
359
360 assert(p);
361
362 if (p->size <= sz)
363 return;
364
0e03ade5 365 HASHMAP_FOREACH_KEY(n, s, p->names, i) {
74b2466e
LP
366
367 if (PTR_TO_SIZE(n) < sz)
368 continue;
369
370 hashmap_remove(p->names, s);
371 free(s);
372 }
373
374 p->size = sz;
375}
376
623a4c97
LP
377int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
378 void *q;
379 int r;
380
381 assert(p);
382
383 r = dns_packet_extend(p, l, &q, start);
384 if (r < 0)
385 return r;
386
1f66559c 387 memcpy_safe(q, d, l);
623a4c97
LP
388 return 0;
389}
390
74b2466e
LP
391int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
392 void *d;
393 int r;
394
395 assert(p);
396
397 r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
398 if (r < 0)
399 return r;
400
401 ((uint8_t*) d)[0] = v;
402
403 return 0;
404}
405
406int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
407 void *d;
408 int r;
409
410 assert(p);
411
412 r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
413 if (r < 0)
414 return r;
415
725ca0e5 416 unaligned_write_be16(d, v);
623a4c97
LP
417
418 return 0;
419}
420
421int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
422 void *d;
423 int r;
424
425 assert(p);
426
427 r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
428 if (r < 0)
429 return r;
430
725ca0e5 431 unaligned_write_be32(d, v);
74b2466e
LP
432
433 return 0;
434}
435
436int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
74b2466e
LP
437 assert(p);
438 assert(s);
439
c38a52da 440 return dns_packet_append_raw_string(p, s, strlen(s), start);
74b2466e
LP
441}
442
2001c805
LP
443int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start) {
444 void *d;
445 int r;
446
447 assert(p);
448 assert(s || size == 0);
449
450 if (size > 255)
451 return -E2BIG;
452
453 r = dns_packet_extend(p, 1 + size, &d, start);
454 if (r < 0)
455 return r;
456
457 ((uint8_t*) d)[0] = (uint8_t) size;
458
75f32f04 459 memcpy_safe(((uint8_t*) d) + 1, s, size);
2001c805
LP
460
461 return 0;
462}
463
a3db237b 464int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, bool canonical_candidate, size_t *start) {
a8812dd7 465 uint8_t *w;
74b2466e
LP
466 int r;
467
a3db237b
LP
468 /* Append a label to a packet. Optionally, does this in DNSSEC
469 * canonical form, if this label is marked as a candidate for
470 * it, and the canonical form logic is enabled for the
471 * packet */
472
74b2466e
LP
473 assert(p);
474 assert(d);
475
476 if (l > DNS_LABEL_MAX)
477 return -E2BIG;
478
a8812dd7 479 r = dns_packet_extend(p, 1 + l, (void**) &w, start);
74b2466e
LP
480 if (r < 0)
481 return r;
482
a8812dd7
LP
483 *(w++) = (uint8_t) l;
484
a3db237b 485 if (p->canonical_form && canonical_candidate) {
a8812dd7
LP
486 size_t i;
487
488 /* Generate in canonical form, as defined by DNSSEC
489 * RFC 4034, Section 6.2, i.e. all lower-case. */
490
b577e3d5
LP
491 for (i = 0; i < l; i++)
492 w[i] = (uint8_t) ascii_tolower(d[i]);
a8812dd7
LP
493 } else
494 /* Otherwise, just copy the string unaltered. This is
495 * essential for DNS-SD, where the casing of labels
496 * matters and needs to be retained. */
497 memcpy(w, d, l);
74b2466e
LP
498
499 return 0;
500}
501
f6a5fec6
LP
502int dns_packet_append_name(
503 DnsPacket *p,
504 const char *name,
505 bool allow_compression,
a3db237b 506 bool canonical_candidate,
f6a5fec6
LP
507 size_t *start) {
508
74b2466e
LP
509 size_t saved_size;
510 int r;
511
512 assert(p);
513 assert(name);
514
f6a5fec6
LP
515 if (p->refuse_compression)
516 allow_compression = false;
517
74b2466e
LP
518 saved_size = p->size;
519
e48b9a64 520 while (!dns_name_is_root(name)) {
08f904fd 521 const char *z = name;
74b2466e 522 char label[DNS_LABEL_MAX];
151226ab 523 size_t n = 0;
74b2466e 524
151226ab
ZJS
525 if (allow_compression)
526 n = PTR_TO_SIZE(hashmap_get(p->names, name));
74b2466e
LP
527 if (n > 0) {
528 assert(n < p->size);
529
530 if (n < 0x4000) {
531 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
532 if (r < 0)
533 goto fail;
534
535 goto done;
536 }
537 }
538
7470cc4c 539 r = dns_label_unescape(&name, label, sizeof label, 0);
74b2466e
LP
540 if (r < 0)
541 goto fail;
542
a3db237b 543 r = dns_packet_append_label(p, label, r, canonical_candidate, &n);
74b2466e
LP
544 if (r < 0)
545 goto fail;
546
151226ab 547 if (allow_compression) {
08f904fd
LP
548 _cleanup_free_ char *s = NULL;
549
550 s = strdup(z);
551 if (!s) {
552 r = -ENOMEM;
553 goto fail;
554 }
555
d5099efc 556 r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops);
151226ab
ZJS
557 if (r < 0)
558 goto fail;
74b2466e 559
151226ab
ZJS
560 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
561 if (r < 0)
562 goto fail;
74b2466e 563
151226ab
ZJS
564 s = NULL;
565 }
74b2466e
LP
566 }
567
568 r = dns_packet_append_uint8(p, 0, NULL);
569 if (r < 0)
570 return r;
571
572done:
573 if (start)
574 *start = saved_size;
575
576 return 0;
577
578fail:
579 dns_packet_truncate(p, saved_size);
580 return r;
581}
582
58ab31d5 583int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, const DnsAnswerFlags flags, size_t *start) {
74b2466e 584 size_t saved_size;
58ab31d5 585 uint16_t class;
74b2466e
LP
586 int r;
587
588 assert(p);
589 assert(k);
590
591 saved_size = p->size;
592
1c02e7ba 593 r = dns_packet_append_name(p, dns_resource_key_name(k), true, true, NULL);
74b2466e
LP
594 if (r < 0)
595 goto fail;
596
597 r = dns_packet_append_uint16(p, k->type, NULL);
598 if (r < 0)
599 goto fail;
600
58ab31d5
DR
601 class = flags & DNS_ANSWER_CACHE_FLUSH ? k->class | MDNS_RR_CACHE_FLUSH : k->class;
602 r = dns_packet_append_uint16(p, class, NULL);
74b2466e
LP
603 if (r < 0)
604 goto fail;
605
606 if (start)
607 *start = saved_size;
608
609 return 0;
610
611fail:
612 dns_packet_truncate(p, saved_size);
613 return r;
614}
615
e1a9f1a8 616static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, const uint8_t *types, size_t *start) {
50f1e641
TG
617 size_t saved_size;
618 int r;
619
620 assert(p);
621 assert(types);
1792f223 622 assert(length > 0);
50f1e641 623
50f1e641
TG
624 saved_size = p->size;
625
1792f223
TG
626 r = dns_packet_append_uint8(p, window, NULL);
627 if (r < 0)
628 goto fail;
50f1e641 629
1792f223
TG
630 r = dns_packet_append_uint8(p, length, NULL);
631 if (r < 0)
632 goto fail;
6fa91901 633
1792f223
TG
634 r = dns_packet_append_blob(p, types, length, NULL);
635 if (r < 0)
636 goto fail;
50f1e641
TG
637
638 if (start)
639 *start = saved_size;
640
641 return 0;
642fail:
643 dns_packet_truncate(p, saved_size);
644 return r;
645}
646
647static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
cb57dd41 648 Iterator i;
50f1e641 649 uint8_t window = 0;
1792f223 650 uint8_t entry = 0;
50f1e641
TG
651 uint8_t bitmaps[32] = {};
652 unsigned n;
653 size_t saved_size;
654 int r;
655
656 assert(p);
50f1e641
TG
657
658 saved_size = p->size;
659
cb57dd41 660 BITMAP_FOREACH(n, types, i) {
50f1e641
TG
661 assert(n <= 0xffff);
662
1792f223
TG
663 if ((n >> 8) != window && bitmaps[entry / 8] != 0) {
664 r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
50f1e641
TG
665 if (r < 0)
666 goto fail;
667
1792f223 668 zero(bitmaps);
50f1e641
TG
669 }
670
1792f223 671 window = n >> 8;
50f1e641
TG
672 entry = n & 255;
673
674 bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
675 }
676
d0ae14ff
LP
677 if (bitmaps[entry / 8] != 0) {
678 r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
679 if (r < 0)
680 goto fail;
681 }
50f1e641
TG
682
683 if (start)
684 *start = saved_size;
685
686 return 0;
687fail:
688 dns_packet_truncate(p, saved_size);
689 return r;
690}
691
dc913c9a 692/* Append the OPT pseudo-RR described in RFC6891 */
f2ed4c69 693int dns_packet_append_opt(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, int rcode, size_t *start) {
dc913c9a
TG
694 size_t saved_size;
695 int r;
696
697 assert(p);
698 /* we must never advertise supported packet size smaller than the legacy max */
699 assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
f2ed4c69
LP
700 assert(rcode >= 0);
701 assert(rcode <= _DNS_RCODE_MAX);
dc913c9a 702
519ef046
LP
703 if (p->opt_start != (size_t) -1)
704 return -EBUSY;
705
706 assert(p->opt_size == (size_t) -1);
707
dc913c9a
TG
708 saved_size = p->size;
709
710 /* empty name */
711 r = dns_packet_append_uint8(p, 0, NULL);
712 if (r < 0)
713 return r;
714
715 /* type */
716 r = dns_packet_append_uint16(p, DNS_TYPE_OPT, NULL);
717 if (r < 0)
718 goto fail;
719
f2ed4c69 720 /* class: maximum udp packet that can be received */
dc913c9a
TG
721 r = dns_packet_append_uint16(p, max_udp_size, NULL);
722 if (r < 0)
723 goto fail;
724
725 /* extended RCODE and VERSION */
f2ed4c69 726 r = dns_packet_append_uint16(p, ((uint16_t) rcode & 0x0FF0) << 4, NULL);
dc913c9a
TG
727 if (r < 0)
728 goto fail;
729
7586f4d1
TG
730 /* flags: DNSSEC OK (DO), see RFC3225 */
731 r = dns_packet_append_uint16(p, edns0_do ? EDNS0_OPT_DO : 0, NULL);
dc913c9a
TG
732 if (r < 0)
733 goto fail;
734
735 /* RDLENGTH */
12c40d4c 736 if (edns0_do && !DNS_PACKET_QR(p)) {
b30bf55d 737 /* If DO is on and this is not a reply, also append RFC6975 Algorithm data */
665408ac
LP
738
739 static const uint8_t rfc6975[] = {
740
741 0, 5, /* OPTION_CODE: DAU */
546e635a 742#if HAVE_GCRYPT && GCRYPT_VERSION_NUMBER >= 0x010600
73a4cd17
MCO
743 0, 7, /* LIST_LENGTH */
744#else
665408ac 745 0, 6, /* LIST_LENGTH */
73a4cd17 746#endif
665408ac
LP
747 DNSSEC_ALGORITHM_RSASHA1,
748 DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1,
749 DNSSEC_ALGORITHM_RSASHA256,
750 DNSSEC_ALGORITHM_RSASHA512,
751 DNSSEC_ALGORITHM_ECDSAP256SHA256,
752 DNSSEC_ALGORITHM_ECDSAP384SHA384,
546e635a 753#if HAVE_GCRYPT && GCRYPT_VERSION_NUMBER >= 0x010600
73a4cd17
MCO
754 DNSSEC_ALGORITHM_ED25519,
755#endif
665408ac
LP
756
757 0, 6, /* OPTION_CODE: DHU */
758 0, 3, /* LIST_LENGTH */
759 DNSSEC_DIGEST_SHA1,
760 DNSSEC_DIGEST_SHA256,
761 DNSSEC_DIGEST_SHA384,
762
763 0, 7, /* OPTION_CODE: N3U */
764 0, 1, /* LIST_LENGTH */
765 NSEC3_ALGORITHM_SHA1,
766 };
767
768 r = dns_packet_append_uint16(p, sizeof(rfc6975), NULL);
769 if (r < 0)
770 goto fail;
771
772 r = dns_packet_append_blob(p, rfc6975, sizeof(rfc6975), NULL);
773 } else
774 r = dns_packet_append_uint16(p, 0, NULL);
dc913c9a
TG
775 if (r < 0)
776 goto fail;
777
519ef046
LP
778 DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) + 1);
779
780 p->opt_start = saved_size;
781 p->opt_size = p->size - saved_size;
782
dc913c9a
TG
783 if (start)
784 *start = saved_size;
785
786 return 0;
787
788fail:
789 dns_packet_truncate(p, saved_size);
790 return r;
791}
792
519ef046
LP
793int dns_packet_truncate_opt(DnsPacket *p) {
794 assert(p);
795
796 if (p->opt_start == (size_t) -1) {
797 assert(p->opt_size == (size_t) -1);
798 return 0;
799 }
800
801 assert(p->opt_size != (size_t) -1);
802 assert(DNS_PACKET_ARCOUNT(p) > 0);
803
804 if (p->opt_start + p->opt_size != p->size)
805 return -EBUSY;
806
807 dns_packet_truncate(p, p->opt_start);
808 DNS_PACKET_HEADER(p)->arcount = htobe16(DNS_PACKET_ARCOUNT(p) - 1);
809 p->opt_start = p->opt_size = (size_t) -1;
810
811 return 1;
812}
813
58ab31d5 814int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, const DnsAnswerFlags flags, size_t *start, size_t *rdata_start) {
f471bc11 815
a8812dd7 816 size_t saved_size, rdlength_offset, end, rdlength, rds;
c3ae4188 817 uint32_t ttl;
623a4c97
LP
818 int r;
819
820 assert(p);
821 assert(rr);
822
823 saved_size = p->size;
824
58ab31d5 825 r = dns_packet_append_key(p, rr->key, flags, NULL);
623a4c97
LP
826 if (r < 0)
827 goto fail;
828
c3ae4188
DR
829 ttl = flags & DNS_ANSWER_GOODBYE ? 0 : rr->ttl;
830 r = dns_packet_append_uint32(p, ttl, NULL);
623a4c97
LP
831 if (r < 0)
832 goto fail;
833
834 /* Initially we write 0 here */
835 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
836 if (r < 0)
837 goto fail;
838
a8812dd7
LP
839 rds = p->size - saved_size;
840
0dae31d4 841 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
623a4c97 842
9c92ce6d
LP
843 case DNS_TYPE_SRV:
844 r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
845 if (r < 0)
846 goto fail;
847
848 r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
849 if (r < 0)
850 goto fail;
851
852 r = dns_packet_append_uint16(p, rr->srv.port, NULL);
853 if (r < 0)
854 goto fail;
855
b2776a60
YW
856 /* RFC 2782 states "Unless and until permitted by future standards
857 * action, name compression is not to be used for this field." */
858 r = dns_packet_append_name(p, rr->srv.name, false, false, NULL);
9c92ce6d
LP
859 break;
860
623a4c97
LP
861 case DNS_TYPE_PTR:
862 case DNS_TYPE_NS:
863 case DNS_TYPE_CNAME:
8ac4e9e1 864 case DNS_TYPE_DNAME:
a3db237b 865 r = dns_packet_append_name(p, rr->ptr.name, true, false, NULL);
623a4c97
LP
866 break;
867
868 case DNS_TYPE_HINFO:
869 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
870 if (r < 0)
871 goto fail;
872
873 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
874 break;
875
9de3e329 876 case DNS_TYPE_SPF: /* exactly the same as TXT */
2001c805 877 case DNS_TYPE_TXT:
2e276efc 878
2001c805 879 if (!rr->txt.items) {
1ccda9b7
LP
880 /* RFC 6763, section 6.1 suggests to generate
881 * single empty string for an empty array. */
882
2001c805 883 r = dns_packet_append_raw_string(p, NULL, 0, NULL);
2e276efc
ZJS
884 if (r < 0)
885 goto fail;
1ccda9b7 886 } else {
2001c805
LP
887 DnsTxtItem *i;
888
889 LIST_FOREACH(items, i, rr->txt.items) {
890 r = dns_packet_append_raw_string(p, i->data, i->length, NULL);
1ccda9b7
LP
891 if (r < 0)
892 goto fail;
893 }
2e276efc
ZJS
894 }
895
6a6fc3df 896 r = 0;
2e276efc 897 break;
2e276efc 898
623a4c97
LP
899 case DNS_TYPE_A:
900 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
901 break;
902
903 case DNS_TYPE_AAAA:
904 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
905 break;
906
907 case DNS_TYPE_SOA:
a3db237b 908 r = dns_packet_append_name(p, rr->soa.mname, true, false, NULL);
623a4c97
LP
909 if (r < 0)
910 goto fail;
911
a3db237b 912 r = dns_packet_append_name(p, rr->soa.rname, true, false, NULL);
623a4c97
LP
913 if (r < 0)
914 goto fail;
915
916 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
917 if (r < 0)
918 goto fail;
919
920 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
921 if (r < 0)
922 goto fail;
923
924 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
925 if (r < 0)
926 goto fail;
927
928 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
929 if (r < 0)
930 goto fail;
931
932 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
933 break;
934
935 case DNS_TYPE_MX:
946c7094
ZJS
936 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
937 if (r < 0)
938 goto fail;
939
a3db237b 940 r = dns_packet_append_name(p, rr->mx.exchange, true, false, NULL);
946c7094
ZJS
941 break;
942
0dae31d4
ZJS
943 case DNS_TYPE_LOC:
944 r = dns_packet_append_uint8(p, rr->loc.version, NULL);
945 if (r < 0)
946 goto fail;
947
948 r = dns_packet_append_uint8(p, rr->loc.size, NULL);
949 if (r < 0)
950 goto fail;
951
952 r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
953 if (r < 0)
954 goto fail;
955
956 r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
957 if (r < 0)
958 goto fail;
959
afbc4f26 960 r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
0dae31d4
ZJS
961 if (r < 0)
962 goto fail;
963
afbc4f26 964 r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
0dae31d4
ZJS
965 if (r < 0)
966 goto fail;
967
afbc4f26 968 r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
0dae31d4
ZJS
969 break;
970
abf126a3
TG
971 case DNS_TYPE_DS:
972 r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL);
973 if (r < 0)
974 goto fail;
975
976 r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL);
977 if (r < 0)
978 goto fail;
979
980 r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL);
981 if (r < 0)
982 goto fail;
983
984 r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL);
985 break;
986
623a4c97 987 case DNS_TYPE_SSHFP:
42cc2eeb
LP
988 r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
989 if (r < 0)
990 goto fail;
8db0d2f5 991
42cc2eeb
LP
992 r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
993 if (r < 0)
994 goto fail;
995
549c1a25 996 r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL);
42cc2eeb
LP
997 break;
998
8db0d2f5 999 case DNS_TYPE_DNSKEY:
f91dc240 1000 r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL);
8db0d2f5
ZJS
1001 if (r < 0)
1002 goto fail;
1003
f91dc240 1004 r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL);
8db0d2f5
ZJS
1005 if (r < 0)
1006 goto fail;
1007
1008 r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
1009 if (r < 0)
1010 goto fail;
1011
1012 r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
1013 break;
1014
151226ab
ZJS
1015 case DNS_TYPE_RRSIG:
1016 r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
1017 if (r < 0)
1018 goto fail;
1019
1020 r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
1021 if (r < 0)
1022 goto fail;
1023
1024 r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
1025 if (r < 0)
1026 goto fail;
1027
1028 r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
1029 if (r < 0)
1030 goto fail;
1031
1032 r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
1033 if (r < 0)
1034 goto fail;
1035
1036 r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
1037 if (r < 0)
1038 goto fail;
1039
0b1b17d3 1040 r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL);
151226ab
ZJS
1041 if (r < 0)
1042 goto fail;
1043
a3db237b 1044 r = dns_packet_append_name(p, rr->rrsig.signer, false, true, NULL);
151226ab
ZJS
1045 if (r < 0)
1046 goto fail;
1047
1048 r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
1049 break;
1050
50f1e641 1051 case DNS_TYPE_NSEC:
a3db237b 1052 r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, false, NULL);
50f1e641
TG
1053 if (r < 0)
1054 goto fail;
1055
1056 r = dns_packet_append_types(p, rr->nsec.types, NULL);
1057 if (r < 0)
1058 goto fail;
1059
5d45a880 1060 break;
d75acfb0 1061
5d45a880
TG
1062 case DNS_TYPE_NSEC3:
1063 r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL);
1064 if (r < 0)
1065 goto fail;
1066
1067 r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL);
1068 if (r < 0)
1069 goto fail;
1070
1071 r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL);
1072 if (r < 0)
1073 goto fail;
1074
1075 r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL);
1076 if (r < 0)
1077 goto fail;
1078
1079 r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL);
1080 if (r < 0)
1081 goto fail;
1082
1083 r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL);
1084 if (r < 0)
1085 goto fail;
1086
1087 r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL);
1088 if (r < 0)
1089 goto fail;
1090
1091 r = dns_packet_append_types(p, rr->nsec3.types, NULL);
1092 if (r < 0)
1093 goto fail;
1094
50f1e641 1095 break;
d75acfb0 1096
48d45d2b
ZJS
1097 case DNS_TYPE_TLSA:
1098 r = dns_packet_append_uint8(p, rr->tlsa.cert_usage, NULL);
1099 if (r < 0)
1100 goto fail;
1101
1102 r = dns_packet_append_uint8(p, rr->tlsa.selector, NULL);
1103 if (r < 0)
1104 goto fail;
1105
1106 r = dns_packet_append_uint8(p, rr->tlsa.matching_type, NULL);
1107 if (r < 0)
1108 goto fail;
1109
1110 r = dns_packet_append_blob(p, rr->tlsa.data, rr->tlsa.data_size, NULL);
1111 break;
1112
95052df3
ZJS
1113 case DNS_TYPE_CAA:
1114 r = dns_packet_append_uint8(p, rr->caa.flags, NULL);
1115 if (r < 0)
1116 goto fail;
1117
1118 r = dns_packet_append_string(p, rr->caa.tag, NULL);
1119 if (r < 0)
1120 goto fail;
1121
1122 r = dns_packet_append_blob(p, rr->caa.value, rr->caa.value_size, NULL);
1123 break;
1124
d75acfb0 1125 case DNS_TYPE_OPT:
d93a16b8 1126 case DNS_TYPE_OPENPGPKEY:
0dae31d4 1127 case _DNS_TYPE_INVALID: /* unparseable */
623a4c97 1128 default:
0dae31d4 1129
a43a068a 1130 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.data_size, NULL);
623a4c97
LP
1131 break;
1132 }
1133 if (r < 0)
1134 goto fail;
1135
1136 /* Let's calculate the actual data size and update the field */
1137 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
1138 if (rdlength > 0xFFFF) {
555f5cdc 1139 r = -ENOSPC;
623a4c97
LP
1140 goto fail;
1141 }
1142
1143 end = p->size;
1144 p->size = rdlength_offset;
1145 r = dns_packet_append_uint16(p, rdlength, NULL);
1146 if (r < 0)
1147 goto fail;
1148 p->size = end;
1149
351e6342
LP
1150 if (start)
1151 *start = saved_size;
1152
a8812dd7
LP
1153 if (rdata_start)
1154 *rdata_start = rds;
1155
623a4c97
LP
1156 return 0;
1157
1158fail:
1159 dns_packet_truncate(p, saved_size);
1160 return r;
1161}
1162
f471bc11
LP
1163int dns_packet_append_question(DnsPacket *p, DnsQuestion *q) {
1164 DnsResourceKey *key;
1165 int r;
1166
1167 assert(p);
1168
1169 DNS_QUESTION_FOREACH(key, q) {
58ab31d5 1170 r = dns_packet_append_key(p, key, 0, NULL);
f471bc11
LP
1171 if (r < 0)
1172 return r;
1173 }
1174
1175 return 0;
1176}
1177
1178int dns_packet_append_answer(DnsPacket *p, DnsAnswer *a) {
1179 DnsResourceRecord *rr;
58ab31d5 1180 DnsAnswerFlags flags;
f471bc11
LP
1181 int r;
1182
1183 assert(p);
1184
58ab31d5
DR
1185 DNS_ANSWER_FOREACH_FLAGS(rr, flags, a) {
1186 r = dns_packet_append_rr(p, rr, flags, NULL, NULL);
f471bc11
LP
1187 if (r < 0)
1188 return r;
1189 }
1190
1191 return 0;
1192}
1193
74b2466e
LP
1194int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
1195 assert(p);
1196
1197 if (p->rindex + sz > p->size)
1198 return -EMSGSIZE;
1199
1200 if (ret)
1201 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
1202
1203 if (start)
1204 *start = p->rindex;
1205
1206 p->rindex += sz;
1207 return 0;
1208}
1209
8ba9fd9c 1210void dns_packet_rewind(DnsPacket *p, size_t idx) {
74b2466e
LP
1211 assert(p);
1212 assert(idx <= p->size);
1213 assert(idx >= DNS_PACKET_HEADER_SIZE);
1214
1215 p->rindex = idx;
1216}
1217
623a4c97
LP
1218int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
1219 const void *q;
1220 int r;
1221
1222 assert(p);
1223 assert(d);
1224
1225 r = dns_packet_read(p, sz, &q, start);
1226 if (r < 0)
1227 return r;
1228
1229 memcpy(d, q, sz);
1230 return 0;
1231}
1232
f5430a3e
LP
1233static int dns_packet_read_memdup(
1234 DnsPacket *p, size_t size,
1235 void **ret, size_t *ret_size,
1236 size_t *ret_start) {
1237
1238 const void *src;
1239 size_t start;
1240 int r;
1241
1242 assert(p);
1243 assert(ret);
1244
1245 r = dns_packet_read(p, size, &src, &start);
1246 if (r < 0)
1247 return r;
1248
1249 if (size <= 0)
1250 *ret = NULL;
1251 else {
1252 void *copy;
1253
1254 copy = memdup(src, size);
1255 if (!copy)
1256 return -ENOMEM;
1257
1258 *ret = copy;
1259 }
1260
1261 if (ret_size)
1262 *ret_size = size;
1263 if (ret_start)
1264 *ret_start = start;
1265
1266 return 0;
1267}
1268
74b2466e
LP
1269int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
1270 const void *d;
1271 int r;
1272
1273 assert(p);
1274
1275 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
1276 if (r < 0)
1277 return r;
1278
1279 *ret = ((uint8_t*) d)[0];
1280 return 0;
1281}
1282
1283int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
1284 const void *d;
1285 int r;
1286
1287 assert(p);
1288
1289 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
1290 if (r < 0)
1291 return r;
1292
725ca0e5
TG
1293 *ret = unaligned_read_be16(d);
1294
74b2466e
LP
1295 return 0;
1296}
1297
1298int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
1299 const void *d;
1300 int r;
1301
1302 assert(p);
1303
1304 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
1305 if (r < 0)
1306 return r;
1307
725ca0e5 1308 *ret = unaligned_read_be32(d);
74b2466e
LP
1309
1310 return 0;
1311}
1312
1313int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
e18a3c73 1314 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
74b2466e
LP
1315 const void *d;
1316 char *t;
1317 uint8_t c;
1318 int r;
1319
1320 assert(p);
e18a3c73 1321 INIT_REWINDER(rewinder, p);
74b2466e
LP
1322
1323 r = dns_packet_read_uint8(p, &c, NULL);
1324 if (r < 0)
e18a3c73 1325 return r;
74b2466e
LP
1326
1327 r = dns_packet_read(p, c, &d, NULL);
1328 if (r < 0)
e18a3c73 1329 return r;
74b2466e 1330
e18a3c73
ZJS
1331 if (memchr(d, 0, c))
1332 return -EBADMSG;
74b2466e
LP
1333
1334 t = strndup(d, c);
e18a3c73
ZJS
1335 if (!t)
1336 return -ENOMEM;
74b2466e
LP
1337
1338 if (!utf8_is_valid(t)) {
1339 free(t);
e18a3c73 1340 return -EBADMSG;
74b2466e
LP
1341 }
1342
1343 *ret = t;
1344
1345 if (start)
e18a3c73
ZJS
1346 *start = rewinder.saved_rindex;
1347 CANCEL_REWINDER(rewinder);
74b2466e
LP
1348
1349 return 0;
74b2466e
LP
1350}
1351
2001c805 1352int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start) {
e18a3c73 1353 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
2001c805
LP
1354 uint8_t c;
1355 int r;
1356
1357 assert(p);
e18a3c73 1358 INIT_REWINDER(rewinder, p);
2001c805
LP
1359
1360 r = dns_packet_read_uint8(p, &c, NULL);
1361 if (r < 0)
e18a3c73 1362 return r;
2001c805
LP
1363
1364 r = dns_packet_read(p, c, ret, NULL);
1365 if (r < 0)
e18a3c73 1366 return r;
2001c805
LP
1367
1368 if (size)
1369 *size = c;
1370 if (start)
e18a3c73
ZJS
1371 *start = rewinder.saved_rindex;
1372 CANCEL_REWINDER(rewinder);
2001c805
LP
1373
1374 return 0;
2001c805
LP
1375}
1376
f6a5fec6
LP
1377int dns_packet_read_name(
1378 DnsPacket *p,
1379 char **_ret,
1380 bool allow_compression,
1381 size_t *start) {
1382
e18a3c73
ZJS
1383 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
1384 size_t after_rindex = 0, jump_barrier;
74b2466e
LP
1385 _cleanup_free_ char *ret = NULL;
1386 size_t n = 0, allocated = 0;
1387 bool first = true;
1388 int r;
1389
1390 assert(p);
1391 assert(_ret);
e18a3c73
ZJS
1392 INIT_REWINDER(rewinder, p);
1393 jump_barrier = p->rindex;
74b2466e 1394
f6a5fec6
LP
1395 if (p->refuse_compression)
1396 allow_compression = false;
1397
74b2466e
LP
1398 for (;;) {
1399 uint8_t c, d;
1400
1401 r = dns_packet_read_uint8(p, &c, NULL);
1402 if (r < 0)
e18a3c73 1403 return r;
74b2466e
LP
1404
1405 if (c == 0)
1406 /* End of name */
1407 break;
1408 else if (c <= 63) {
74b2466e
LP
1409 const char *label;
1410
1411 /* Literal label */
1412 r = dns_packet_read(p, c, (const void**) &label, NULL);
1413 if (r < 0)
e18a3c73 1414 return r;
74b2466e 1415
e18a3c73
ZJS
1416 if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX))
1417 return -ENOMEM;
74b2466e 1418
422baca0 1419 if (first)
74b2466e 1420 first = false;
422baca0
LP
1421 else
1422 ret[n++] = '.';
1423
1424 r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
1425 if (r < 0)
e18a3c73 1426 return r;
74b2466e 1427
74b2466e
LP
1428 n += r;
1429 continue;
151226ab 1430 } else if (allow_compression && (c & 0xc0) == 0xc0) {
74b2466e
LP
1431 uint16_t ptr;
1432
1433 /* Pointer */
1434 r = dns_packet_read_uint8(p, &d, NULL);
1435 if (r < 0)
e18a3c73 1436 return r;
74b2466e
LP
1437
1438 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
e18a3c73
ZJS
1439 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier)
1440 return -EBADMSG;
74b2466e
LP
1441
1442 if (after_rindex == 0)
1443 after_rindex = p->rindex;
1444
f131770b 1445 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
c75dbf9b 1446 jump_barrier = ptr;
74b2466e 1447 p->rindex = ptr;
e18a3c73
ZJS
1448 } else
1449 return -EBADMSG;
74b2466e
LP
1450 }
1451
e18a3c73
ZJS
1452 if (!GREEDY_REALLOC(ret, allocated, n + 1))
1453 return -ENOMEM;
74b2466e
LP
1454
1455 ret[n] = 0;
1456
1457 if (after_rindex != 0)
1458 p->rindex= after_rindex;
1459
1cc6c93a 1460 *_ret = TAKE_PTR(ret);
74b2466e
LP
1461
1462 if (start)
e18a3c73
ZJS
1463 *start = rewinder.saved_rindex;
1464 CANCEL_REWINDER(rewinder);
74b2466e
LP
1465
1466 return 0;
74b2466e
LP
1467}
1468
50f1e641
TG
1469static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) {
1470 uint8_t window;
1471 uint8_t length;
1472 const uint8_t *bitmap;
2ad613ad 1473 uint8_t bit = 0;
50f1e641
TG
1474 unsigned i;
1475 bool found = false;
e18a3c73 1476 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
50f1e641
TG
1477 int r;
1478
1479 assert(p);
1480 assert(types);
e18a3c73 1481 INIT_REWINDER(rewinder, p);
50f1e641
TG
1482
1483 r = bitmap_ensure_allocated(types);
1484 if (r < 0)
e18a3c73 1485 return r;
50f1e641
TG
1486
1487 r = dns_packet_read_uint8(p, &window, NULL);
1488 if (r < 0)
e18a3c73 1489 return r;
50f1e641
TG
1490
1491 r = dns_packet_read_uint8(p, &length, NULL);
1492 if (r < 0)
e18a3c73 1493 return r;
50f1e641
TG
1494
1495 if (length == 0 || length > 32)
1496 return -EBADMSG;
1497
1498 r = dns_packet_read(p, length, (const void **)&bitmap, NULL);
1499 if (r < 0)
e18a3c73 1500 return r;
50f1e641
TG
1501
1502 for (i = 0; i < length; i++) {
1503 uint8_t bitmask = 1 << 7;
50f1e641
TG
1504
1505 if (!bitmap[i]) {
1506 found = false;
2ad613ad 1507 bit += 8;
50f1e641
TG
1508 continue;
1509 }
1510
1511 found = true;
1512
9f939335 1513 for (; bitmask; bit++, bitmask >>= 1)
50f1e641
TG
1514 if (bitmap[i] & bitmask) {
1515 uint16_t n;
1516
50f1e641
TG
1517 n = (uint16_t) window << 8 | (uint16_t) bit;
1518
8e6edc49
TG
1519 /* Ignore pseudo-types. see RFC4034 section 4.1.2 */
1520 if (dns_type_is_pseudo(n))
1521 continue;
1522
50f1e641
TG
1523 r = bitmap_set(*types, n);
1524 if (r < 0)
e18a3c73 1525 return r;
50f1e641 1526 }
50f1e641
TG
1527 }
1528
1529 if (!found)
1530 return -EBADMSG;
1531
1532 if (start)
e18a3c73
ZJS
1533 *start = rewinder.saved_rindex;
1534 CANCEL_REWINDER(rewinder);
50f1e641
TG
1535
1536 return 0;
50f1e641
TG
1537}
1538
89492aaf 1539static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
e18a3c73 1540 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
89492aaf
TG
1541 int r;
1542
e18a3c73 1543 INIT_REWINDER(rewinder, p);
89492aaf 1544
e18a3c73 1545 while (p->rindex < rewinder.saved_rindex + size) {
89492aaf
TG
1546 r = dns_packet_read_type_window(p, types, NULL);
1547 if (r < 0)
e18a3c73 1548 return r;
89492aaf
TG
1549
1550 /* don't read past end of current RR */
e18a3c73
ZJS
1551 if (p->rindex > rewinder.saved_rindex + size)
1552 return -EBADMSG;
89492aaf
TG
1553 }
1554
e18a3c73
ZJS
1555 if (p->rindex != rewinder.saved_rindex + size)
1556 return -EBADMSG;
89492aaf
TG
1557
1558 if (start)
e18a3c73
ZJS
1559 *start = rewinder.saved_rindex;
1560 CANCEL_REWINDER(rewinder);
89492aaf
TG
1561
1562 return 0;
89492aaf
TG
1563}
1564
d2579eec 1565int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, bool *ret_cache_flush, size_t *start) {
e18a3c73 1566 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
faa133f3 1567 _cleanup_free_ char *name = NULL;
d2579eec 1568 bool cache_flush = false;
faa133f3
LP
1569 uint16_t class, type;
1570 DnsResourceKey *key;
74b2466e
LP
1571 int r;
1572
1573 assert(p);
1574 assert(ret);
e18a3c73 1575 INIT_REWINDER(rewinder, p);
74b2466e 1576
151226ab 1577 r = dns_packet_read_name(p, &name, true, NULL);
74b2466e 1578 if (r < 0)
e18a3c73 1579 return r;
74b2466e 1580
faa133f3 1581 r = dns_packet_read_uint16(p, &type, NULL);
74b2466e 1582 if (r < 0)
e18a3c73 1583 return r;
74b2466e 1584
faa133f3 1585 r = dns_packet_read_uint16(p, &class, NULL);
74b2466e 1586 if (r < 0)
e18a3c73 1587 return r;
74b2466e 1588
23502de3
DM
1589 if (p->protocol == DNS_PROTOCOL_MDNS) {
1590 /* See RFC6762, Section 10.2 */
1591
d2579eec 1592 if (type != DNS_TYPE_OPT && (class & MDNS_RR_CACHE_FLUSH)) {
23502de3 1593 class &= ~MDNS_RR_CACHE_FLUSH;
d2579eec
LP
1594 cache_flush = true;
1595 }
23502de3
DM
1596 }
1597
faa133f3 1598 key = dns_resource_key_new_consume(class, type, name);
e18a3c73
ZJS
1599 if (!key)
1600 return -ENOMEM;
faa133f3
LP
1601
1602 name = NULL;
1603 *ret = key;
74b2466e 1604
d2579eec
LP
1605 if (ret_cache_flush)
1606 *ret_cache_flush = cache_flush;
74b2466e 1607 if (start)
e18a3c73
ZJS
1608 *start = rewinder.saved_rindex;
1609 CANCEL_REWINDER(rewinder);
74b2466e
LP
1610
1611 return 0;
74b2466e
LP
1612}
1613
afbc4f26
ZJS
1614static bool loc_size_ok(uint8_t size) {
1615 uint8_t m = size >> 4, e = size & 0xF;
1616
1617 return m <= 9 && e <= 9 && (m > 0 || e == 0);
1618}
1619
d2579eec 1620int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, bool *ret_cache_flush, size_t *start) {
faa133f3
LP
1621 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1622 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
e18a3c73
ZJS
1623 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder;
1624 size_t offset;
74b2466e 1625 uint16_t rdlength;
d2579eec 1626 bool cache_flush;
74b2466e
LP
1627 int r;
1628
1629 assert(p);
1630 assert(ret);
1631
e18a3c73 1632 INIT_REWINDER(rewinder, p);
74b2466e 1633
d2579eec 1634 r = dns_packet_read_key(p, &key, &cache_flush, NULL);
74b2466e 1635 if (r < 0)
e18a3c73 1636 return r;
74b2466e 1637
e18a3c73
ZJS
1638 if (!dns_class_is_valid_rr(key->class) || !dns_type_is_valid_rr(key->type))
1639 return -EBADMSG;
0e2bcd6a 1640
faa133f3 1641 rr = dns_resource_record_new(key);
e18a3c73
ZJS
1642 if (!rr)
1643 return -ENOMEM;
faa133f3 1644
74b2466e
LP
1645 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1646 if (r < 0)
e18a3c73 1647 return r;
74b2466e 1648
0d0b52d7
LP
1649 /* RFC 2181, Section 8, suggests to
1650 * treat a TTL with the MSB set as a zero TTL. */
1651 if (rr->ttl & UINT32_C(0x80000000))
1652 rr->ttl = 0;
1653
74b2466e
LP
1654 r = dns_packet_read_uint16(p, &rdlength, NULL);
1655 if (r < 0)
e18a3c73 1656 return r;
74b2466e 1657
e18a3c73
ZJS
1658 if (p->rindex + rdlength > p->size)
1659 return -EBADMSG;
74b2466e
LP
1660
1661 offset = p->rindex;
1662
faa133f3 1663 switch (rr->key->type) {
74b2466e 1664
9c92ce6d
LP
1665 case DNS_TYPE_SRV:
1666 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1667 if (r < 0)
e18a3c73 1668 return r;
9c92ce6d
LP
1669 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1670 if (r < 0)
e18a3c73 1671 return r;
9c92ce6d
LP
1672 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1673 if (r < 0)
e18a3c73 1674 return r;
151226ab 1675 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
9c92ce6d
LP
1676 break;
1677
74b2466e
LP
1678 case DNS_TYPE_PTR:
1679 case DNS_TYPE_NS:
1680 case DNS_TYPE_CNAME:
8ac4e9e1 1681 case DNS_TYPE_DNAME:
151226ab 1682 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1683 break;
1684
1685 case DNS_TYPE_HINFO:
1686 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1687 if (r < 0)
e18a3c73 1688 return r;
74b2466e
LP
1689
1690 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1691 break;
1692
9de3e329 1693 case DNS_TYPE_SPF: /* exactly the same as TXT */
1ccda9b7
LP
1694 case DNS_TYPE_TXT:
1695 if (rdlength <= 0) {
ebb779dc
DR
1696 r = dns_txt_item_new_empty(&rr->txt.items);
1697 if (r < 0)
1698 return r;
1ccda9b7 1699 } else {
2001c805
LP
1700 DnsTxtItem *last = NULL;
1701
1ccda9b7 1702 while (p->rindex < offset + rdlength) {
2001c805
LP
1703 DnsTxtItem *i;
1704 const void *data;
1705 size_t sz;
2e276efc 1706
2001c805 1707 r = dns_packet_read_raw_string(p, &data, &sz, NULL);
1ccda9b7 1708 if (r < 0)
2001c805 1709 return r;
1ccda9b7 1710
2001c805
LP
1711 i = malloc0(offsetof(DnsTxtItem, data) + sz + 1); /* extra NUL byte at the end */
1712 if (!i)
1713 return -ENOMEM;
1714
1715 memcpy(i->data, data, sz);
1716 i->length = sz;
1717
1718 LIST_INSERT_AFTER(items, rr->txt.items, last, i);
1719 last = i;
1ccda9b7 1720 }
6a6fc3df
LP
1721 }
1722
1723 r = 0;
2e276efc 1724 break;
2e276efc 1725
74b2466e 1726 case DNS_TYPE_A:
623a4c97 1727 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1728 break;
1729
1730 case DNS_TYPE_AAAA:
623a4c97 1731 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1732 break;
1733
7e8e0422 1734 case DNS_TYPE_SOA:
151226ab 1735 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422 1736 if (r < 0)
e18a3c73 1737 return r;
7e8e0422 1738
151226ab 1739 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422 1740 if (r < 0)
e18a3c73 1741 return r;
7e8e0422
LP
1742
1743 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1744 if (r < 0)
e18a3c73 1745 return r;
7e8e0422
LP
1746
1747 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1748 if (r < 0)
e18a3c73 1749 return r;
7e8e0422
LP
1750
1751 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1752 if (r < 0)
e18a3c73 1753 return r;
7e8e0422
LP
1754
1755 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1756 if (r < 0)
e18a3c73 1757 return r;
7e8e0422
LP
1758
1759 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1760 break;
1761
623a4c97 1762 case DNS_TYPE_MX:
946c7094
ZJS
1763 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1764 if (r < 0)
e18a3c73 1765 return r;
946c7094 1766
151226ab 1767 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
1768 break;
1769
0dae31d4
ZJS
1770 case DNS_TYPE_LOC: {
1771 uint8_t t;
1772 size_t pos;
1773
1774 r = dns_packet_read_uint8(p, &t, &pos);
1775 if (r < 0)
e18a3c73 1776 return r;
0dae31d4
ZJS
1777
1778 if (t == 0) {
1779 rr->loc.version = t;
1780
1781 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1782 if (r < 0)
e18a3c73 1783 return r;
0dae31d4 1784
e18a3c73
ZJS
1785 if (!loc_size_ok(rr->loc.size))
1786 return -EBADMSG;
afbc4f26 1787
0dae31d4
ZJS
1788 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1789 if (r < 0)
e18a3c73 1790 return r;
0dae31d4 1791
e18a3c73
ZJS
1792 if (!loc_size_ok(rr->loc.horiz_pre))
1793 return -EBADMSG;
afbc4f26 1794
0dae31d4
ZJS
1795 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1796 if (r < 0)
e18a3c73 1797 return r;
0dae31d4 1798
e18a3c73
ZJS
1799 if (!loc_size_ok(rr->loc.vert_pre))
1800 return -EBADMSG;
afbc4f26 1801
0dae31d4
ZJS
1802 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1803 if (r < 0)
e18a3c73 1804 return r;
0dae31d4
ZJS
1805
1806 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1807 if (r < 0)
e18a3c73 1808 return r;
0dae31d4
ZJS
1809
1810 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1811 if (r < 0)
e18a3c73 1812 return r;
0dae31d4
ZJS
1813
1814 break;
1815 } else {
1816 dns_packet_rewind(p, pos);
1817 rr->unparseable = true;
afbc4f26 1818 goto unparseable;
0dae31d4
ZJS
1819 }
1820 }
1821
abf126a3
TG
1822 case DNS_TYPE_DS:
1823 r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
1824 if (r < 0)
e18a3c73 1825 return r;
abf126a3
TG
1826
1827 r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
1828 if (r < 0)
e18a3c73 1829 return r;
abf126a3
TG
1830
1831 r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
1832 if (r < 0)
e18a3c73 1833 return r;
abf126a3 1834
8a0f6d1f
SL
1835 if (rdlength < 4)
1836 return -EBADMSG;
1837
f5430a3e
LP
1838 r = dns_packet_read_memdup(p, rdlength - 4,
1839 &rr->ds.digest, &rr->ds.digest_size,
1840 NULL);
abf126a3 1841 if (r < 0)
e18a3c73 1842 return r;
abf126a3 1843
e18a3c73 1844 if (rr->ds.digest_size <= 0)
f1d178cc
TG
1845 /* the accepted size depends on the algorithm, but for now
1846 just ensure that the value is greater than zero */
e18a3c73 1847 return -EBADMSG;
f1d178cc 1848
abf126a3 1849 break;
d75acfb0 1850
623a4c97 1851 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1852 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1853 if (r < 0)
e18a3c73 1854 return r;
42cc2eeb
LP
1855
1856 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1857 if (r < 0)
e18a3c73 1858 return r;
42cc2eeb 1859
8a0f6d1f
SL
1860 if (rdlength < 2)
1861 return -EBADMSG;
1862
f5430a3e 1863 r = dns_packet_read_memdup(p, rdlength - 2,
549c1a25 1864 &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size,
f5430a3e 1865 NULL);
f1d178cc 1866
e18a3c73 1867 if (rr->sshfp.fingerprint_size <= 0)
f1d178cc
TG
1868 /* the accepted size depends on the algorithm, but for now
1869 just ensure that the value is greater than zero */
e18a3c73 1870 return -EBADMSG;
f1d178cc 1871
8db0d2f5
ZJS
1872 break;
1873
f91dc240
LP
1874 case DNS_TYPE_DNSKEY:
1875 r = dns_packet_read_uint16(p, &rr->dnskey.flags, NULL);
8db0d2f5 1876 if (r < 0)
e18a3c73 1877 return r;
8db0d2f5 1878
f91dc240 1879 r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL);
8db0d2f5 1880 if (r < 0)
e18a3c73 1881 return r;
8db0d2f5 1882
8db0d2f5
ZJS
1883 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1884 if (r < 0)
e18a3c73 1885 return r;
8db0d2f5 1886
8a0f6d1f
SL
1887 if (rdlength < 4)
1888 return -EBADMSG;
1889
f5430a3e
LP
1890 r = dns_packet_read_memdup(p, rdlength - 4,
1891 &rr->dnskey.key, &rr->dnskey.key_size,
1892 NULL);
f1d178cc 1893
e18a3c73 1894 if (rr->dnskey.key_size <= 0)
f1d178cc
TG
1895 /* the accepted size depends on the algorithm, but for now
1896 just ensure that the value is greater than zero */
e18a3c73 1897 return -EBADMSG;
f1d178cc 1898
42cc2eeb
LP
1899 break;
1900
151226ab
ZJS
1901 case DNS_TYPE_RRSIG:
1902 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
1903 if (r < 0)
e18a3c73 1904 return r;
151226ab
ZJS
1905
1906 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
1907 if (r < 0)
e18a3c73 1908 return r;
151226ab
ZJS
1909
1910 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
1911 if (r < 0)
e18a3c73 1912 return r;
151226ab
ZJS
1913
1914 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
1915 if (r < 0)
e18a3c73 1916 return r;
151226ab
ZJS
1917
1918 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
1919 if (r < 0)
e18a3c73 1920 return r;
151226ab
ZJS
1921
1922 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
1923 if (r < 0)
e18a3c73 1924 return r;
151226ab
ZJS
1925
1926 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
1927 if (r < 0)
e18a3c73 1928 return r;
151226ab
ZJS
1929
1930 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
1931 if (r < 0)
e18a3c73 1932 return r;
151226ab 1933
8a0f6d1f
SL
1934 if (rdlength + offset < p->rindex)
1935 return -EBADMSG;
1936
f5430a3e
LP
1937 r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
1938 &rr->rrsig.signature, &rr->rrsig.signature_size,
1939 NULL);
f1d178cc 1940
e18a3c73 1941 if (rr->rrsig.signature_size <= 0)
f1d178cc
TG
1942 /* the accepted size depends on the algorithm, but for now
1943 just ensure that the value is greater than zero */
e18a3c73 1944 return -EBADMSG;
f1d178cc 1945
151226ab
ZJS
1946 break;
1947
d84e543d
DM
1948 case DNS_TYPE_NSEC: {
1949
1950 /*
e5abebab 1951 * RFC6762, section 18.14 explictly states mDNS should use name compression.
d84e543d
DM
1952 * This contradicts RFC3845, section 2.1.1
1953 */
1954
1955 bool allow_compressed = p->protocol == DNS_PROTOCOL_MDNS;
1956
1957 r = dns_packet_read_name(p, &rr->nsec.next_domain_name, allow_compressed, NULL);
50f1e641 1958 if (r < 0)
e18a3c73 1959 return r;
50f1e641 1960
89492aaf 1961 r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
89492aaf 1962
09eaf68c
TG
1963 /* We accept empty NSEC bitmaps. The bit indicating the presence of the NSEC record itself
1964 * is redundant and in e.g., RFC4956 this fact is used to define a use for NSEC records
1965 * without the NSEC bit set. */
50f1e641
TG
1966
1967 break;
d84e543d 1968 }
5d45a880
TG
1969 case DNS_TYPE_NSEC3: {
1970 uint8_t size;
1971
1972 r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
1973 if (r < 0)
e18a3c73 1974 return r;
5d45a880
TG
1975
1976 r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
1977 if (r < 0)
e18a3c73 1978 return r;
5d45a880
TG
1979
1980 r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
1981 if (r < 0)
e18a3c73 1982 return r;
5d45a880 1983
f1d178cc 1984 /* this may be zero */
5d45a880
TG
1985 r = dns_packet_read_uint8(p, &size, NULL);
1986 if (r < 0)
e18a3c73 1987 return r;
5d45a880 1988
f5430a3e 1989 r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
5d45a880 1990 if (r < 0)
e18a3c73 1991 return r;
5d45a880 1992
5d45a880
TG
1993 r = dns_packet_read_uint8(p, &size, NULL);
1994 if (r < 0)
e18a3c73 1995 return r;
5d45a880 1996
e18a3c73
ZJS
1997 if (size <= 0)
1998 return -EBADMSG;
f1d178cc 1999
e18a3c73
ZJS
2000 r = dns_packet_read_memdup(p, size,
2001 &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size,
2002 NULL);
5d45a880 2003 if (r < 0)
e18a3c73 2004 return r;
5d45a880 2005
6b9308d1 2006 r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL);
5d45a880 2007
0bbd72b2
TG
2008 /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
2009
5d45a880
TG
2010 break;
2011 }
d75acfb0 2012
48d45d2b
ZJS
2013 case DNS_TYPE_TLSA:
2014 r = dns_packet_read_uint8(p, &rr->tlsa.cert_usage, NULL);
2015 if (r < 0)
e18a3c73 2016 return r;
48d45d2b
ZJS
2017
2018 r = dns_packet_read_uint8(p, &rr->tlsa.selector, NULL);
2019 if (r < 0)
e18a3c73 2020 return r;
48d45d2b
ZJS
2021
2022 r = dns_packet_read_uint8(p, &rr->tlsa.matching_type, NULL);
2023 if (r < 0)
e18a3c73 2024 return r;
48d45d2b 2025
8a0f6d1f
SL
2026 if (rdlength < 3)
2027 return -EBADMSG;
2028
48d45d2b
ZJS
2029 r = dns_packet_read_memdup(p, rdlength - 3,
2030 &rr->tlsa.data, &rr->tlsa.data_size,
2031 NULL);
e18a3c73
ZJS
2032
2033 if (rr->tlsa.data_size <= 0)
48d45d2b
ZJS
2034 /* the accepted size depends on the algorithm, but for now
2035 just ensure that the value is greater than zero */
e18a3c73 2036 return -EBADMSG;
48d45d2b
ZJS
2037
2038 break;
2039
95052df3
ZJS
2040 case DNS_TYPE_CAA:
2041 r = dns_packet_read_uint8(p, &rr->caa.flags, NULL);
2042 if (r < 0)
2043 return r;
2044
2045 r = dns_packet_read_string(p, &rr->caa.tag, NULL);
2046 if (r < 0)
2047 return r;
2048
8a0f6d1f
SL
2049 if (rdlength + offset < p->rindex)
2050 return -EBADMSG;
2051
95052df3
ZJS
2052 r = dns_packet_read_memdup(p,
2053 rdlength + offset - p->rindex,
2054 &rr->caa.value, &rr->caa.value_size, NULL);
48d45d2b
ZJS
2055
2056 break;
2057
d75acfb0 2058 case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */
d93a16b8 2059 case DNS_TYPE_OPENPGPKEY:
74b2466e 2060 default:
afbc4f26 2061 unparseable:
a43a068a 2062 r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.data_size, NULL);
e18a3c73 2063
74b2466e
LP
2064 break;
2065 }
2066 if (r < 0)
e18a3c73
ZJS
2067 return r;
2068 if (p->rindex != offset + rdlength)
2069 return -EBADMSG;
74b2466e 2070
1cc6c93a 2071 *ret = TAKE_PTR(rr);
74b2466e 2072
d2579eec
LP
2073 if (ret_cache_flush)
2074 *ret_cache_flush = cache_flush;
74b2466e 2075 if (start)
e18a3c73
ZJS
2076 *start = rewinder.saved_rindex;
2077 CANCEL_REWINDER(rewinder);
74b2466e
LP
2078
2079 return 0;
74b2466e
LP
2080}
2081
c3f7000e
LP
2082static bool opt_is_good(DnsResourceRecord *rr, bool *rfc6975) {
2083 const uint8_t* p;
2084 bool found_dau_dhu_n3u = false;
2085 size_t l;
2086
2087 /* Checks whether the specified OPT RR is well-formed and whether it contains RFC6975 data (which is not OK in
2088 * a reply). */
2089
2090 assert(rr);
2091 assert(rr->key->type == DNS_TYPE_OPT);
2092
2093 /* Check that the version is 0 */
b30bf55d
LP
2094 if (((rr->ttl >> 16) & UINT32_C(0xFF)) != 0) {
2095 *rfc6975 = false;
2096 return true; /* if it's not version 0, it's OK, but we will ignore the OPT field contents */
2097 }
c3f7000e
LP
2098
2099 p = rr->opt.data;
a43a068a 2100 l = rr->opt.data_size;
c3f7000e
LP
2101 while (l > 0) {
2102 uint16_t option_code, option_length;
2103
2104 /* At least four bytes for OPTION-CODE and OPTION-LENGTH are required */
2105 if (l < 4U)
2106 return false;
2107
2108 option_code = unaligned_read_be16(p);
2109 option_length = unaligned_read_be16(p + 2);
2110
2111 if (l < option_length + 4U)
2112 return false;
2113
2114 /* RFC 6975 DAU, DHU or N3U fields found. */
2115 if (IN_SET(option_code, 5, 6, 7))
2116 found_dau_dhu_n3u = true;
2117
2118 p += option_length + 4U;
2119 l -= option_length + 4U;
2120 }
2121
2122 *rfc6975 = found_dau_dhu_n3u;
2123 return true;
2124}
2125
4a49e560 2126static int dns_packet_extract_question(DnsPacket *p, DnsQuestion **ret_question) {
faa133f3 2127 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
faa133f3 2128 unsigned n, i;
74b2466e
LP
2129 int r;
2130
3cb10d3a 2131 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
2132 if (n > 0) {
2133 question = dns_question_new(n);
e18a3c73
ZJS
2134 if (!question)
2135 return -ENOMEM;
74b2466e 2136
2d34cf0c
ZJS
2137 _cleanup_set_free_ Set *keys = NULL; /* references to keys are kept by Question */
2138
2139 keys = set_new(&dns_resource_key_hash_ops);
2140 if (!keys)
2141 return log_oom();
2142
2143 r = set_reserve(keys, n * 2); /* Higher multipliers give slightly higher efficiency through
2144 * hash collisions, but the gains quickly drop of after 2. */
2145 if (r < 0)
2146 return r;
2147
faa133f3
LP
2148 for (i = 0; i < n; i++) {
2149 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
d2579eec 2150 bool cache_flush;
74b2466e 2151
d2579eec 2152 r = dns_packet_read_key(p, &key, &cache_flush, NULL);
faa133f3 2153 if (r < 0)
e18a3c73 2154 return r;
74b2466e 2155
e18a3c73
ZJS
2156 if (cache_flush)
2157 return -EBADMSG;
d2579eec 2158
e18a3c73
ZJS
2159 if (!dns_type_is_valid_query(key->type))
2160 return -EBADMSG;
c463eb78 2161
2d34cf0c
ZJS
2162 r = set_put(keys, key);
2163 if (r < 0)
2164 return r;
2165 if (r == 0)
2166 /* Already in the Question, let's skip */
2167 continue;
2168
2169 r = dns_question_add_raw(question, key);
faa133f3 2170 if (r < 0)
e18a3c73 2171 return r;
faa133f3
LP
2172 }
2173 }
322345fd 2174
1cc6c93a
YW
2175 *ret_question = TAKE_PTR(question);
2176
4a49e560
ZJS
2177 return 0;
2178}
2179
2180static int dns_packet_extract_answer(DnsPacket *p, DnsAnswer **ret_answer) {
2181 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
2182 unsigned n, i;
2183 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *previous = NULL;
2184 bool bad_opt = false;
2185 int r;
2186
faa133f3 2187 n = DNS_PACKET_RRCOUNT(p);
4a49e560
ZJS
2188 if (n == 0)
2189 return 0;
c3f7000e 2190
4a49e560
ZJS
2191 answer = dns_answer_new(n);
2192 if (!answer)
2193 return -ENOMEM;
322345fd 2194
4a49e560
ZJS
2195 for (i = 0; i < n; i++) {
2196 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
2197 bool cache_flush = false;
322345fd 2198
4a49e560
ZJS
2199 r = dns_packet_read_rr(p, &rr, &cache_flush, NULL);
2200 if (r < 0)
2201 return r;
322345fd 2202
4a49e560
ZJS
2203 /* Try to reduce memory usage a bit */
2204 if (previous)
2205 dns_resource_key_reduce(&rr->key, &previous->key);
f57e3cd5 2206
4a49e560
ZJS
2207 if (rr->key->type == DNS_TYPE_OPT) {
2208 bool has_rfc6975;
c3f7000e 2209
4a49e560
ZJS
2210 if (p->opt || bad_opt) {
2211 /* Multiple OPT RRs? if so, let's ignore all, because there's
2212 * something wrong with the server, and if one is valid we wouldn't
2213 * know which one. */
2214 log_debug("Multiple OPT RRs detected, ignoring all.");
2215 bad_opt = true;
2216 continue;
2217 }
e6b57b37 2218
4a49e560
ZJS
2219 if (!dns_name_is_root(dns_resource_key_name(rr->key))) {
2220 /* If the OPT RR is not owned by the root domain, then it is bad,
2221 * let's ignore it. */
2222 log_debug("OPT RR is not owned by root domain, ignoring.");
2223 bad_opt = true;
2224 continue;
2225 }
c3f7000e 2226
4a49e560
ZJS
2227 if (i < DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)) {
2228 /* OPT RR is in the wrong section? Some Belkin routers do this. This
2229 * is a hint the EDNS implementation is borked, like the Belkin one
2230 * is, hence ignore it. */
2231 log_debug("OPT RR in wrong section, ignoring.");
2232 bad_opt = true;
2233 continue;
2234 }
2235
2236 if (!opt_is_good(rr, &has_rfc6975)) {
2237 log_debug("Malformed OPT RR, ignoring.");
2238 bad_opt = true;
2239 continue;
2240 }
2241
2242 if (DNS_PACKET_QR(p)) {
2243 /* Additional checks for responses */
2244
2245 if (!DNS_RESOURCE_RECORD_OPT_VERSION_SUPPORTED(rr)) {
2246 /* If this is a reply and we don't know the EDNS version
2247 * then something is weird... */
2248 log_debug("EDNS version newer that our request, bad server.");
2249 return -EBADMSG;
ff7febd5
LP
2250 }
2251
4a49e560
ZJS
2252 if (has_rfc6975) {
2253 /* If the OPT RR contains RFC6975 algorithm data, then this
2254 * is indication that the server just copied the OPT it got
2255 * from us (which contained that data) back into the reply.
2256 * If so, then it doesn't properly support EDNS, as RFC6975
2257 * makes it very clear that the algorithm data should only
2258 * be contained in questions, never in replies. Crappy
2259 * Belkin routers copy the OPT data for example, hence let's
2260 * detect this so that we downgrade early. */
2261 log_debug("OPT RR contained RFC6975 data, ignoring.");
c3f7000e
LP
2262 bad_opt = true;
2263 continue;
2264 }
4a49e560 2265 }
e6b57b37 2266
4a49e560
ZJS
2267 p->opt = dns_resource_record_ref(rr);
2268 } else {
2269 /* According to RFC 4795, section 2.9. only the RRs from the Answer section
2270 * shall be cached. Hence mark only those RRs as cacheable by default, but
2271 * not the ones from the Additional or Authority sections. */
2272 DnsAnswerFlags flags =
2273 (i < DNS_PACKET_ANCOUNT(p) ? DNS_ANSWER_CACHEABLE : 0) |
2274 (p->protocol == DNS_PROTOCOL_MDNS && !cache_flush ? DNS_ANSWER_SHARED_OWNER : 0);
2275
2276 r = dns_answer_add(answer, rr, p->ifindex, flags);
2277 if (r < 0)
2278 return r;
2279 }
d75acfb0 2280
4a49e560
ZJS
2281 /* Remember this RR, so that we potentically can merge it's ->key object with the
2282 * next RR. Note that we only do this if we actually decided to keep the RR around.
2283 */
2284 dns_resource_record_unref(previous);
2285 previous = dns_resource_record_ref(rr);
2286 }
105e1512 2287
4a49e560
ZJS
2288 if (bad_opt)
2289 p->opt = dns_resource_record_unref(p->opt);
105e1512 2290
1cc6c93a
YW
2291 *ret_answer = TAKE_PTR(answer);
2292
4a49e560
ZJS
2293 return 0;
2294}
ebc8a106 2295
4a49e560
ZJS
2296int dns_packet_extract(DnsPacket *p) {
2297 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
2298 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
2299 _cleanup_(rewind_dns_packet) DnsPacketRewinder rewinder = {};
2300 int r;
c3f7000e 2301
4a49e560
ZJS
2302 if (p->extracted)
2303 return 0;
2304
2305 INIT_REWINDER(rewinder, p);
2306 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
2307
2308 r = dns_packet_extract_question(p, &question);
2309 if (r < 0)
2310 return r;
2311
2312 r = dns_packet_extract_answer(p, &answer);
2313 if (r < 0)
2314 return r;
322345fd 2315
1cc6c93a
YW
2316 p->question = TAKE_PTR(question);
2317 p->answer = TAKE_PTR(answer);
322345fd 2318
a4076574
LP
2319 p->extracted = true;
2320
e18a3c73
ZJS
2321 /* no CANCEL, always rewind */
2322 return 0;
322345fd
LP
2323}
2324
8af5b883
LP
2325int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
2326 int r;
2327
2328 assert(p);
2329 assert(key);
2330
2331 /* Checks if the specified packet is a reply for the specified
2332 * key and the specified key is the only one in the question
2333 * section. */
2334
2335 if (DNS_PACKET_QR(p) != 1)
2336 return 0;
2337
2338 /* Let's unpack the packet, if that hasn't happened yet. */
2339 r = dns_packet_extract(p);
2340 if (r < 0)
2341 return r;
2342
a924f43f
EV
2343 if (!p->question)
2344 return 0;
2345
8af5b883
LP
2346 if (p->question->n_keys != 1)
2347 return 0;
2348
2349 return dns_resource_key_equal(p->question->keys[0], key);
2350}
2351
7a08d314 2352static void dns_packet_hash_func(const DnsPacket *s, struct siphash *state) {
98767d75
IT
2353 assert(s);
2354
2355 siphash24_compress(&s->size, sizeof(s->size), state);
2356 siphash24_compress(DNS_PACKET_DATA((DnsPacket*) s), s->size, state);
2357}
2358
7a08d314 2359static int dns_packet_compare_func(const DnsPacket *x, const DnsPacket *y) {
a0edd02e 2360 int r;
98767d75 2361
a0edd02e
FB
2362 r = CMP(x->size, y->size);
2363 if (r != 0)
2364 return r;
98767d75
IT
2365
2366 return memcmp(DNS_PACKET_DATA((DnsPacket*) x), DNS_PACKET_DATA((DnsPacket*) y), x->size);
2367}
2368
7a08d314 2369DEFINE_HASH_OPS(dns_packet_hash_ops, DnsPacket, dns_packet_hash_func, dns_packet_compare_func);
98767d75 2370
74b2466e
LP
2371static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
2372 [DNS_RCODE_SUCCESS] = "SUCCESS",
2373 [DNS_RCODE_FORMERR] = "FORMERR",
2374 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
2375 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
2376 [DNS_RCODE_NOTIMP] = "NOTIMP",
2377 [DNS_RCODE_REFUSED] = "REFUSED",
2378 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
2379 [DNS_RCODE_YXRRSET] = "YRRSET",
2380 [DNS_RCODE_NXRRSET] = "NXRRSET",
2381 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
2382 [DNS_RCODE_NOTZONE] = "NOTZONE",
2383 [DNS_RCODE_BADVERS] = "BADVERS",
2384 [DNS_RCODE_BADKEY] = "BADKEY",
2385 [DNS_RCODE_BADTIME] = "BADTIME",
2386 [DNS_RCODE_BADMODE] = "BADMODE",
2387 [DNS_RCODE_BADNAME] = "BADNAME",
2388 [DNS_RCODE_BADALG] = "BADALG",
2389 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
6f21e066 2390 [DNS_RCODE_BADCOOKIE] = "BADCOOKIE",
74b2466e
LP
2391};
2392DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc
LP
2393
2394static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
2395 [DNS_PROTOCOL_DNS] = "dns",
2396 [DNS_PROTOCOL_MDNS] = "mdns",
2397 [DNS_PROTOCOL_LLMNR] = "llmnr",
2398};
2399DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);