]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
resolved: degrade the feature level on explicit failure
[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
1716f6dc 31int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
74b2466e
LP
32 DnsPacket *p;
33 size_t a;
34
35 assert(ret);
36
a0166609 37 if (mtu <= UDP_PACKET_HEADER_SIZE)
74b2466e
LP
38 a = DNS_PACKET_SIZE_START;
39 else
a0166609 40 a = mtu - UDP_PACKET_HEADER_SIZE;
74b2466e
LP
41
42 if (a < DNS_PACKET_HEADER_SIZE)
43 a = DNS_PACKET_HEADER_SIZE;
44
c73ce96b
LP
45 /* round up to next page size */
46 a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
47
48 /* make sure we never allocate more than useful */
49 if (a > DNS_PACKET_SIZE_MAX)
50 a = DNS_PACKET_SIZE_MAX;
51
74b2466e
LP
52 p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
53 if (!p)
54 return -ENOMEM;
55
56 p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
57 p->allocated = a;
1716f6dc 58 p->protocol = protocol;
74b2466e
LP
59 p->n_ref = 1;
60
61 *ret = p;
62
63 return 0;
64}
65
1716f6dc 66int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
74b2466e
LP
67 DnsPacket *p;
68 DnsPacketHeader *h;
069360a6 69 int r;
74b2466e
LP
70
71 assert(ret);
72
1716f6dc 73 r = dns_packet_new(&p, protocol, mtu);
74b2466e
LP
74 if (r < 0)
75 return r;
76
77 h = DNS_PACKET_HEADER(p);
1716f6dc 78
069360a6
LP
79 if (protocol == DNS_PROTOCOL_LLMNR)
80 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
81 0 /* opcode */,
82 0 /* c */,
83 0 /* tc */,
84 0 /* t */,
85 0 /* ra */,
86 0 /* ad */,
87 0 /* cd */,
88 0 /* rcode */));
89 else
90 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
91 0 /* opcode */,
92 0 /* aa */,
93 0 /* tc */,
94 1 /* rd (ask for recursion) */,
95 0 /* ra */,
96 0 /* ad */,
97 0 /* cd */,
98 0 /* rcode */));
74b2466e
LP
99
100 *ret = p;
101 return 0;
102}
103
104DnsPacket *dns_packet_ref(DnsPacket *p) {
105
106 if (!p)
107 return NULL;
108
109 assert(p->n_ref > 0);
110 p->n_ref++;
111 return p;
112}
113
114static void dns_packet_free(DnsPacket *p) {
115 char *s;
116
117 assert(p);
118
faa133f3
LP
119 dns_question_unref(p->question);
120 dns_answer_unref(p->answer);
322345fd 121
74b2466e
LP
122 while ((s = hashmap_steal_first_key(p->names)))
123 free(s);
124 hashmap_free(p->names);
125
faa133f3 126 free(p->_data);
74b2466e
LP
127 free(p);
128}
129
130DnsPacket *dns_packet_unref(DnsPacket *p) {
131 if (!p)
132 return NULL;
133
134 assert(p->n_ref > 0);
135
136 if (p->n_ref == 1)
137 dns_packet_free(p);
138 else
139 p->n_ref--;
140
141 return NULL;
142}
143
144int dns_packet_validate(DnsPacket *p) {
145 assert(p);
146
147 if (p->size < DNS_PACKET_HEADER_SIZE)
148 return -EBADMSG;
149
c73ce96b
LP
150 if (p->size > DNS_PACKET_SIZE_MAX)
151 return -EBADMSG;
152
623a4c97 153 return 1;
74b2466e
LP
154}
155
156int dns_packet_validate_reply(DnsPacket *p) {
74b2466e
LP
157 int r;
158
159 assert(p);
160
161 r = dns_packet_validate(p);
162 if (r < 0)
163 return r;
164
623a4c97
LP
165 if (DNS_PACKET_QR(p) != 1)
166 return 0;
167
168 if (DNS_PACKET_OPCODE(p) != 0)
74b2466e
LP
169 return -EBADMSG;
170
818ef443
DM
171 switch (p->protocol) {
172 case DNS_PROTOCOL_LLMNR:
173 /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
174 if (DNS_PACKET_QDCOUNT(p) != 1)
175 return -EBADMSG;
176
177 break;
178
179 default:
180 break;
181 }
ea917db9 182
623a4c97
LP
183 return 1;
184}
185
186int dns_packet_validate_query(DnsPacket *p) {
187 int r;
188
189 assert(p);
190
191 r = dns_packet_validate(p);
192 if (r < 0)
193 return r;
194
195 if (DNS_PACKET_QR(p) != 0)
196 return 0;
197
3cb10d3a 198 if (DNS_PACKET_OPCODE(p) != 0)
74b2466e
LP
199 return -EBADMSG;
200
623a4c97
LP
201 if (DNS_PACKET_TC(p))
202 return -EBADMSG;
203
818ef443
DM
204 switch (p->protocol) {
205 case DNS_PROTOCOL_LLMNR:
206 /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
207 if (DNS_PACKET_QDCOUNT(p) != 1)
208 return -EBADMSG;
623a4c97 209
818ef443
DM
210 /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
211 if (DNS_PACKET_ANCOUNT(p) > 0)
212 return -EBADMSG;
623a4c97 213
818ef443
DM
214 /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
215 if (DNS_PACKET_NSCOUNT(p) > 0)
216 return -EBADMSG;
217
218 break;
219
220 default:
221 break;
222 }
623a4c97
LP
223
224 return 1;
74b2466e
LP
225}
226
227static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
228 assert(p);
229
c73ce96b
LP
230 if (p->size + add > p->allocated) {
231 size_t a;
232
233 a = PAGE_ALIGN((p->size + add) * 2);
234 if (a > DNS_PACKET_SIZE_MAX)
235 a = DNS_PACKET_SIZE_MAX;
236
237 if (p->size + add > a)
238 return -EMSGSIZE;
239
faa133f3 240 if (p->_data) {
c73ce96b
LP
241 void *d;
242
faa133f3 243 d = realloc(p->_data, a);
c73ce96b
LP
244 if (!d)
245 return -ENOMEM;
246
faa133f3 247 p->_data = d;
c73ce96b 248 } else {
faa133f3
LP
249 p->_data = malloc(a);
250 if (!p->_data)
c73ce96b
LP
251 return -ENOMEM;
252
faa133f3
LP
253 memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
254 memzero((uint8_t*) p->_data + p->size, a - p->size);
c73ce96b
LP
255 }
256
257 p->allocated = a;
258 }
74b2466e
LP
259
260 if (start)
261 *start = p->size;
262
263 if (ret)
264 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
265
266 p->size += add;
267 return 0;
268}
269
270static void dns_packet_truncate(DnsPacket *p, size_t sz) {
271 Iterator i;
272 char *s;
273 void *n;
274
275 assert(p);
276
277 if (p->size <= sz)
278 return;
279
0e03ade5 280 HASHMAP_FOREACH_KEY(n, s, p->names, i) {
74b2466e
LP
281
282 if (PTR_TO_SIZE(n) < sz)
283 continue;
284
285 hashmap_remove(p->names, s);
286 free(s);
287 }
288
289 p->size = sz;
290}
291
623a4c97
LP
292int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
293 void *q;
294 int r;
295
296 assert(p);
297
298 r = dns_packet_extend(p, l, &q, start);
299 if (r < 0)
300 return r;
301
302 memcpy(q, d, l);
303 return 0;
304}
305
74b2466e
LP
306int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
307 void *d;
308 int r;
309
310 assert(p);
311
312 r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
313 if (r < 0)
314 return r;
315
316 ((uint8_t*) d)[0] = v;
317
318 return 0;
319}
320
321int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
322 void *d;
323 int r;
324
325 assert(p);
326
327 r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
328 if (r < 0)
329 return r;
330
725ca0e5 331 unaligned_write_be16(d, v);
623a4c97
LP
332
333 return 0;
334}
335
336int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
337 void *d;
338 int r;
339
340 assert(p);
341
342 r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
343 if (r < 0)
344 return r;
345
725ca0e5 346 unaligned_write_be32(d, v);
74b2466e
LP
347
348 return 0;
349}
350
351int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
352 void *d;
353 size_t l;
354 int r;
355
356 assert(p);
357 assert(s);
358
359 l = strlen(s);
360 if (l > 255)
361 return -E2BIG;
362
363 r = dns_packet_extend(p, 1 + l, &d, start);
364 if (r < 0)
365 return r;
366
367 ((uint8_t*) d)[0] = (uint8_t) l;
368 memcpy(((uint8_t*) d) + 1, s, l);
369
370 return 0;
371}
372
2001c805
LP
373int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start) {
374 void *d;
375 int r;
376
377 assert(p);
378 assert(s || size == 0);
379
380 if (size > 255)
381 return -E2BIG;
382
383 r = dns_packet_extend(p, 1 + size, &d, start);
384 if (r < 0)
385 return r;
386
387 ((uint8_t*) d)[0] = (uint8_t) size;
388
389 if (size > 0)
390 memcpy(((uint8_t*) d) + 1, s, size);
391
392 return 0;
393}
394
74b2466e
LP
395int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
396 void *w;
397 int r;
398
399 assert(p);
400 assert(d);
401
402 if (l > DNS_LABEL_MAX)
403 return -E2BIG;
404
405 r = dns_packet_extend(p, 1 + l, &w, start);
406 if (r < 0)
407 return r;
408
409 ((uint8_t*) w)[0] = (uint8_t) l;
410 memcpy(((uint8_t*) w) + 1, d, l);
411
412 return 0;
413}
414
f6a5fec6
LP
415int dns_packet_append_name(
416 DnsPacket *p,
417 const char *name,
418 bool allow_compression,
419 size_t *start) {
420
74b2466e
LP
421 size_t saved_size;
422 int r;
423
424 assert(p);
425 assert(name);
426
f6a5fec6
LP
427 if (p->refuse_compression)
428 allow_compression = false;
429
74b2466e
LP
430 saved_size = p->size;
431
432 while (*name) {
433 _cleanup_free_ char *s = NULL;
434 char label[DNS_LABEL_MAX];
151226ab 435 size_t n = 0;
bdf10b5b 436 int k;
74b2466e 437
151226ab
ZJS
438 if (allow_compression)
439 n = PTR_TO_SIZE(hashmap_get(p->names, name));
74b2466e
LP
440 if (n > 0) {
441 assert(n < p->size);
442
443 if (n < 0x4000) {
444 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
445 if (r < 0)
446 goto fail;
447
448 goto done;
449 }
450 }
451
452 s = strdup(name);
453 if (!s) {
454 r = -ENOMEM;
455 goto fail;
456 }
457
458 r = dns_label_unescape(&name, label, sizeof(label));
459 if (r < 0)
460 goto fail;
461
bdf10b5b
LP
462 if (p->protocol == DNS_PROTOCOL_DNS)
463 k = dns_label_apply_idna(label, r, label, sizeof(label));
464 else
465 k = dns_label_undo_idna(label, r, label, sizeof(label));
466 if (k < 0) {
467 r = k;
468 goto fail;
469 }
470 if (k > 0)
471 r = k;
472
74b2466e
LP
473 r = dns_packet_append_label(p, label, r, &n);
474 if (r < 0)
475 goto fail;
476
151226ab 477 if (allow_compression) {
d5099efc 478 r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops);
151226ab
ZJS
479 if (r < 0)
480 goto fail;
74b2466e 481
151226ab
ZJS
482 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
483 if (r < 0)
484 goto fail;
74b2466e 485
151226ab
ZJS
486 s = NULL;
487 }
74b2466e
LP
488 }
489
490 r = dns_packet_append_uint8(p, 0, NULL);
491 if (r < 0)
492 return r;
493
494done:
495 if (start)
496 *start = saved_size;
497
498 return 0;
499
500fail:
501 dns_packet_truncate(p, saved_size);
502 return r;
503}
504
505int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
506 size_t saved_size;
507 int r;
508
509 assert(p);
510 assert(k);
511
512 saved_size = p->size;
513
151226ab 514 r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, NULL);
74b2466e
LP
515 if (r < 0)
516 goto fail;
517
518 r = dns_packet_append_uint16(p, k->type, NULL);
519 if (r < 0)
520 goto fail;
521
522 r = dns_packet_append_uint16(p, k->class, NULL);
523 if (r < 0)
524 goto fail;
525
526 if (start)
527 *start = saved_size;
528
529 return 0;
530
531fail:
532 dns_packet_truncate(p, saved_size);
533 return r;
534}
535
50f1e641
TG
536static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, uint8_t *types, size_t *start) {
537 size_t saved_size;
538 int r;
539
540 assert(p);
541 assert(types);
1792f223 542 assert(length > 0);
50f1e641 543
50f1e641
TG
544 saved_size = p->size;
545
1792f223
TG
546 r = dns_packet_append_uint8(p, window, NULL);
547 if (r < 0)
548 goto fail;
50f1e641 549
1792f223
TG
550 r = dns_packet_append_uint8(p, length, NULL);
551 if (r < 0)
552 goto fail;
6fa91901 553
1792f223
TG
554 r = dns_packet_append_blob(p, types, length, NULL);
555 if (r < 0)
556 goto fail;
50f1e641
TG
557
558 if (start)
559 *start = saved_size;
560
561 return 0;
562fail:
563 dns_packet_truncate(p, saved_size);
564 return r;
565}
566
567static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
cb57dd41 568 Iterator i;
50f1e641 569 uint8_t window = 0;
1792f223 570 uint8_t entry = 0;
50f1e641
TG
571 uint8_t bitmaps[32] = {};
572 unsigned n;
573 size_t saved_size;
574 int r;
575
576 assert(p);
577 assert(types);
578
579 saved_size = p->size;
580
cb57dd41 581 BITMAP_FOREACH(n, types, i) {
50f1e641
TG
582 assert(n <= 0xffff);
583
1792f223
TG
584 if ((n >> 8) != window && bitmaps[entry / 8] != 0) {
585 r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
50f1e641
TG
586 if (r < 0)
587 goto fail;
588
1792f223 589 zero(bitmaps);
50f1e641
TG
590 }
591
1792f223 592 window = n >> 8;
50f1e641
TG
593
594 entry = n & 255;
595
596 bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
597 }
598
1792f223 599 r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
50f1e641
TG
600 if (r < 0)
601 goto fail;
602
603 if (start)
604 *start = saved_size;
605
606 return 0;
607fail:
608 dns_packet_truncate(p, saved_size);
609 return r;
610}
611
623a4c97
LP
612int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
613 size_t saved_size, rdlength_offset, end, rdlength;
614 int r;
615
616 assert(p);
617 assert(rr);
618
619 saved_size = p->size;
620
621 r = dns_packet_append_key(p, rr->key, NULL);
622 if (r < 0)
623 goto fail;
624
625 r = dns_packet_append_uint32(p, rr->ttl, NULL);
626 if (r < 0)
627 goto fail;
628
629 /* Initially we write 0 here */
630 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
631 if (r < 0)
632 goto fail;
633
0dae31d4 634 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
623a4c97 635
9c92ce6d
LP
636 case DNS_TYPE_SRV:
637 r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
638 if (r < 0)
639 goto fail;
640
641 r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
642 if (r < 0)
643 goto fail;
644
645 r = dns_packet_append_uint16(p, rr->srv.port, NULL);
646 if (r < 0)
647 goto fail;
648
151226ab 649 r = dns_packet_append_name(p, rr->srv.name, true, NULL);
9c92ce6d
LP
650 break;
651
623a4c97
LP
652 case DNS_TYPE_PTR:
653 case DNS_TYPE_NS:
654 case DNS_TYPE_CNAME:
8ac4e9e1 655 case DNS_TYPE_DNAME:
151226ab 656 r = dns_packet_append_name(p, rr->ptr.name, true, NULL);
623a4c97
LP
657 break;
658
659 case DNS_TYPE_HINFO:
660 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
661 if (r < 0)
662 goto fail;
663
664 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
665 break;
666
9de3e329 667 case DNS_TYPE_SPF: /* exactly the same as TXT */
2001c805 668 case DNS_TYPE_TXT:
2e276efc 669
2001c805 670 if (!rr->txt.items) {
1ccda9b7
LP
671 /* RFC 6763, section 6.1 suggests to generate
672 * single empty string for an empty array. */
673
2001c805 674 r = dns_packet_append_raw_string(p, NULL, 0, NULL);
2e276efc
ZJS
675 if (r < 0)
676 goto fail;
1ccda9b7 677 } else {
2001c805
LP
678 DnsTxtItem *i;
679
680 LIST_FOREACH(items, i, rr->txt.items) {
681 r = dns_packet_append_raw_string(p, i->data, i->length, NULL);
1ccda9b7
LP
682 if (r < 0)
683 goto fail;
684 }
2e276efc
ZJS
685 }
686
6a6fc3df 687 r = 0;
2e276efc 688 break;
2e276efc 689
623a4c97
LP
690 case DNS_TYPE_A:
691 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
692 break;
693
694 case DNS_TYPE_AAAA:
695 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
696 break;
697
698 case DNS_TYPE_SOA:
151226ab 699 r = dns_packet_append_name(p, rr->soa.mname, true, NULL);
623a4c97
LP
700 if (r < 0)
701 goto fail;
702
151226ab 703 r = dns_packet_append_name(p, rr->soa.rname, true, NULL);
623a4c97
LP
704 if (r < 0)
705 goto fail;
706
707 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
708 if (r < 0)
709 goto fail;
710
711 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
712 if (r < 0)
713 goto fail;
714
715 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
716 if (r < 0)
717 goto fail;
718
719 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
720 if (r < 0)
721 goto fail;
722
723 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
724 break;
725
726 case DNS_TYPE_MX:
946c7094
ZJS
727 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
728 if (r < 0)
729 goto fail;
730
151226ab 731 r = dns_packet_append_name(p, rr->mx.exchange, true, NULL);
946c7094
ZJS
732 break;
733
0dae31d4
ZJS
734 case DNS_TYPE_LOC:
735 r = dns_packet_append_uint8(p, rr->loc.version, NULL);
736 if (r < 0)
737 goto fail;
738
739 r = dns_packet_append_uint8(p, rr->loc.size, NULL);
740 if (r < 0)
741 goto fail;
742
743 r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
744 if (r < 0)
745 goto fail;
746
747 r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
748 if (r < 0)
749 goto fail;
750
afbc4f26 751 r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
0dae31d4
ZJS
752 if (r < 0)
753 goto fail;
754
afbc4f26 755 r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
0dae31d4
ZJS
756 if (r < 0)
757 goto fail;
758
afbc4f26 759 r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
0dae31d4
ZJS
760 break;
761
abf126a3
TG
762 case DNS_TYPE_DS:
763 r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL);
764 if (r < 0)
765 goto fail;
766
767 r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL);
768 if (r < 0)
769 goto fail;
770
771 r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL);
772 if (r < 0)
773 goto fail;
774
775 r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL);
776 break;
777
623a4c97 778 case DNS_TYPE_SSHFP:
42cc2eeb
LP
779 r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
780 if (r < 0)
781 goto fail;
8db0d2f5 782
42cc2eeb
LP
783 r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
784 if (r < 0)
785 goto fail;
786
549c1a25 787 r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL);
42cc2eeb
LP
788 break;
789
8db0d2f5
ZJS
790 case DNS_TYPE_DNSKEY:
791 r = dns_packet_append_uint16(p, dnskey_to_flags(rr), NULL);
792 if (r < 0)
793 goto fail;
794
795 r = dns_packet_append_uint8(p, 3u, NULL);
796 if (r < 0)
797 goto fail;
798
799 r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
800 if (r < 0)
801 goto fail;
802
803 r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
804 break;
805
151226ab
ZJS
806 case DNS_TYPE_RRSIG:
807 r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
808 if (r < 0)
809 goto fail;
810
811 r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
812 if (r < 0)
813 goto fail;
814
815 r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
816 if (r < 0)
817 goto fail;
818
819 r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
820 if (r < 0)
821 goto fail;
822
823 r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
824 if (r < 0)
825 goto fail;
826
827 r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
828 if (r < 0)
829 goto fail;
830
0b1b17d3 831 r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL);
151226ab
ZJS
832 if (r < 0)
833 goto fail;
834
835 r = dns_packet_append_name(p, rr->rrsig.signer, false, NULL);
836 if (r < 0)
837 goto fail;
838
839 r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
840 break;
841
50f1e641
TG
842 case DNS_TYPE_NSEC:
843 r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, NULL);
844 if (r < 0)
845 goto fail;
846
847 r = dns_packet_append_types(p, rr->nsec.types, NULL);
848 if (r < 0)
849 goto fail;
850
5d45a880
TG
851 break;
852 case DNS_TYPE_NSEC3:
853 r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL);
854 if (r < 0)
855 goto fail;
856
857 r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL);
858 if (r < 0)
859 goto fail;
860
861 r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL);
862 if (r < 0)
863 goto fail;
864
865 r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL);
866 if (r < 0)
867 goto fail;
868
869 r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL);
870 if (r < 0)
871 goto fail;
872
873 r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL);
874 if (r < 0)
875 goto fail;
876
877 r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL);
878 if (r < 0)
879 goto fail;
880
881 r = dns_packet_append_types(p, rr->nsec3.types, NULL);
882 if (r < 0)
883 goto fail;
884
50f1e641 885 break;
0dae31d4 886 case _DNS_TYPE_INVALID: /* unparseable */
623a4c97 887 default:
0dae31d4 888
623a4c97
LP
889 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
890 break;
891 }
892 if (r < 0)
893 goto fail;
894
895 /* Let's calculate the actual data size and update the field */
896 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
897 if (rdlength > 0xFFFF) {
898 r = ENOSPC;
899 goto fail;
900 }
901
902 end = p->size;
903 p->size = rdlength_offset;
904 r = dns_packet_append_uint16(p, rdlength, NULL);
905 if (r < 0)
906 goto fail;
907 p->size = end;
908
351e6342
LP
909 if (start)
910 *start = saved_size;
911
623a4c97
LP
912 return 0;
913
914fail:
915 dns_packet_truncate(p, saved_size);
916 return r;
917}
918
919
74b2466e
LP
920int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
921 assert(p);
922
923 if (p->rindex + sz > p->size)
924 return -EMSGSIZE;
925
926 if (ret)
927 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
928
929 if (start)
930 *start = p->rindex;
931
932 p->rindex += sz;
933 return 0;
934}
935
8ba9fd9c 936void dns_packet_rewind(DnsPacket *p, size_t idx) {
74b2466e
LP
937 assert(p);
938 assert(idx <= p->size);
939 assert(idx >= DNS_PACKET_HEADER_SIZE);
940
941 p->rindex = idx;
942}
943
623a4c97
LP
944int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
945 const void *q;
946 int r;
947
948 assert(p);
949 assert(d);
950
951 r = dns_packet_read(p, sz, &q, start);
952 if (r < 0)
953 return r;
954
955 memcpy(d, q, sz);
956 return 0;
957}
958
f5430a3e
LP
959static int dns_packet_read_memdup(
960 DnsPacket *p, size_t size,
961 void **ret, size_t *ret_size,
962 size_t *ret_start) {
963
964 const void *src;
965 size_t start;
966 int r;
967
968 assert(p);
969 assert(ret);
970
971 r = dns_packet_read(p, size, &src, &start);
972 if (r < 0)
973 return r;
974
975 if (size <= 0)
976 *ret = NULL;
977 else {
978 void *copy;
979
980 copy = memdup(src, size);
981 if (!copy)
982 return -ENOMEM;
983
984 *ret = copy;
985 }
986
987 if (ret_size)
988 *ret_size = size;
989 if (ret_start)
990 *ret_start = start;
991
992 return 0;
993}
994
74b2466e
LP
995int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
996 const void *d;
997 int r;
998
999 assert(p);
1000
1001 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
1002 if (r < 0)
1003 return r;
1004
1005 *ret = ((uint8_t*) d)[0];
1006 return 0;
1007}
1008
1009int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
1010 const void *d;
1011 int r;
1012
1013 assert(p);
1014
1015 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
1016 if (r < 0)
1017 return r;
1018
725ca0e5
TG
1019 *ret = unaligned_read_be16(d);
1020
74b2466e
LP
1021 return 0;
1022}
1023
1024int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
1025 const void *d;
1026 int r;
1027
1028 assert(p);
1029
1030 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
1031 if (r < 0)
1032 return r;
1033
725ca0e5 1034 *ret = unaligned_read_be32(d);
74b2466e
LP
1035
1036 return 0;
1037}
1038
1039int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
1040 size_t saved_rindex;
1041 const void *d;
1042 char *t;
1043 uint8_t c;
1044 int r;
1045
1046 assert(p);
1047
1048 saved_rindex = p->rindex;
1049
1050 r = dns_packet_read_uint8(p, &c, NULL);
1051 if (r < 0)
1052 goto fail;
1053
1054 r = dns_packet_read(p, c, &d, NULL);
1055 if (r < 0)
1056 goto fail;
1057
1058 if (memchr(d, 0, c)) {
1059 r = -EBADMSG;
1060 goto fail;
1061 }
1062
1063 t = strndup(d, c);
1064 if (!t) {
1065 r = -ENOMEM;
1066 goto fail;
1067 }
1068
1069 if (!utf8_is_valid(t)) {
1070 free(t);
1071 r = -EBADMSG;
1072 goto fail;
1073 }
1074
1075 *ret = t;
1076
1077 if (start)
1078 *start = saved_rindex;
1079
1080 return 0;
1081
1082fail:
1083 dns_packet_rewind(p, saved_rindex);
1084 return r;
1085}
1086
2001c805
LP
1087int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start) {
1088 size_t saved_rindex;
1089 uint8_t c;
1090 int r;
1091
1092 assert(p);
1093
1094 saved_rindex = p->rindex;
1095
1096 r = dns_packet_read_uint8(p, &c, NULL);
1097 if (r < 0)
1098 goto fail;
1099
1100 r = dns_packet_read(p, c, ret, NULL);
1101 if (r < 0)
1102 goto fail;
1103
1104 if (size)
1105 *size = c;
1106 if (start)
1107 *start = saved_rindex;
1108
1109 return 0;
1110
1111fail:
1112 dns_packet_rewind(p, saved_rindex);
1113 return r;
1114}
1115
f6a5fec6
LP
1116int dns_packet_read_name(
1117 DnsPacket *p,
1118 char **_ret,
1119 bool allow_compression,
1120 size_t *start) {
1121
c75dbf9b 1122 size_t saved_rindex, after_rindex = 0, jump_barrier;
74b2466e
LP
1123 _cleanup_free_ char *ret = NULL;
1124 size_t n = 0, allocated = 0;
1125 bool first = true;
1126 int r;
1127
1128 assert(p);
1129 assert(_ret);
1130
f6a5fec6
LP
1131 if (p->refuse_compression)
1132 allow_compression = false;
1133
74b2466e 1134 saved_rindex = p->rindex;
c75dbf9b 1135 jump_barrier = p->rindex;
74b2466e
LP
1136
1137 for (;;) {
1138 uint8_t c, d;
1139
1140 r = dns_packet_read_uint8(p, &c, NULL);
1141 if (r < 0)
1142 goto fail;
1143
1144 if (c == 0)
1145 /* End of name */
1146 break;
1147 else if (c <= 63) {
74b2466e
LP
1148 const char *label;
1149
1150 /* Literal label */
1151 r = dns_packet_read(p, c, (const void**) &label, NULL);
1152 if (r < 0)
1153 goto fail;
1154
422baca0 1155 if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) {
74b2466e
LP
1156 r = -ENOMEM;
1157 goto fail;
1158 }
1159
422baca0 1160 if (first)
74b2466e 1161 first = false;
422baca0
LP
1162 else
1163 ret[n++] = '.';
1164
1165 r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
1166 if (r < 0)
1167 goto fail;
74b2466e 1168
74b2466e
LP
1169 n += r;
1170 continue;
151226ab 1171 } else if (allow_compression && (c & 0xc0) == 0xc0) {
74b2466e
LP
1172 uint16_t ptr;
1173
1174 /* Pointer */
1175 r = dns_packet_read_uint8(p, &d, NULL);
1176 if (r < 0)
1177 goto fail;
1178
1179 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
c75dbf9b 1180 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
74b2466e
LP
1181 r = -EBADMSG;
1182 goto fail;
1183 }
1184
1185 if (after_rindex == 0)
1186 after_rindex = p->rindex;
1187
f131770b 1188 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
c75dbf9b 1189 jump_barrier = ptr;
74b2466e 1190 p->rindex = ptr;
59aa5821
SP
1191 } else {
1192 r = -EBADMSG;
74b2466e 1193 goto fail;
59aa5821 1194 }
74b2466e
LP
1195 }
1196
1197 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
1198 r = -ENOMEM;
1199 goto fail;
1200 }
1201
1202 ret[n] = 0;
1203
1204 if (after_rindex != 0)
1205 p->rindex= after_rindex;
1206
1207 *_ret = ret;
1208 ret = NULL;
1209
1210 if (start)
1211 *start = saved_rindex;
1212
1213 return 0;
1214
1215fail:
1216 dns_packet_rewind(p, saved_rindex);
1217 return r;
1218}
1219
50f1e641
TG
1220static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) {
1221 uint8_t window;
1222 uint8_t length;
1223 const uint8_t *bitmap;
2ad613ad 1224 uint8_t bit = 0;
50f1e641
TG
1225 unsigned i;
1226 bool found = false;
1227 size_t saved_rindex;
1228 int r;
1229
1230 assert(p);
1231 assert(types);
1232
1233 saved_rindex = p->rindex;
1234
1235 r = bitmap_ensure_allocated(types);
1236 if (r < 0)
1237 goto fail;
1238
1239 r = dns_packet_read_uint8(p, &window, NULL);
1240 if (r < 0)
1241 goto fail;
1242
1243 r = dns_packet_read_uint8(p, &length, NULL);
1244 if (r < 0)
1245 goto fail;
1246
1247 if (length == 0 || length > 32)
1248 return -EBADMSG;
1249
1250 r = dns_packet_read(p, length, (const void **)&bitmap, NULL);
1251 if (r < 0)
1252 goto fail;
1253
1254 for (i = 0; i < length; i++) {
1255 uint8_t bitmask = 1 << 7;
50f1e641
TG
1256
1257 if (!bitmap[i]) {
1258 found = false;
2ad613ad 1259 bit += 8;
50f1e641
TG
1260 continue;
1261 }
1262
1263 found = true;
1264
1265 while (bitmask) {
1266 if (bitmap[i] & bitmask) {
1267 uint16_t n;
1268
50f1e641
TG
1269 n = (uint16_t) window << 8 | (uint16_t) bit;
1270
8e6edc49
TG
1271 /* Ignore pseudo-types. see RFC4034 section 4.1.2 */
1272 if (dns_type_is_pseudo(n))
1273 continue;
1274
50f1e641
TG
1275 r = bitmap_set(*types, n);
1276 if (r < 0)
1277 goto fail;
1278 }
1279
1280 bit ++;
1281 bitmask >>= 1;
1282 }
1283 }
1284
1285 if (!found)
1286 return -EBADMSG;
1287
1288 if (start)
1289 *start = saved_rindex;
1290
1291 return 0;
1292fail:
1293 dns_packet_rewind(p, saved_rindex);
1294 return r;
1295}
1296
89492aaf
TG
1297static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
1298 size_t saved_rindex;
1299 int r;
1300
1301 saved_rindex = p->rindex;
1302
1303 while (p->rindex < saved_rindex + size) {
1304 r = dns_packet_read_type_window(p, types, NULL);
1305 if (r < 0)
1306 goto fail;
1307
1308 /* don't read past end of current RR */
1309 if (p->rindex > saved_rindex + size) {
1310 r = -EBADMSG;
1311 goto fail;
1312 }
1313 }
1314
1315 if (p->rindex != saved_rindex + size) {
1316 r = -EBADMSG;
1317 goto fail;
1318 }
1319
1320 if (start)
1321 *start = saved_rindex;
1322
1323 return 0;
1324fail:
1325 dns_packet_rewind(p, saved_rindex);
1326 return r;
1327}
1328
faa133f3
LP
1329int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
1330 _cleanup_free_ char *name = NULL;
1331 uint16_t class, type;
1332 DnsResourceKey *key;
74b2466e
LP
1333 size_t saved_rindex;
1334 int r;
1335
1336 assert(p);
1337 assert(ret);
1338
1339 saved_rindex = p->rindex;
1340
151226ab 1341 r = dns_packet_read_name(p, &name, true, NULL);
74b2466e
LP
1342 if (r < 0)
1343 goto fail;
1344
faa133f3 1345 r = dns_packet_read_uint16(p, &type, NULL);
74b2466e
LP
1346 if (r < 0)
1347 goto fail;
1348
faa133f3 1349 r = dns_packet_read_uint16(p, &class, NULL);
74b2466e
LP
1350 if (r < 0)
1351 goto fail;
1352
faa133f3
LP
1353 key = dns_resource_key_new_consume(class, type, name);
1354 if (!key) {
1355 r = -ENOMEM;
1356 goto fail;
1357 }
1358
1359 name = NULL;
1360 *ret = key;
74b2466e
LP
1361
1362 if (start)
1363 *start = saved_rindex;
1364
1365 return 0;
1366fail:
1367 dns_packet_rewind(p, saved_rindex);
1368 return r;
1369}
1370
afbc4f26
ZJS
1371static bool loc_size_ok(uint8_t size) {
1372 uint8_t m = size >> 4, e = size & 0xF;
1373
1374 return m <= 9 && e <= 9 && (m > 0 || e == 0);
1375}
1376
8db0d2f5 1377static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
3ef77d04
LP
1378 assert(rr);
1379
8db0d2f5
ZJS
1380 if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
1381 return -EBADMSG;
1382
1383 rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
1384 rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
1385 return 0;
1386}
1387
74b2466e 1388int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
faa133f3
LP
1389 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1390 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e
LP
1391 size_t saved_rindex, offset;
1392 uint16_t rdlength;
74b2466e
LP
1393 int r;
1394
1395 assert(p);
1396 assert(ret);
1397
4e0296a9 1398 saved_rindex = p->rindex;
74b2466e 1399
faa133f3 1400 r = dns_packet_read_key(p, &key, NULL);
74b2466e
LP
1401 if (r < 0)
1402 goto fail;
1403
0e2bcd6a
LP
1404 if (key->class == DNS_CLASS_ANY ||
1405 key->type == DNS_TYPE_ANY) {
1406 r = -EBADMSG;
1407 goto fail;
1408 }
1409
faa133f3
LP
1410 rr = dns_resource_record_new(key);
1411 if (!rr) {
1412 r = -ENOMEM;
1413 goto fail;
1414 }
1415
74b2466e
LP
1416 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1417 if (r < 0)
1418 goto fail;
1419
1420 r = dns_packet_read_uint16(p, &rdlength, NULL);
1421 if (r < 0)
1422 goto fail;
1423
1424 if (p->rindex + rdlength > p->size) {
1425 r = -EBADMSG;
1426 goto fail;
1427 }
1428
1429 offset = p->rindex;
1430
faa133f3 1431 switch (rr->key->type) {
74b2466e 1432
9c92ce6d
LP
1433 case DNS_TYPE_SRV:
1434 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1435 if (r < 0)
1436 goto fail;
1437 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1438 if (r < 0)
1439 goto fail;
1440 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1441 if (r < 0)
1442 goto fail;
151226ab 1443 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
9c92ce6d
LP
1444 break;
1445
74b2466e
LP
1446 case DNS_TYPE_PTR:
1447 case DNS_TYPE_NS:
1448 case DNS_TYPE_CNAME:
8ac4e9e1 1449 case DNS_TYPE_DNAME:
151226ab 1450 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1451 break;
1452
1453 case DNS_TYPE_HINFO:
1454 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1455 if (r < 0)
1456 goto fail;
1457
1458 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1459 break;
1460
9de3e329 1461 case DNS_TYPE_SPF: /* exactly the same as TXT */
1ccda9b7
LP
1462 case DNS_TYPE_TXT:
1463 if (rdlength <= 0) {
2001c805 1464 DnsTxtItem *i;
1ccda9b7
LP
1465 /* RFC 6763, section 6.1 suggests to treat
1466 * empty TXT RRs as equivalent to a TXT record
1467 * with a single empty string. */
0e3434ae 1468
2001c805
LP
1469 i = malloc0(offsetof(DnsTxtItem, data) + 1); /* for safety reasons we add an extra NUL byte */
1470 if (!i)
1471 return -ENOMEM;
1472
1473 rr->txt.items = i;
1ccda9b7 1474 } else {
2001c805
LP
1475 DnsTxtItem *last = NULL;
1476
1ccda9b7 1477 while (p->rindex < offset + rdlength) {
2001c805
LP
1478 DnsTxtItem *i;
1479 const void *data;
1480 size_t sz;
2e276efc 1481
2001c805 1482 r = dns_packet_read_raw_string(p, &data, &sz, NULL);
1ccda9b7 1483 if (r < 0)
2001c805 1484 return r;
1ccda9b7 1485
2001c805
LP
1486 i = malloc0(offsetof(DnsTxtItem, data) + sz + 1); /* extra NUL byte at the end */
1487 if (!i)
1488 return -ENOMEM;
1489
1490 memcpy(i->data, data, sz);
1491 i->length = sz;
1492
1493 LIST_INSERT_AFTER(items, rr->txt.items, last, i);
1494 last = i;
1ccda9b7 1495 }
6a6fc3df
LP
1496 }
1497
1498 r = 0;
2e276efc 1499 break;
2e276efc 1500
74b2466e 1501 case DNS_TYPE_A:
623a4c97 1502 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1503 break;
1504
1505 case DNS_TYPE_AAAA:
623a4c97 1506 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1507 break;
1508
7e8e0422 1509 case DNS_TYPE_SOA:
151226ab 1510 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422
LP
1511 if (r < 0)
1512 goto fail;
1513
151226ab 1514 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422
LP
1515 if (r < 0)
1516 goto fail;
1517
1518 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1519 if (r < 0)
1520 goto fail;
1521
1522 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1523 if (r < 0)
1524 goto fail;
1525
1526 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1527 if (r < 0)
1528 goto fail;
1529
1530 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1531 if (r < 0)
1532 goto fail;
1533
1534 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1535 break;
1536
623a4c97 1537 case DNS_TYPE_MX:
946c7094
ZJS
1538 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1539 if (r < 0)
1540 goto fail;
1541
151226ab 1542 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
1543 break;
1544
0dae31d4
ZJS
1545 case DNS_TYPE_LOC: {
1546 uint8_t t;
1547 size_t pos;
1548
1549 r = dns_packet_read_uint8(p, &t, &pos);
1550 if (r < 0)
1551 goto fail;
1552
1553 if (t == 0) {
1554 rr->loc.version = t;
1555
1556 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1557 if (r < 0)
1558 goto fail;
1559
afbc4f26
ZJS
1560 if (!loc_size_ok(rr->loc.size)) {
1561 r = -EBADMSG;
1562 goto fail;
1563 }
1564
0dae31d4
ZJS
1565 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1566 if (r < 0)
1567 goto fail;
1568
afbc4f26
ZJS
1569 if (!loc_size_ok(rr->loc.horiz_pre)) {
1570 r = -EBADMSG;
1571 goto fail;
1572 }
1573
0dae31d4
ZJS
1574 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1575 if (r < 0)
1576 goto fail;
1577
afbc4f26
ZJS
1578 if (!loc_size_ok(rr->loc.vert_pre)) {
1579 r = -EBADMSG;
1580 goto fail;
1581 }
1582
0dae31d4
ZJS
1583 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1584 if (r < 0)
1585 goto fail;
1586
1587 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1588 if (r < 0)
1589 goto fail;
1590
1591 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1592 if (r < 0)
1593 goto fail;
1594
1595 break;
1596 } else {
1597 dns_packet_rewind(p, pos);
1598 rr->unparseable = true;
afbc4f26 1599 goto unparseable;
0dae31d4
ZJS
1600 }
1601 }
1602
abf126a3
TG
1603 case DNS_TYPE_DS:
1604 r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
1605 if (r < 0)
1606 goto fail;
1607
1608 r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
1609 if (r < 0)
1610 goto fail;
1611
1612 r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
1613 if (r < 0)
1614 goto fail;
1615
f5430a3e
LP
1616 r = dns_packet_read_memdup(p, rdlength - 4,
1617 &rr->ds.digest, &rr->ds.digest_size,
1618 NULL);
abf126a3
TG
1619 if (r < 0)
1620 goto fail;
1621
f1d178cc
TG
1622 if (rr->ds.digest_size <= 0) {
1623 /* the accepted size depends on the algorithm, but for now
1624 just ensure that the value is greater than zero */
1625 r = -EBADMSG;
1626 goto fail;
1627 }
1628
abf126a3 1629 break;
623a4c97 1630 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1631 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1632 if (r < 0)
1633 goto fail;
1634
1635 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1636 if (r < 0)
1637 goto fail;
1638
f5430a3e 1639 r = dns_packet_read_memdup(p, rdlength - 2,
549c1a25 1640 &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size,
f5430a3e 1641 NULL);
f1d178cc 1642
549c1a25 1643 if (rr->sshfp.fingerprint_size <= 0) {
f1d178cc
TG
1644 /* the accepted size depends on the algorithm, but for now
1645 just ensure that the value is greater than zero */
1646 r = -EBADMSG;
1647 goto fail;
1648 }
1649
8db0d2f5
ZJS
1650 break;
1651
1652 case DNS_TYPE_DNSKEY: {
1653 uint16_t flags;
1654 uint8_t proto;
1655
1656 r = dns_packet_read_uint16(p, &flags, NULL);
42cc2eeb
LP
1657 if (r < 0)
1658 goto fail;
1659
8db0d2f5
ZJS
1660 r = dnskey_parse_flags(rr, flags);
1661 if (r < 0)
1662 goto fail;
1663
1664 r = dns_packet_read_uint8(p, &proto, NULL);
1665 if (r < 0)
1666 goto fail;
1667
1668 /* protocol is required to be always 3 */
1669 if (proto != 3) {
1670 r = -EBADMSG;
42cc2eeb
LP
1671 goto fail;
1672 }
1673
8db0d2f5
ZJS
1674 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1675 if (r < 0)
1676 goto fail;
1677
f5430a3e
LP
1678 r = dns_packet_read_memdup(p, rdlength - 4,
1679 &rr->dnskey.key, &rr->dnskey.key_size,
1680 NULL);
f1d178cc
TG
1681
1682 if (rr->dnskey.key_size <= 0) {
1683 /* the accepted size depends on the algorithm, but for now
1684 just ensure that the value is greater than zero */
1685 r = -EBADMSG;
1686 goto fail;
1687 }
1688
42cc2eeb 1689 break;
8db0d2f5 1690 }
42cc2eeb 1691
151226ab
ZJS
1692 case DNS_TYPE_RRSIG:
1693 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
1694 if (r < 0)
1695 goto fail;
1696
1697 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
1698 if (r < 0)
1699 goto fail;
1700
1701 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
1702 if (r < 0)
1703 goto fail;
1704
1705 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
1706 if (r < 0)
1707 goto fail;
1708
1709 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
1710 if (r < 0)
1711 goto fail;
1712
1713 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
1714 if (r < 0)
1715 goto fail;
1716
1717 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
1718 if (r < 0)
1719 goto fail;
1720
1721 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
1722 if (r < 0)
1723 goto fail;
1724
f5430a3e
LP
1725 r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
1726 &rr->rrsig.signature, &rr->rrsig.signature_size,
1727 NULL);
f1d178cc
TG
1728
1729 if (rr->rrsig.signature_size <= 0) {
1730 /* the accepted size depends on the algorithm, but for now
1731 just ensure that the value is greater than zero */
1732 r = -EBADMSG;
1733 goto fail;
1734 }
1735
151226ab
ZJS
1736 break;
1737
50f1e641
TG
1738 case DNS_TYPE_NSEC:
1739 r = dns_packet_read_name(p, &rr->nsec.next_domain_name, false, NULL);
1740 if (r < 0)
1741 goto fail;
1742
89492aaf
TG
1743 r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
1744 if (r < 0)
1745 goto fail;
1746
09eaf68c
TG
1747 /* We accept empty NSEC bitmaps. The bit indicating the presence of the NSEC record itself
1748 * is redundant and in e.g., RFC4956 this fact is used to define a use for NSEC records
1749 * without the NSEC bit set. */
50f1e641
TG
1750
1751 break;
5d45a880
TG
1752
1753 case DNS_TYPE_NSEC3: {
1754 uint8_t size;
1755
1756 r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
1757 if (r < 0)
1758 goto fail;
1759
1760 r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
1761 if (r < 0)
1762 goto fail;
1763
1764 r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
1765 if (r < 0)
1766 goto fail;
1767
f1d178cc 1768 /* this may be zero */
5d45a880
TG
1769 r = dns_packet_read_uint8(p, &size, NULL);
1770 if (r < 0)
1771 goto fail;
1772
f5430a3e 1773 r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
5d45a880
TG
1774 if (r < 0)
1775 goto fail;
1776
5d45a880
TG
1777 r = dns_packet_read_uint8(p, &size, NULL);
1778 if (r < 0)
1779 goto fail;
1780
f1d178cc
TG
1781 if (size <= 0) {
1782 r = -EBADMSG;
1783 goto fail;
1784 }
1785
f5430a3e 1786 r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL);
5d45a880
TG
1787 if (r < 0)
1788 goto fail;
1789
6b9308d1 1790 r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL);
5d45a880
TG
1791 if (r < 0)
1792 goto fail;
1793
0bbd72b2
TG
1794 /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
1795
5d45a880
TG
1796 break;
1797 }
74b2466e 1798 default:
afbc4f26 1799 unparseable:
f5430a3e 1800 r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
74b2466e
LP
1801 if (r < 0)
1802 goto fail;
74b2466e
LP
1803 break;
1804 }
1805 if (r < 0)
1806 goto fail;
1807 if (p->rindex != offset + rdlength) {
1808 r = -EBADMSG;
1809 goto fail;
1810 }
1811
1812 *ret = rr;
1813 rr = NULL;
1814
1815 if (start)
1816 *start = saved_rindex;
1817
1818 return 0;
1819fail:
1820 dns_packet_rewind(p, saved_rindex);
1821 return r;
1822}
1823
faa133f3
LP
1824int dns_packet_extract(DnsPacket *p) {
1825 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1826 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1827 size_t saved_rindex;
1828 unsigned n, i;
74b2466e
LP
1829 int r;
1830
a4076574
LP
1831 if (p->extracted)
1832 return 0;
1833
faa133f3 1834 saved_rindex = p->rindex;
322345fd
LP
1835 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1836
3cb10d3a 1837 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
1838 if (n > 0) {
1839 question = dns_question_new(n);
1840 if (!question) {
1841 r = -ENOMEM;
1842 goto finish;
1843 }
74b2466e 1844
faa133f3
LP
1845 for (i = 0; i < n; i++) {
1846 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e 1847
faa133f3
LP
1848 r = dns_packet_read_key(p, &key, NULL);
1849 if (r < 0)
1850 goto finish;
74b2466e 1851
faa133f3
LP
1852 r = dns_question_add(question, key);
1853 if (r < 0)
1854 goto finish;
1855 }
1856 }
322345fd 1857
faa133f3
LP
1858 n = DNS_PACKET_RRCOUNT(p);
1859 if (n > 0) {
1860 answer = dns_answer_new(n);
1861 if (!answer) {
1862 r = -ENOMEM;
1863 goto finish;
1864 }
322345fd 1865
faa133f3
LP
1866 for (i = 0; i < n; i++) {
1867 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
322345fd 1868
faa133f3
LP
1869 r = dns_packet_read_rr(p, &rr, NULL);
1870 if (r < 0)
1871 goto finish;
322345fd 1872
78c6a153 1873 r = dns_answer_add(answer, rr, p->ifindex);
faa133f3
LP
1874 if (r < 0)
1875 goto finish;
1876 }
322345fd
LP
1877 }
1878
faa133f3
LP
1879 p->question = question;
1880 question = NULL;
322345fd 1881
faa133f3
LP
1882 p->answer = answer;
1883 answer = NULL;
322345fd 1884
a4076574
LP
1885 p->extracted = true;
1886
faa133f3 1887 r = 0;
322345fd
LP
1888
1889finish:
1890 p->rindex = saved_rindex;
1891 return r;
1892}
1893
74b2466e
LP
1894static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1895 [DNS_RCODE_SUCCESS] = "SUCCESS",
1896 [DNS_RCODE_FORMERR] = "FORMERR",
1897 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1898 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1899 [DNS_RCODE_NOTIMP] = "NOTIMP",
1900 [DNS_RCODE_REFUSED] = "REFUSED",
1901 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1902 [DNS_RCODE_YXRRSET] = "YRRSET",
1903 [DNS_RCODE_NXRRSET] = "NXRRSET",
1904 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1905 [DNS_RCODE_NOTZONE] = "NOTZONE",
1906 [DNS_RCODE_BADVERS] = "BADVERS",
1907 [DNS_RCODE_BADKEY] = "BADKEY",
1908 [DNS_RCODE_BADTIME] = "BADTIME",
1909 [DNS_RCODE_BADMODE] = "BADMODE",
1910 [DNS_RCODE_BADNAME] = "BADNAME",
1911 [DNS_RCODE_BADALG] = "BADALG",
1912 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1913};
1914DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc
LP
1915
1916static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1917 [DNS_PROTOCOL_DNS] = "dns",
1918 [DNS_PROTOCOL_MDNS] = "mdns",
1919 [DNS_PROTOCOL_LLMNR] = "llmnr",
1920};
1921DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
ff3d6560
ZJS
1922
1923static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
5d45a880
TG
1924 [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
1925 [DNSSEC_ALGORITHM_DH] = "DH",
1926 [DNSSEC_ALGORITHM_DSA] = "DSA",
1927 [DNSSEC_ALGORITHM_ECC] = "ECC",
1928 [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
1929 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1",
1930 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
1931 [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
1932 [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
1933 [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
ff3d6560
ZJS
1934};
1935DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);