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