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