]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
dns-domain: change dns_srv_type_is_valid() return value to bool
[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) {
1148 _cleanup_free_ char *t = NULL;
1149 const char *label;
1150
1151 /* Literal label */
1152 r = dns_packet_read(p, c, (const void**) &label, NULL);
1153 if (r < 0)
1154 goto fail;
1155
1156 r = dns_label_escape(label, c, &t);
1157 if (r < 0)
1158 goto fail;
1159
1160 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
1161 r = -ENOMEM;
1162 goto fail;
1163 }
1164
1165 if (!first)
1166 ret[n++] = '.';
1167 else
1168 first = false;
1169
85818582 1170 memcpy(ret + n, t, r);
74b2466e
LP
1171 n += r;
1172 continue;
151226ab 1173 } else if (allow_compression && (c & 0xc0) == 0xc0) {
74b2466e
LP
1174 uint16_t ptr;
1175
1176 /* Pointer */
1177 r = dns_packet_read_uint8(p, &d, NULL);
1178 if (r < 0)
1179 goto fail;
1180
1181 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
c75dbf9b 1182 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
74b2466e
LP
1183 r = -EBADMSG;
1184 goto fail;
1185 }
1186
1187 if (after_rindex == 0)
1188 after_rindex = p->rindex;
1189
f131770b 1190 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
c75dbf9b 1191 jump_barrier = ptr;
74b2466e 1192 p->rindex = ptr;
59aa5821
SP
1193 } else {
1194 r = -EBADMSG;
74b2466e 1195 goto fail;
59aa5821 1196 }
74b2466e
LP
1197 }
1198
1199 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
1200 r = -ENOMEM;
1201 goto fail;
1202 }
1203
1204 ret[n] = 0;
1205
1206 if (after_rindex != 0)
1207 p->rindex= after_rindex;
1208
1209 *_ret = ret;
1210 ret = NULL;
1211
1212 if (start)
1213 *start = saved_rindex;
1214
1215 return 0;
1216
1217fail:
1218 dns_packet_rewind(p, saved_rindex);
1219 return r;
1220}
1221
50f1e641
TG
1222static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) {
1223 uint8_t window;
1224 uint8_t length;
1225 const uint8_t *bitmap;
2ad613ad 1226 uint8_t bit = 0;
50f1e641
TG
1227 unsigned i;
1228 bool found = false;
1229 size_t saved_rindex;
1230 int r;
1231
1232 assert(p);
1233 assert(types);
1234
1235 saved_rindex = p->rindex;
1236
1237 r = bitmap_ensure_allocated(types);
1238 if (r < 0)
1239 goto fail;
1240
1241 r = dns_packet_read_uint8(p, &window, NULL);
1242 if (r < 0)
1243 goto fail;
1244
1245 r = dns_packet_read_uint8(p, &length, NULL);
1246 if (r < 0)
1247 goto fail;
1248
1249 if (length == 0 || length > 32)
1250 return -EBADMSG;
1251
1252 r = dns_packet_read(p, length, (const void **)&bitmap, NULL);
1253 if (r < 0)
1254 goto fail;
1255
1256 for (i = 0; i < length; i++) {
1257 uint8_t bitmask = 1 << 7;
50f1e641
TG
1258
1259 if (!bitmap[i]) {
1260 found = false;
2ad613ad 1261 bit += 8;
50f1e641
TG
1262 continue;
1263 }
1264
1265 found = true;
1266
1267 while (bitmask) {
1268 if (bitmap[i] & bitmask) {
1269 uint16_t n;
1270
50f1e641
TG
1271 n = (uint16_t) window << 8 | (uint16_t) bit;
1272
8e6edc49
TG
1273 /* Ignore pseudo-types. see RFC4034 section 4.1.2 */
1274 if (dns_type_is_pseudo(n))
1275 continue;
1276
50f1e641
TG
1277 r = bitmap_set(*types, n);
1278 if (r < 0)
1279 goto fail;
1280 }
1281
1282 bit ++;
1283 bitmask >>= 1;
1284 }
1285 }
1286
1287 if (!found)
1288 return -EBADMSG;
1289
1290 if (start)
1291 *start = saved_rindex;
1292
1293 return 0;
1294fail:
1295 dns_packet_rewind(p, saved_rindex);
1296 return r;
1297}
1298
89492aaf
TG
1299static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
1300 size_t saved_rindex;
1301 int r;
1302
1303 saved_rindex = p->rindex;
1304
1305 while (p->rindex < saved_rindex + size) {
1306 r = dns_packet_read_type_window(p, types, NULL);
1307 if (r < 0)
1308 goto fail;
1309
1310 /* don't read past end of current RR */
1311 if (p->rindex > saved_rindex + size) {
1312 r = -EBADMSG;
1313 goto fail;
1314 }
1315 }
1316
1317 if (p->rindex != saved_rindex + size) {
1318 r = -EBADMSG;
1319 goto fail;
1320 }
1321
1322 if (start)
1323 *start = saved_rindex;
1324
1325 return 0;
1326fail:
1327 dns_packet_rewind(p, saved_rindex);
1328 return r;
1329}
1330
faa133f3
LP
1331int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
1332 _cleanup_free_ char *name = NULL;
1333 uint16_t class, type;
1334 DnsResourceKey *key;
74b2466e
LP
1335 size_t saved_rindex;
1336 int r;
1337
1338 assert(p);
1339 assert(ret);
1340
1341 saved_rindex = p->rindex;
1342
151226ab 1343 r = dns_packet_read_name(p, &name, true, NULL);
74b2466e
LP
1344 if (r < 0)
1345 goto fail;
1346
faa133f3 1347 r = dns_packet_read_uint16(p, &type, NULL);
74b2466e
LP
1348 if (r < 0)
1349 goto fail;
1350
faa133f3 1351 r = dns_packet_read_uint16(p, &class, NULL);
74b2466e
LP
1352 if (r < 0)
1353 goto fail;
1354
faa133f3
LP
1355 key = dns_resource_key_new_consume(class, type, name);
1356 if (!key) {
1357 r = -ENOMEM;
1358 goto fail;
1359 }
1360
1361 name = NULL;
1362 *ret = key;
74b2466e
LP
1363
1364 if (start)
1365 *start = saved_rindex;
1366
1367 return 0;
1368fail:
1369 dns_packet_rewind(p, saved_rindex);
1370 return r;
1371}
1372
afbc4f26
ZJS
1373static bool loc_size_ok(uint8_t size) {
1374 uint8_t m = size >> 4, e = size & 0xF;
1375
1376 return m <= 9 && e <= 9 && (m > 0 || e == 0);
1377}
1378
8db0d2f5 1379static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
3ef77d04
LP
1380 assert(rr);
1381
8db0d2f5
ZJS
1382 if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
1383 return -EBADMSG;
1384
1385 rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
1386 rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
1387 return 0;
1388}
1389
74b2466e 1390int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
faa133f3
LP
1391 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1392 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e
LP
1393 size_t saved_rindex, offset;
1394 uint16_t rdlength;
74b2466e
LP
1395 int r;
1396
1397 assert(p);
1398 assert(ret);
1399
4e0296a9 1400 saved_rindex = p->rindex;
74b2466e 1401
faa133f3 1402 r = dns_packet_read_key(p, &key, NULL);
74b2466e
LP
1403 if (r < 0)
1404 goto fail;
1405
0e2bcd6a
LP
1406 if (key->class == DNS_CLASS_ANY ||
1407 key->type == DNS_TYPE_ANY) {
1408 r = -EBADMSG;
1409 goto fail;
1410 }
1411
faa133f3
LP
1412 rr = dns_resource_record_new(key);
1413 if (!rr) {
1414 r = -ENOMEM;
1415 goto fail;
1416 }
1417
74b2466e
LP
1418 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1419 if (r < 0)
1420 goto fail;
1421
1422 r = dns_packet_read_uint16(p, &rdlength, NULL);
1423 if (r < 0)
1424 goto fail;
1425
1426 if (p->rindex + rdlength > p->size) {
1427 r = -EBADMSG;
1428 goto fail;
1429 }
1430
1431 offset = p->rindex;
1432
faa133f3 1433 switch (rr->key->type) {
74b2466e 1434
9c92ce6d
LP
1435 case DNS_TYPE_SRV:
1436 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1437 if (r < 0)
1438 goto fail;
1439 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1440 if (r < 0)
1441 goto fail;
1442 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1443 if (r < 0)
1444 goto fail;
151226ab 1445 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
9c92ce6d
LP
1446 break;
1447
74b2466e
LP
1448 case DNS_TYPE_PTR:
1449 case DNS_TYPE_NS:
1450 case DNS_TYPE_CNAME:
8ac4e9e1 1451 case DNS_TYPE_DNAME:
151226ab 1452 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1453 break;
1454
1455 case DNS_TYPE_HINFO:
1456 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1457 if (r < 0)
1458 goto fail;
1459
1460 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1461 break;
1462
9de3e329 1463 case DNS_TYPE_SPF: /* exactly the same as TXT */
1ccda9b7
LP
1464 case DNS_TYPE_TXT:
1465 if (rdlength <= 0) {
2001c805 1466 DnsTxtItem *i;
1ccda9b7
LP
1467 /* RFC 6763, section 6.1 suggests to treat
1468 * empty TXT RRs as equivalent to a TXT record
1469 * with a single empty string. */
0e3434ae 1470
2001c805
LP
1471 i = malloc0(offsetof(DnsTxtItem, data) + 1); /* for safety reasons we add an extra NUL byte */
1472 if (!i)
1473 return -ENOMEM;
1474
1475 rr->txt.items = i;
1ccda9b7 1476 } else {
2001c805
LP
1477 DnsTxtItem *last = NULL;
1478
1ccda9b7 1479 while (p->rindex < offset + rdlength) {
2001c805
LP
1480 DnsTxtItem *i;
1481 const void *data;
1482 size_t sz;
2e276efc 1483
2001c805 1484 r = dns_packet_read_raw_string(p, &data, &sz, NULL);
1ccda9b7 1485 if (r < 0)
2001c805 1486 return r;
1ccda9b7 1487
2001c805
LP
1488 i = malloc0(offsetof(DnsTxtItem, data) + sz + 1); /* extra NUL byte at the end */
1489 if (!i)
1490 return -ENOMEM;
1491
1492 memcpy(i->data, data, sz);
1493 i->length = sz;
1494
1495 LIST_INSERT_AFTER(items, rr->txt.items, last, i);
1496 last = i;
1ccda9b7 1497 }
6a6fc3df
LP
1498 }
1499
1500 r = 0;
2e276efc 1501 break;
2e276efc 1502
74b2466e 1503 case DNS_TYPE_A:
623a4c97 1504 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1505 break;
1506
1507 case DNS_TYPE_AAAA:
623a4c97 1508 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1509 break;
1510
7e8e0422 1511 case DNS_TYPE_SOA:
151226ab 1512 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422
LP
1513 if (r < 0)
1514 goto fail;
1515
151226ab 1516 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422
LP
1517 if (r < 0)
1518 goto fail;
1519
1520 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1521 if (r < 0)
1522 goto fail;
1523
1524 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1525 if (r < 0)
1526 goto fail;
1527
1528 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1529 if (r < 0)
1530 goto fail;
1531
1532 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1533 if (r < 0)
1534 goto fail;
1535
1536 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1537 break;
1538
623a4c97 1539 case DNS_TYPE_MX:
946c7094
ZJS
1540 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1541 if (r < 0)
1542 goto fail;
1543
151226ab 1544 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
1545 break;
1546
0dae31d4
ZJS
1547 case DNS_TYPE_LOC: {
1548 uint8_t t;
1549 size_t pos;
1550
1551 r = dns_packet_read_uint8(p, &t, &pos);
1552 if (r < 0)
1553 goto fail;
1554
1555 if (t == 0) {
1556 rr->loc.version = t;
1557
1558 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1559 if (r < 0)
1560 goto fail;
1561
afbc4f26
ZJS
1562 if (!loc_size_ok(rr->loc.size)) {
1563 r = -EBADMSG;
1564 goto fail;
1565 }
1566
0dae31d4
ZJS
1567 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1568 if (r < 0)
1569 goto fail;
1570
afbc4f26
ZJS
1571 if (!loc_size_ok(rr->loc.horiz_pre)) {
1572 r = -EBADMSG;
1573 goto fail;
1574 }
1575
0dae31d4
ZJS
1576 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1577 if (r < 0)
1578 goto fail;
1579
afbc4f26
ZJS
1580 if (!loc_size_ok(rr->loc.vert_pre)) {
1581 r = -EBADMSG;
1582 goto fail;
1583 }
1584
0dae31d4
ZJS
1585 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1586 if (r < 0)
1587 goto fail;
1588
1589 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1590 if (r < 0)
1591 goto fail;
1592
1593 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1594 if (r < 0)
1595 goto fail;
1596
1597 break;
1598 } else {
1599 dns_packet_rewind(p, pos);
1600 rr->unparseable = true;
afbc4f26 1601 goto unparseable;
0dae31d4
ZJS
1602 }
1603 }
1604
abf126a3
TG
1605 case DNS_TYPE_DS:
1606 r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
1607 if (r < 0)
1608 goto fail;
1609
1610 r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
1611 if (r < 0)
1612 goto fail;
1613
1614 r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
1615 if (r < 0)
1616 goto fail;
1617
f5430a3e
LP
1618 r = dns_packet_read_memdup(p, rdlength - 4,
1619 &rr->ds.digest, &rr->ds.digest_size,
1620 NULL);
abf126a3
TG
1621 if (r < 0)
1622 goto fail;
1623
f1d178cc
TG
1624 if (rr->ds.digest_size <= 0) {
1625 /* the accepted size depends on the algorithm, but for now
1626 just ensure that the value is greater than zero */
1627 r = -EBADMSG;
1628 goto fail;
1629 }
1630
abf126a3 1631 break;
623a4c97 1632 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1633 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1634 if (r < 0)
1635 goto fail;
1636
1637 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1638 if (r < 0)
1639 goto fail;
1640
f5430a3e 1641 r = dns_packet_read_memdup(p, rdlength - 2,
549c1a25 1642 &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size,
f5430a3e 1643 NULL);
f1d178cc 1644
549c1a25 1645 if (rr->sshfp.fingerprint_size <= 0) {
f1d178cc
TG
1646 /* the accepted size depends on the algorithm, but for now
1647 just ensure that the value is greater than zero */
1648 r = -EBADMSG;
1649 goto fail;
1650 }
1651
8db0d2f5
ZJS
1652 break;
1653
1654 case DNS_TYPE_DNSKEY: {
1655 uint16_t flags;
1656 uint8_t proto;
1657
1658 r = dns_packet_read_uint16(p, &flags, NULL);
42cc2eeb
LP
1659 if (r < 0)
1660 goto fail;
1661
8db0d2f5
ZJS
1662 r = dnskey_parse_flags(rr, flags);
1663 if (r < 0)
1664 goto fail;
1665
1666 r = dns_packet_read_uint8(p, &proto, NULL);
1667 if (r < 0)
1668 goto fail;
1669
1670 /* protocol is required to be always 3 */
1671 if (proto != 3) {
1672 r = -EBADMSG;
42cc2eeb
LP
1673 goto fail;
1674 }
1675
8db0d2f5
ZJS
1676 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1677 if (r < 0)
1678 goto fail;
1679
f5430a3e
LP
1680 r = dns_packet_read_memdup(p, rdlength - 4,
1681 &rr->dnskey.key, &rr->dnskey.key_size,
1682 NULL);
f1d178cc
TG
1683
1684 if (rr->dnskey.key_size <= 0) {
1685 /* the accepted size depends on the algorithm, but for now
1686 just ensure that the value is greater than zero */
1687 r = -EBADMSG;
1688 goto fail;
1689 }
1690
42cc2eeb 1691 break;
8db0d2f5 1692 }
42cc2eeb 1693
151226ab
ZJS
1694 case DNS_TYPE_RRSIG:
1695 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
1696 if (r < 0)
1697 goto fail;
1698
1699 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
1700 if (r < 0)
1701 goto fail;
1702
1703 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
1704 if (r < 0)
1705 goto fail;
1706
1707 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
1708 if (r < 0)
1709 goto fail;
1710
1711 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
1712 if (r < 0)
1713 goto fail;
1714
1715 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
1716 if (r < 0)
1717 goto fail;
1718
1719 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
1720 if (r < 0)
1721 goto fail;
1722
1723 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
1724 if (r < 0)
1725 goto fail;
1726
f5430a3e
LP
1727 r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
1728 &rr->rrsig.signature, &rr->rrsig.signature_size,
1729 NULL);
f1d178cc
TG
1730
1731 if (rr->rrsig.signature_size <= 0) {
1732 /* the accepted size depends on the algorithm, but for now
1733 just ensure that the value is greater than zero */
1734 r = -EBADMSG;
1735 goto fail;
1736 }
1737
151226ab
ZJS
1738 break;
1739
50f1e641
TG
1740 case DNS_TYPE_NSEC:
1741 r = dns_packet_read_name(p, &rr->nsec.next_domain_name, false, NULL);
1742 if (r < 0)
1743 goto fail;
1744
89492aaf
TG
1745 r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
1746 if (r < 0)
1747 goto fail;
1748
bfcc6709
TG
1749 /* The types bitmap must contain at least the NSEC record itself, so an empty bitmap means
1750 something went wrong */
1751 if (bitmap_isclear(rr->nsec.types)) {
1752 r = -EBADMSG;
1753 goto fail;
1754 }
50f1e641
TG
1755
1756 break;
5d45a880
TG
1757
1758 case DNS_TYPE_NSEC3: {
1759 uint8_t size;
1760
1761 r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
1762 if (r < 0)
1763 goto fail;
1764
1765 r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
1766 if (r < 0)
1767 goto fail;
1768
1769 r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
1770 if (r < 0)
1771 goto fail;
1772
f1d178cc 1773 /* this may be zero */
5d45a880
TG
1774 r = dns_packet_read_uint8(p, &size, NULL);
1775 if (r < 0)
1776 goto fail;
1777
f5430a3e 1778 r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
5d45a880
TG
1779 if (r < 0)
1780 goto fail;
1781
5d45a880
TG
1782 r = dns_packet_read_uint8(p, &size, NULL);
1783 if (r < 0)
1784 goto fail;
1785
f1d178cc
TG
1786 if (size <= 0) {
1787 r = -EBADMSG;
1788 goto fail;
1789 }
1790
f5430a3e 1791 r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL);
5d45a880
TG
1792 if (r < 0)
1793 goto fail;
1794
6b9308d1 1795 r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL);
5d45a880
TG
1796 if (r < 0)
1797 goto fail;
1798
0bbd72b2
TG
1799 /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
1800
5d45a880
TG
1801 break;
1802 }
74b2466e 1803 default:
afbc4f26 1804 unparseable:
f5430a3e 1805 r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
74b2466e
LP
1806 if (r < 0)
1807 goto fail;
74b2466e
LP
1808 break;
1809 }
1810 if (r < 0)
1811 goto fail;
1812 if (p->rindex != offset + rdlength) {
1813 r = -EBADMSG;
1814 goto fail;
1815 }
1816
1817 *ret = rr;
1818 rr = NULL;
1819
1820 if (start)
1821 *start = saved_rindex;
1822
1823 return 0;
1824fail:
1825 dns_packet_rewind(p, saved_rindex);
1826 return r;
1827}
1828
faa133f3
LP
1829int dns_packet_extract(DnsPacket *p) {
1830 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1831 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1832 size_t saved_rindex;
1833 unsigned n, i;
74b2466e
LP
1834 int r;
1835
a4076574
LP
1836 if (p->extracted)
1837 return 0;
1838
faa133f3 1839 saved_rindex = p->rindex;
322345fd
LP
1840 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1841
3cb10d3a 1842 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
1843 if (n > 0) {
1844 question = dns_question_new(n);
1845 if (!question) {
1846 r = -ENOMEM;
1847 goto finish;
1848 }
74b2466e 1849
faa133f3
LP
1850 for (i = 0; i < n; i++) {
1851 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e 1852
faa133f3
LP
1853 r = dns_packet_read_key(p, &key, NULL);
1854 if (r < 0)
1855 goto finish;
74b2466e 1856
faa133f3
LP
1857 r = dns_question_add(question, key);
1858 if (r < 0)
1859 goto finish;
1860 }
1861 }
322345fd 1862
faa133f3
LP
1863 n = DNS_PACKET_RRCOUNT(p);
1864 if (n > 0) {
1865 answer = dns_answer_new(n);
1866 if (!answer) {
1867 r = -ENOMEM;
1868 goto finish;
1869 }
322345fd 1870
faa133f3
LP
1871 for (i = 0; i < n; i++) {
1872 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
322345fd 1873
faa133f3
LP
1874 r = dns_packet_read_rr(p, &rr, NULL);
1875 if (r < 0)
1876 goto finish;
322345fd 1877
78c6a153 1878 r = dns_answer_add(answer, rr, p->ifindex);
faa133f3
LP
1879 if (r < 0)
1880 goto finish;
1881 }
322345fd
LP
1882 }
1883
faa133f3
LP
1884 p->question = question;
1885 question = NULL;
322345fd 1886
faa133f3
LP
1887 p->answer = answer;
1888 answer = NULL;
322345fd 1889
a4076574
LP
1890 p->extracted = true;
1891
faa133f3 1892 r = 0;
322345fd
LP
1893
1894finish:
1895 p->rindex = saved_rindex;
1896 return r;
1897}
1898
74b2466e
LP
1899static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1900 [DNS_RCODE_SUCCESS] = "SUCCESS",
1901 [DNS_RCODE_FORMERR] = "FORMERR",
1902 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1903 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1904 [DNS_RCODE_NOTIMP] = "NOTIMP",
1905 [DNS_RCODE_REFUSED] = "REFUSED",
1906 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1907 [DNS_RCODE_YXRRSET] = "YRRSET",
1908 [DNS_RCODE_NXRRSET] = "NXRRSET",
1909 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1910 [DNS_RCODE_NOTZONE] = "NOTZONE",
1911 [DNS_RCODE_BADVERS] = "BADVERS",
1912 [DNS_RCODE_BADKEY] = "BADKEY",
1913 [DNS_RCODE_BADTIME] = "BADTIME",
1914 [DNS_RCODE_BADMODE] = "BADMODE",
1915 [DNS_RCODE_BADNAME] = "BADNAME",
1916 [DNS_RCODE_BADALG] = "BADALG",
1917 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1918};
1919DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc
LP
1920
1921static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1922 [DNS_PROTOCOL_DNS] = "dns",
1923 [DNS_PROTOCOL_MDNS] = "mdns",
1924 [DNS_PROTOCOL_LLMNR] = "llmnr",
1925};
1926DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
ff3d6560
ZJS
1927
1928static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
5d45a880
TG
1929 [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
1930 [DNSSEC_ALGORITHM_DH] = "DH",
1931 [DNSSEC_ALGORITHM_DSA] = "DSA",
1932 [DNSSEC_ALGORITHM_ECC] = "ECC",
1933 [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
1934 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1",
1935 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
1936 [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
1937 [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
1938 [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
ff3d6560
ZJS
1939};
1940DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);