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