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