]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
dns-domain: add code for verifying validity of DNS-SD service names and types
[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
373int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
374 void *w;
375 int r;
376
377 assert(p);
378 assert(d);
379
380 if (l > DNS_LABEL_MAX)
381 return -E2BIG;
382
383 r = dns_packet_extend(p, 1 + l, &w, start);
384 if (r < 0)
385 return r;
386
387 ((uint8_t*) w)[0] = (uint8_t) l;
388 memcpy(((uint8_t*) w) + 1, d, l);
389
390 return 0;
391}
392
f6a5fec6
LP
393int dns_packet_append_name(
394 DnsPacket *p,
395 const char *name,
396 bool allow_compression,
397 size_t *start) {
398
74b2466e
LP
399 size_t saved_size;
400 int r;
401
402 assert(p);
403 assert(name);
404
f6a5fec6
LP
405 if (p->refuse_compression)
406 allow_compression = false;
407
74b2466e
LP
408 saved_size = p->size;
409
410 while (*name) {
411 _cleanup_free_ char *s = NULL;
412 char label[DNS_LABEL_MAX];
151226ab 413 size_t n = 0;
bdf10b5b 414 int k;
74b2466e 415
151226ab
ZJS
416 if (allow_compression)
417 n = PTR_TO_SIZE(hashmap_get(p->names, name));
74b2466e
LP
418 if (n > 0) {
419 assert(n < p->size);
420
421 if (n < 0x4000) {
422 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
423 if (r < 0)
424 goto fail;
425
426 goto done;
427 }
428 }
429
430 s = strdup(name);
431 if (!s) {
432 r = -ENOMEM;
433 goto fail;
434 }
435
436 r = dns_label_unescape(&name, label, sizeof(label));
437 if (r < 0)
438 goto fail;
439
bdf10b5b
LP
440 if (p->protocol == DNS_PROTOCOL_DNS)
441 k = dns_label_apply_idna(label, r, label, sizeof(label));
442 else
443 k = dns_label_undo_idna(label, r, label, sizeof(label));
444 if (k < 0) {
445 r = k;
446 goto fail;
447 }
448 if (k > 0)
449 r = k;
450
74b2466e
LP
451 r = dns_packet_append_label(p, label, r, &n);
452 if (r < 0)
453 goto fail;
454
151226ab 455 if (allow_compression) {
d5099efc 456 r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops);
151226ab
ZJS
457 if (r < 0)
458 goto fail;
74b2466e 459
151226ab
ZJS
460 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
461 if (r < 0)
462 goto fail;
74b2466e 463
151226ab
ZJS
464 s = NULL;
465 }
74b2466e
LP
466 }
467
468 r = dns_packet_append_uint8(p, 0, NULL);
469 if (r < 0)
470 return r;
471
472done:
473 if (start)
474 *start = saved_size;
475
476 return 0;
477
478fail:
479 dns_packet_truncate(p, saved_size);
480 return r;
481}
482
483int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
484 size_t saved_size;
485 int r;
486
487 assert(p);
488 assert(k);
489
490 saved_size = p->size;
491
151226ab 492 r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, NULL);
74b2466e
LP
493 if (r < 0)
494 goto fail;
495
496 r = dns_packet_append_uint16(p, k->type, NULL);
497 if (r < 0)
498 goto fail;
499
500 r = dns_packet_append_uint16(p, k->class, NULL);
501 if (r < 0)
502 goto fail;
503
504 if (start)
505 *start = saved_size;
506
507 return 0;
508
509fail:
510 dns_packet_truncate(p, saved_size);
511 return r;
512}
513
50f1e641
TG
514static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, uint8_t *types, size_t *start) {
515 size_t saved_size;
516 int r;
517
518 assert(p);
519 assert(types);
1792f223 520 assert(length > 0);
50f1e641 521
50f1e641
TG
522 saved_size = p->size;
523
1792f223
TG
524 r = dns_packet_append_uint8(p, window, NULL);
525 if (r < 0)
526 goto fail;
50f1e641 527
1792f223
TG
528 r = dns_packet_append_uint8(p, length, NULL);
529 if (r < 0)
530 goto fail;
6fa91901 531
1792f223
TG
532 r = dns_packet_append_blob(p, types, length, NULL);
533 if (r < 0)
534 goto fail;
50f1e641
TG
535
536 if (start)
537 *start = saved_size;
538
539 return 0;
540fail:
541 dns_packet_truncate(p, saved_size);
542 return r;
543}
544
545static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
cb57dd41 546 Iterator i;
50f1e641 547 uint8_t window = 0;
1792f223 548 uint8_t entry = 0;
50f1e641
TG
549 uint8_t bitmaps[32] = {};
550 unsigned n;
551 size_t saved_size;
552 int r;
553
554 assert(p);
555 assert(types);
556
557 saved_size = p->size;
558
cb57dd41 559 BITMAP_FOREACH(n, types, i) {
50f1e641
TG
560 assert(n <= 0xffff);
561
1792f223
TG
562 if ((n >> 8) != window && bitmaps[entry / 8] != 0) {
563 r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
50f1e641
TG
564 if (r < 0)
565 goto fail;
566
1792f223 567 zero(bitmaps);
50f1e641
TG
568 }
569
1792f223 570 window = n >> 8;
50f1e641
TG
571
572 entry = n & 255;
573
574 bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
575 }
576
1792f223 577 r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
50f1e641
TG
578 if (r < 0)
579 goto fail;
580
581 if (start)
582 *start = saved_size;
583
584 return 0;
585fail:
586 dns_packet_truncate(p, saved_size);
587 return r;
588}
589
623a4c97
LP
590int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
591 size_t saved_size, rdlength_offset, end, rdlength;
592 int r;
593
594 assert(p);
595 assert(rr);
596
597 saved_size = p->size;
598
599 r = dns_packet_append_key(p, rr->key, NULL);
600 if (r < 0)
601 goto fail;
602
603 r = dns_packet_append_uint32(p, rr->ttl, NULL);
604 if (r < 0)
605 goto fail;
606
607 /* Initially we write 0 here */
608 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
609 if (r < 0)
610 goto fail;
611
0dae31d4 612 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
623a4c97 613
9c92ce6d
LP
614 case DNS_TYPE_SRV:
615 r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
616 if (r < 0)
617 goto fail;
618
619 r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
620 if (r < 0)
621 goto fail;
622
623 r = dns_packet_append_uint16(p, rr->srv.port, NULL);
624 if (r < 0)
625 goto fail;
626
151226ab 627 r = dns_packet_append_name(p, rr->srv.name, true, NULL);
9c92ce6d
LP
628 break;
629
623a4c97
LP
630 case DNS_TYPE_PTR:
631 case DNS_TYPE_NS:
632 case DNS_TYPE_CNAME:
8ac4e9e1 633 case DNS_TYPE_DNAME:
151226ab 634 r = dns_packet_append_name(p, rr->ptr.name, true, NULL);
623a4c97
LP
635 break;
636
637 case DNS_TYPE_HINFO:
638 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
639 if (r < 0)
640 goto fail;
641
642 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
643 break;
644
9de3e329 645 case DNS_TYPE_SPF: /* exactly the same as TXT */
2e276efc
ZJS
646 case DNS_TYPE_TXT: {
647 char **s;
648
1ccda9b7
LP
649 if (strv_isempty(rr->txt.strings)) {
650 /* RFC 6763, section 6.1 suggests to generate
651 * single empty string for an empty array. */
652
653 r = dns_packet_append_string(p, "", NULL);
2e276efc
ZJS
654 if (r < 0)
655 goto fail;
1ccda9b7
LP
656 } else {
657 STRV_FOREACH(s, rr->txt.strings) {
658 r = dns_packet_append_string(p, *s, NULL);
659 if (r < 0)
660 goto fail;
661 }
2e276efc
ZJS
662 }
663
6a6fc3df 664 r = 0;
2e276efc
ZJS
665 break;
666 }
667
623a4c97
LP
668 case DNS_TYPE_A:
669 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
670 break;
671
672 case DNS_TYPE_AAAA:
673 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
674 break;
675
676 case DNS_TYPE_SOA:
151226ab 677 r = dns_packet_append_name(p, rr->soa.mname, true, NULL);
623a4c97
LP
678 if (r < 0)
679 goto fail;
680
151226ab 681 r = dns_packet_append_name(p, rr->soa.rname, true, NULL);
623a4c97
LP
682 if (r < 0)
683 goto fail;
684
685 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
686 if (r < 0)
687 goto fail;
688
689 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
690 if (r < 0)
691 goto fail;
692
693 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
694 if (r < 0)
695 goto fail;
696
697 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
698 if (r < 0)
699 goto fail;
700
701 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
702 break;
703
704 case DNS_TYPE_MX:
946c7094
ZJS
705 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
706 if (r < 0)
707 goto fail;
708
151226ab 709 r = dns_packet_append_name(p, rr->mx.exchange, true, NULL);
946c7094
ZJS
710 break;
711
0dae31d4
ZJS
712 case DNS_TYPE_LOC:
713 r = dns_packet_append_uint8(p, rr->loc.version, NULL);
714 if (r < 0)
715 goto fail;
716
717 r = dns_packet_append_uint8(p, rr->loc.size, NULL);
718 if (r < 0)
719 goto fail;
720
721 r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
722 if (r < 0)
723 goto fail;
724
725 r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
726 if (r < 0)
727 goto fail;
728
afbc4f26 729 r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
0dae31d4
ZJS
730 if (r < 0)
731 goto fail;
732
afbc4f26 733 r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
0dae31d4
ZJS
734 if (r < 0)
735 goto fail;
736
afbc4f26 737 r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
0dae31d4
ZJS
738 break;
739
abf126a3
TG
740 case DNS_TYPE_DS:
741 r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL);
742 if (r < 0)
743 goto fail;
744
745 r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL);
746 if (r < 0)
747 goto fail;
748
749 r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL);
750 if (r < 0)
751 goto fail;
752
753 r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL);
754 break;
755
623a4c97 756 case DNS_TYPE_SSHFP:
42cc2eeb
LP
757 r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
758 if (r < 0)
759 goto fail;
8db0d2f5 760
42cc2eeb
LP
761 r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
762 if (r < 0)
763 goto fail;
764
549c1a25 765 r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL);
42cc2eeb
LP
766 break;
767
8db0d2f5
ZJS
768 case DNS_TYPE_DNSKEY:
769 r = dns_packet_append_uint16(p, dnskey_to_flags(rr), NULL);
770 if (r < 0)
771 goto fail;
772
773 r = dns_packet_append_uint8(p, 3u, NULL);
774 if (r < 0)
775 goto fail;
776
777 r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
778 if (r < 0)
779 goto fail;
780
781 r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
782 break;
783
151226ab
ZJS
784 case DNS_TYPE_RRSIG:
785 r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
786 if (r < 0)
787 goto fail;
788
789 r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
790 if (r < 0)
791 goto fail;
792
793 r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
794 if (r < 0)
795 goto fail;
796
797 r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
798 if (r < 0)
799 goto fail;
800
801 r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
802 if (r < 0)
803 goto fail;
804
805 r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
806 if (r < 0)
807 goto fail;
808
0b1b17d3 809 r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL);
151226ab
ZJS
810 if (r < 0)
811 goto fail;
812
813 r = dns_packet_append_name(p, rr->rrsig.signer, false, NULL);
814 if (r < 0)
815 goto fail;
816
817 r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
818 break;
819
50f1e641
TG
820 case DNS_TYPE_NSEC:
821 r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, NULL);
822 if (r < 0)
823 goto fail;
824
825 r = dns_packet_append_types(p, rr->nsec.types, NULL);
826 if (r < 0)
827 goto fail;
828
5d45a880
TG
829 break;
830 case DNS_TYPE_NSEC3:
831 r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL);
832 if (r < 0)
833 goto fail;
834
835 r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL);
836 if (r < 0)
837 goto fail;
838
839 r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL);
840 if (r < 0)
841 goto fail;
842
843 r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL);
844 if (r < 0)
845 goto fail;
846
847 r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL);
848 if (r < 0)
849 goto fail;
850
851 r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL);
852 if (r < 0)
853 goto fail;
854
855 r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL);
856 if (r < 0)
857 goto fail;
858
859 r = dns_packet_append_types(p, rr->nsec3.types, NULL);
860 if (r < 0)
861 goto fail;
862
50f1e641 863 break;
0dae31d4 864 case _DNS_TYPE_INVALID: /* unparseable */
623a4c97 865 default:
0dae31d4 866
623a4c97
LP
867 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
868 break;
869 }
870 if (r < 0)
871 goto fail;
872
873 /* Let's calculate the actual data size and update the field */
874 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
875 if (rdlength > 0xFFFF) {
876 r = ENOSPC;
877 goto fail;
878 }
879
880 end = p->size;
881 p->size = rdlength_offset;
882 r = dns_packet_append_uint16(p, rdlength, NULL);
883 if (r < 0)
884 goto fail;
885 p->size = end;
886
351e6342
LP
887 if (start)
888 *start = saved_size;
889
623a4c97
LP
890 return 0;
891
892fail:
893 dns_packet_truncate(p, saved_size);
894 return r;
895}
896
897
74b2466e
LP
898int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
899 assert(p);
900
901 if (p->rindex + sz > p->size)
902 return -EMSGSIZE;
903
904 if (ret)
905 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
906
907 if (start)
908 *start = p->rindex;
909
910 p->rindex += sz;
911 return 0;
912}
913
8ba9fd9c 914void dns_packet_rewind(DnsPacket *p, size_t idx) {
74b2466e
LP
915 assert(p);
916 assert(idx <= p->size);
917 assert(idx >= DNS_PACKET_HEADER_SIZE);
918
919 p->rindex = idx;
920}
921
623a4c97
LP
922int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
923 const void *q;
924 int r;
925
926 assert(p);
927 assert(d);
928
929 r = dns_packet_read(p, sz, &q, start);
930 if (r < 0)
931 return r;
932
933 memcpy(d, q, sz);
934 return 0;
935}
936
f5430a3e
LP
937static int dns_packet_read_memdup(
938 DnsPacket *p, size_t size,
939 void **ret, size_t *ret_size,
940 size_t *ret_start) {
941
942 const void *src;
943 size_t start;
944 int r;
945
946 assert(p);
947 assert(ret);
948
949 r = dns_packet_read(p, size, &src, &start);
950 if (r < 0)
951 return r;
952
953 if (size <= 0)
954 *ret = NULL;
955 else {
956 void *copy;
957
958 copy = memdup(src, size);
959 if (!copy)
960 return -ENOMEM;
961
962 *ret = copy;
963 }
964
965 if (ret_size)
966 *ret_size = size;
967 if (ret_start)
968 *ret_start = start;
969
970 return 0;
971}
972
74b2466e
LP
973int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
974 const void *d;
975 int r;
976
977 assert(p);
978
979 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
980 if (r < 0)
981 return r;
982
983 *ret = ((uint8_t*) d)[0];
984 return 0;
985}
986
987int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
988 const void *d;
989 int r;
990
991 assert(p);
992
993 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
994 if (r < 0)
995 return r;
996
725ca0e5
TG
997 *ret = unaligned_read_be16(d);
998
74b2466e
LP
999 return 0;
1000}
1001
1002int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
1003 const void *d;
1004 int r;
1005
1006 assert(p);
1007
1008 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
1009 if (r < 0)
1010 return r;
1011
725ca0e5 1012 *ret = unaligned_read_be32(d);
74b2466e
LP
1013
1014 return 0;
1015}
1016
1017int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
1018 size_t saved_rindex;
1019 const void *d;
1020 char *t;
1021 uint8_t c;
1022 int r;
1023
1024 assert(p);
1025
1026 saved_rindex = p->rindex;
1027
1028 r = dns_packet_read_uint8(p, &c, NULL);
1029 if (r < 0)
1030 goto fail;
1031
1032 r = dns_packet_read(p, c, &d, NULL);
1033 if (r < 0)
1034 goto fail;
1035
1036 if (memchr(d, 0, c)) {
1037 r = -EBADMSG;
1038 goto fail;
1039 }
1040
1041 t = strndup(d, c);
1042 if (!t) {
1043 r = -ENOMEM;
1044 goto fail;
1045 }
1046
1047 if (!utf8_is_valid(t)) {
1048 free(t);
1049 r = -EBADMSG;
1050 goto fail;
1051 }
1052
1053 *ret = t;
1054
1055 if (start)
1056 *start = saved_rindex;
1057
1058 return 0;
1059
1060fail:
1061 dns_packet_rewind(p, saved_rindex);
1062 return r;
1063}
1064
f6a5fec6
LP
1065int dns_packet_read_name(
1066 DnsPacket *p,
1067 char **_ret,
1068 bool allow_compression,
1069 size_t *start) {
1070
c75dbf9b 1071 size_t saved_rindex, after_rindex = 0, jump_barrier;
74b2466e
LP
1072 _cleanup_free_ char *ret = NULL;
1073 size_t n = 0, allocated = 0;
1074 bool first = true;
1075 int r;
1076
1077 assert(p);
1078 assert(_ret);
1079
f6a5fec6
LP
1080 if (p->refuse_compression)
1081 allow_compression = false;
1082
74b2466e 1083 saved_rindex = p->rindex;
c75dbf9b 1084 jump_barrier = p->rindex;
74b2466e
LP
1085
1086 for (;;) {
1087 uint8_t c, d;
1088
1089 r = dns_packet_read_uint8(p, &c, NULL);
1090 if (r < 0)
1091 goto fail;
1092
1093 if (c == 0)
1094 /* End of name */
1095 break;
1096 else if (c <= 63) {
1097 _cleanup_free_ char *t = NULL;
1098 const char *label;
1099
1100 /* Literal label */
1101 r = dns_packet_read(p, c, (const void**) &label, NULL);
1102 if (r < 0)
1103 goto fail;
1104
1105 r = dns_label_escape(label, c, &t);
1106 if (r < 0)
1107 goto fail;
1108
1109 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
1110 r = -ENOMEM;
1111 goto fail;
1112 }
1113
1114 if (!first)
1115 ret[n++] = '.';
1116 else
1117 first = false;
1118
85818582 1119 memcpy(ret + n, t, r);
74b2466e
LP
1120 n += r;
1121 continue;
151226ab 1122 } else if (allow_compression && (c & 0xc0) == 0xc0) {
74b2466e
LP
1123 uint16_t ptr;
1124
1125 /* Pointer */
1126 r = dns_packet_read_uint8(p, &d, NULL);
1127 if (r < 0)
1128 goto fail;
1129
1130 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
c75dbf9b 1131 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
74b2466e
LP
1132 r = -EBADMSG;
1133 goto fail;
1134 }
1135
1136 if (after_rindex == 0)
1137 after_rindex = p->rindex;
1138
f131770b 1139 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
c75dbf9b 1140 jump_barrier = ptr;
74b2466e 1141 p->rindex = ptr;
59aa5821
SP
1142 } else {
1143 r = -EBADMSG;
74b2466e 1144 goto fail;
59aa5821 1145 }
74b2466e
LP
1146 }
1147
1148 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
1149 r = -ENOMEM;
1150 goto fail;
1151 }
1152
1153 ret[n] = 0;
1154
1155 if (after_rindex != 0)
1156 p->rindex= after_rindex;
1157
1158 *_ret = ret;
1159 ret = NULL;
1160
1161 if (start)
1162 *start = saved_rindex;
1163
1164 return 0;
1165
1166fail:
1167 dns_packet_rewind(p, saved_rindex);
1168 return r;
1169}
1170
50f1e641
TG
1171static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) {
1172 uint8_t window;
1173 uint8_t length;
1174 const uint8_t *bitmap;
2ad613ad 1175 uint8_t bit = 0;
50f1e641
TG
1176 unsigned i;
1177 bool found = false;
1178 size_t saved_rindex;
1179 int r;
1180
1181 assert(p);
1182 assert(types);
1183
1184 saved_rindex = p->rindex;
1185
1186 r = bitmap_ensure_allocated(types);
1187 if (r < 0)
1188 goto fail;
1189
1190 r = dns_packet_read_uint8(p, &window, NULL);
1191 if (r < 0)
1192 goto fail;
1193
1194 r = dns_packet_read_uint8(p, &length, NULL);
1195 if (r < 0)
1196 goto fail;
1197
1198 if (length == 0 || length > 32)
1199 return -EBADMSG;
1200
1201 r = dns_packet_read(p, length, (const void **)&bitmap, NULL);
1202 if (r < 0)
1203 goto fail;
1204
1205 for (i = 0; i < length; i++) {
1206 uint8_t bitmask = 1 << 7;
50f1e641
TG
1207
1208 if (!bitmap[i]) {
1209 found = false;
2ad613ad 1210 bit += 8;
50f1e641
TG
1211 continue;
1212 }
1213
1214 found = true;
1215
1216 while (bitmask) {
1217 if (bitmap[i] & bitmask) {
1218 uint16_t n;
1219
50f1e641
TG
1220 n = (uint16_t) window << 8 | (uint16_t) bit;
1221
8e6edc49
TG
1222 /* Ignore pseudo-types. see RFC4034 section 4.1.2 */
1223 if (dns_type_is_pseudo(n))
1224 continue;
1225
50f1e641
TG
1226 r = bitmap_set(*types, n);
1227 if (r < 0)
1228 goto fail;
1229 }
1230
1231 bit ++;
1232 bitmask >>= 1;
1233 }
1234 }
1235
1236 if (!found)
1237 return -EBADMSG;
1238
1239 if (start)
1240 *start = saved_rindex;
1241
1242 return 0;
1243fail:
1244 dns_packet_rewind(p, saved_rindex);
1245 return r;
1246}
1247
89492aaf
TG
1248static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
1249 size_t saved_rindex;
1250 int r;
1251
1252 saved_rindex = p->rindex;
1253
1254 while (p->rindex < saved_rindex + size) {
1255 r = dns_packet_read_type_window(p, types, NULL);
1256 if (r < 0)
1257 goto fail;
1258
1259 /* don't read past end of current RR */
1260 if (p->rindex > saved_rindex + size) {
1261 r = -EBADMSG;
1262 goto fail;
1263 }
1264 }
1265
1266 if (p->rindex != saved_rindex + size) {
1267 r = -EBADMSG;
1268 goto fail;
1269 }
1270
1271 if (start)
1272 *start = saved_rindex;
1273
1274 return 0;
1275fail:
1276 dns_packet_rewind(p, saved_rindex);
1277 return r;
1278}
1279
faa133f3
LP
1280int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
1281 _cleanup_free_ char *name = NULL;
1282 uint16_t class, type;
1283 DnsResourceKey *key;
74b2466e
LP
1284 size_t saved_rindex;
1285 int r;
1286
1287 assert(p);
1288 assert(ret);
1289
1290 saved_rindex = p->rindex;
1291
151226ab 1292 r = dns_packet_read_name(p, &name, true, NULL);
74b2466e
LP
1293 if (r < 0)
1294 goto fail;
1295
faa133f3 1296 r = dns_packet_read_uint16(p, &type, NULL);
74b2466e
LP
1297 if (r < 0)
1298 goto fail;
1299
faa133f3 1300 r = dns_packet_read_uint16(p, &class, NULL);
74b2466e
LP
1301 if (r < 0)
1302 goto fail;
1303
faa133f3
LP
1304 key = dns_resource_key_new_consume(class, type, name);
1305 if (!key) {
1306 r = -ENOMEM;
1307 goto fail;
1308 }
1309
1310 name = NULL;
1311 *ret = key;
74b2466e
LP
1312
1313 if (start)
1314 *start = saved_rindex;
1315
1316 return 0;
1317fail:
1318 dns_packet_rewind(p, saved_rindex);
1319 return r;
1320}
1321
afbc4f26
ZJS
1322static bool loc_size_ok(uint8_t size) {
1323 uint8_t m = size >> 4, e = size & 0xF;
1324
1325 return m <= 9 && e <= 9 && (m > 0 || e == 0);
1326}
1327
8db0d2f5 1328static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
3ef77d04
LP
1329 assert(rr);
1330
8db0d2f5
ZJS
1331 if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
1332 return -EBADMSG;
1333
1334 rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
1335 rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
1336 return 0;
1337}
1338
74b2466e 1339int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
faa133f3
LP
1340 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1341 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e
LP
1342 size_t saved_rindex, offset;
1343 uint16_t rdlength;
74b2466e
LP
1344 int r;
1345
1346 assert(p);
1347 assert(ret);
1348
4e0296a9 1349 saved_rindex = p->rindex;
74b2466e 1350
faa133f3 1351 r = dns_packet_read_key(p, &key, NULL);
74b2466e
LP
1352 if (r < 0)
1353 goto fail;
1354
0e2bcd6a
LP
1355 if (key->class == DNS_CLASS_ANY ||
1356 key->type == DNS_TYPE_ANY) {
1357 r = -EBADMSG;
1358 goto fail;
1359 }
1360
faa133f3
LP
1361 rr = dns_resource_record_new(key);
1362 if (!rr) {
1363 r = -ENOMEM;
1364 goto fail;
1365 }
1366
74b2466e
LP
1367 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1368 if (r < 0)
1369 goto fail;
1370
1371 r = dns_packet_read_uint16(p, &rdlength, NULL);
1372 if (r < 0)
1373 goto fail;
1374
1375 if (p->rindex + rdlength > p->size) {
1376 r = -EBADMSG;
1377 goto fail;
1378 }
1379
1380 offset = p->rindex;
1381
faa133f3 1382 switch (rr->key->type) {
74b2466e 1383
9c92ce6d
LP
1384 case DNS_TYPE_SRV:
1385 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1386 if (r < 0)
1387 goto fail;
1388 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1389 if (r < 0)
1390 goto fail;
1391 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1392 if (r < 0)
1393 goto fail;
151226ab 1394 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
9c92ce6d
LP
1395 break;
1396
74b2466e
LP
1397 case DNS_TYPE_PTR:
1398 case DNS_TYPE_NS:
1399 case DNS_TYPE_CNAME:
8ac4e9e1 1400 case DNS_TYPE_DNAME:
151226ab 1401 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1402 break;
1403
1404 case DNS_TYPE_HINFO:
1405 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1406 if (r < 0)
1407 goto fail;
1408
1409 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1410 break;
1411
9de3e329 1412 case DNS_TYPE_SPF: /* exactly the same as TXT */
1ccda9b7
LP
1413 case DNS_TYPE_TXT:
1414 if (rdlength <= 0) {
1415 /* RFC 6763, section 6.1 suggests to treat
1416 * empty TXT RRs as equivalent to a TXT record
1417 * with a single empty string. */
0e3434ae 1418
1ccda9b7 1419 r = strv_extend(&rr->txt.strings, "");
2e276efc
ZJS
1420 if (r < 0)
1421 goto fail;
1ccda9b7
LP
1422 } else {
1423 while (p->rindex < offset + rdlength) {
1424 char *s;
2e276efc 1425
1ccda9b7
LP
1426 r = dns_packet_read_string(p, &s, NULL);
1427 if (r < 0)
1428 goto fail;
1429
1430 r = strv_consume(&rr->txt.strings, s);
1431 if (r < 0)
1432 goto fail;
1433 }
6a6fc3df
LP
1434 }
1435
1436 r = 0;
2e276efc 1437 break;
2e276efc 1438
74b2466e 1439 case DNS_TYPE_A:
623a4c97 1440 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1441 break;
1442
1443 case DNS_TYPE_AAAA:
623a4c97 1444 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1445 break;
1446
7e8e0422 1447 case DNS_TYPE_SOA:
151226ab 1448 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422
LP
1449 if (r < 0)
1450 goto fail;
1451
151226ab 1452 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422
LP
1453 if (r < 0)
1454 goto fail;
1455
1456 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1457 if (r < 0)
1458 goto fail;
1459
1460 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1461 if (r < 0)
1462 goto fail;
1463
1464 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1465 if (r < 0)
1466 goto fail;
1467
1468 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1469 if (r < 0)
1470 goto fail;
1471
1472 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1473 break;
1474
623a4c97 1475 case DNS_TYPE_MX:
946c7094
ZJS
1476 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1477 if (r < 0)
1478 goto fail;
1479
151226ab 1480 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
1481 break;
1482
0dae31d4
ZJS
1483 case DNS_TYPE_LOC: {
1484 uint8_t t;
1485 size_t pos;
1486
1487 r = dns_packet_read_uint8(p, &t, &pos);
1488 if (r < 0)
1489 goto fail;
1490
1491 if (t == 0) {
1492 rr->loc.version = t;
1493
1494 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1495 if (r < 0)
1496 goto fail;
1497
afbc4f26
ZJS
1498 if (!loc_size_ok(rr->loc.size)) {
1499 r = -EBADMSG;
1500 goto fail;
1501 }
1502
0dae31d4
ZJS
1503 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1504 if (r < 0)
1505 goto fail;
1506
afbc4f26
ZJS
1507 if (!loc_size_ok(rr->loc.horiz_pre)) {
1508 r = -EBADMSG;
1509 goto fail;
1510 }
1511
0dae31d4
ZJS
1512 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1513 if (r < 0)
1514 goto fail;
1515
afbc4f26
ZJS
1516 if (!loc_size_ok(rr->loc.vert_pre)) {
1517 r = -EBADMSG;
1518 goto fail;
1519 }
1520
0dae31d4
ZJS
1521 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1522 if (r < 0)
1523 goto fail;
1524
1525 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1526 if (r < 0)
1527 goto fail;
1528
1529 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1530 if (r < 0)
1531 goto fail;
1532
1533 break;
1534 } else {
1535 dns_packet_rewind(p, pos);
1536 rr->unparseable = true;
afbc4f26 1537 goto unparseable;
0dae31d4
ZJS
1538 }
1539 }
1540
abf126a3
TG
1541 case DNS_TYPE_DS:
1542 r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
1543 if (r < 0)
1544 goto fail;
1545
1546 r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
1547 if (r < 0)
1548 goto fail;
1549
1550 r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
1551 if (r < 0)
1552 goto fail;
1553
f5430a3e
LP
1554 r = dns_packet_read_memdup(p, rdlength - 4,
1555 &rr->ds.digest, &rr->ds.digest_size,
1556 NULL);
abf126a3
TG
1557 if (r < 0)
1558 goto fail;
1559
f1d178cc
TG
1560 if (rr->ds.digest_size <= 0) {
1561 /* the accepted size depends on the algorithm, but for now
1562 just ensure that the value is greater than zero */
1563 r = -EBADMSG;
1564 goto fail;
1565 }
1566
abf126a3 1567 break;
623a4c97 1568 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1569 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1570 if (r < 0)
1571 goto fail;
1572
1573 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1574 if (r < 0)
1575 goto fail;
1576
f5430a3e 1577 r = dns_packet_read_memdup(p, rdlength - 2,
549c1a25 1578 &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size,
f5430a3e 1579 NULL);
f1d178cc 1580
549c1a25 1581 if (rr->sshfp.fingerprint_size <= 0) {
f1d178cc
TG
1582 /* the accepted size depends on the algorithm, but for now
1583 just ensure that the value is greater than zero */
1584 r = -EBADMSG;
1585 goto fail;
1586 }
1587
8db0d2f5
ZJS
1588 break;
1589
1590 case DNS_TYPE_DNSKEY: {
1591 uint16_t flags;
1592 uint8_t proto;
1593
1594 r = dns_packet_read_uint16(p, &flags, NULL);
42cc2eeb
LP
1595 if (r < 0)
1596 goto fail;
1597
8db0d2f5
ZJS
1598 r = dnskey_parse_flags(rr, flags);
1599 if (r < 0)
1600 goto fail;
1601
1602 r = dns_packet_read_uint8(p, &proto, NULL);
1603 if (r < 0)
1604 goto fail;
1605
1606 /* protocol is required to be always 3 */
1607 if (proto != 3) {
1608 r = -EBADMSG;
42cc2eeb
LP
1609 goto fail;
1610 }
1611
8db0d2f5
ZJS
1612 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1613 if (r < 0)
1614 goto fail;
1615
f5430a3e
LP
1616 r = dns_packet_read_memdup(p, rdlength - 4,
1617 &rr->dnskey.key, &rr->dnskey.key_size,
1618 NULL);
f1d178cc
TG
1619
1620 if (rr->dnskey.key_size <= 0) {
1621 /* the accepted size depends on the algorithm, but for now
1622 just ensure that the value is greater than zero */
1623 r = -EBADMSG;
1624 goto fail;
1625 }
1626
42cc2eeb 1627 break;
8db0d2f5 1628 }
42cc2eeb 1629
151226ab
ZJS
1630 case DNS_TYPE_RRSIG:
1631 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
1632 if (r < 0)
1633 goto fail;
1634
1635 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
1636 if (r < 0)
1637 goto fail;
1638
1639 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
1640 if (r < 0)
1641 goto fail;
1642
1643 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
1644 if (r < 0)
1645 goto fail;
1646
1647 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
1648 if (r < 0)
1649 goto fail;
1650
1651 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
1652 if (r < 0)
1653 goto fail;
1654
1655 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
1656 if (r < 0)
1657 goto fail;
1658
1659 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
1660 if (r < 0)
1661 goto fail;
1662
f5430a3e
LP
1663 r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
1664 &rr->rrsig.signature, &rr->rrsig.signature_size,
1665 NULL);
f1d178cc
TG
1666
1667 if (rr->rrsig.signature_size <= 0) {
1668 /* the accepted size depends on the algorithm, but for now
1669 just ensure that the value is greater than zero */
1670 r = -EBADMSG;
1671 goto fail;
1672 }
1673
151226ab
ZJS
1674 break;
1675
50f1e641
TG
1676 case DNS_TYPE_NSEC:
1677 r = dns_packet_read_name(p, &rr->nsec.next_domain_name, false, NULL);
1678 if (r < 0)
1679 goto fail;
1680
89492aaf
TG
1681 r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
1682 if (r < 0)
1683 goto fail;
1684
bfcc6709
TG
1685 /* The types bitmap must contain at least the NSEC record itself, so an empty bitmap means
1686 something went wrong */
1687 if (bitmap_isclear(rr->nsec.types)) {
1688 r = -EBADMSG;
1689 goto fail;
1690 }
50f1e641
TG
1691
1692 break;
5d45a880
TG
1693
1694 case DNS_TYPE_NSEC3: {
1695 uint8_t size;
1696
1697 r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
1698 if (r < 0)
1699 goto fail;
1700
1701 r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
1702 if (r < 0)
1703 goto fail;
1704
1705 r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
1706 if (r < 0)
1707 goto fail;
1708
f1d178cc 1709 /* this may be zero */
5d45a880
TG
1710 r = dns_packet_read_uint8(p, &size, NULL);
1711 if (r < 0)
1712 goto fail;
1713
f5430a3e 1714 r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
5d45a880
TG
1715 if (r < 0)
1716 goto fail;
1717
5d45a880
TG
1718 r = dns_packet_read_uint8(p, &size, NULL);
1719 if (r < 0)
1720 goto fail;
1721
f1d178cc
TG
1722 if (size <= 0) {
1723 r = -EBADMSG;
1724 goto fail;
1725 }
1726
f5430a3e 1727 r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL);
5d45a880
TG
1728 if (r < 0)
1729 goto fail;
1730
6b9308d1 1731 r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL);
5d45a880
TG
1732 if (r < 0)
1733 goto fail;
1734
0bbd72b2
TG
1735 /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
1736
5d45a880
TG
1737 break;
1738 }
74b2466e 1739 default:
afbc4f26 1740 unparseable:
f5430a3e 1741 r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
74b2466e
LP
1742 if (r < 0)
1743 goto fail;
74b2466e
LP
1744 break;
1745 }
1746 if (r < 0)
1747 goto fail;
1748 if (p->rindex != offset + rdlength) {
1749 r = -EBADMSG;
1750 goto fail;
1751 }
1752
1753 *ret = rr;
1754 rr = NULL;
1755
1756 if (start)
1757 *start = saved_rindex;
1758
1759 return 0;
1760fail:
1761 dns_packet_rewind(p, saved_rindex);
1762 return r;
1763}
1764
faa133f3
LP
1765int dns_packet_extract(DnsPacket *p) {
1766 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1767 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1768 size_t saved_rindex;
1769 unsigned n, i;
74b2466e
LP
1770 int r;
1771
a4076574
LP
1772 if (p->extracted)
1773 return 0;
1774
faa133f3 1775 saved_rindex = p->rindex;
322345fd
LP
1776 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1777
3cb10d3a 1778 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
1779 if (n > 0) {
1780 question = dns_question_new(n);
1781 if (!question) {
1782 r = -ENOMEM;
1783 goto finish;
1784 }
74b2466e 1785
faa133f3
LP
1786 for (i = 0; i < n; i++) {
1787 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e 1788
faa133f3
LP
1789 r = dns_packet_read_key(p, &key, NULL);
1790 if (r < 0)
1791 goto finish;
74b2466e 1792
faa133f3
LP
1793 r = dns_question_add(question, key);
1794 if (r < 0)
1795 goto finish;
1796 }
1797 }
322345fd 1798
faa133f3
LP
1799 n = DNS_PACKET_RRCOUNT(p);
1800 if (n > 0) {
1801 answer = dns_answer_new(n);
1802 if (!answer) {
1803 r = -ENOMEM;
1804 goto finish;
1805 }
322345fd 1806
faa133f3
LP
1807 for (i = 0; i < n; i++) {
1808 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
322345fd 1809
faa133f3
LP
1810 r = dns_packet_read_rr(p, &rr, NULL);
1811 if (r < 0)
1812 goto finish;
322345fd 1813
78c6a153 1814 r = dns_answer_add(answer, rr, p->ifindex);
faa133f3
LP
1815 if (r < 0)
1816 goto finish;
1817 }
322345fd
LP
1818 }
1819
faa133f3
LP
1820 p->question = question;
1821 question = NULL;
322345fd 1822
faa133f3
LP
1823 p->answer = answer;
1824 answer = NULL;
322345fd 1825
a4076574
LP
1826 p->extracted = true;
1827
faa133f3 1828 r = 0;
322345fd
LP
1829
1830finish:
1831 p->rindex = saved_rindex;
1832 return r;
1833}
1834
74b2466e
LP
1835static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1836 [DNS_RCODE_SUCCESS] = "SUCCESS",
1837 [DNS_RCODE_FORMERR] = "FORMERR",
1838 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1839 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1840 [DNS_RCODE_NOTIMP] = "NOTIMP",
1841 [DNS_RCODE_REFUSED] = "REFUSED",
1842 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1843 [DNS_RCODE_YXRRSET] = "YRRSET",
1844 [DNS_RCODE_NXRRSET] = "NXRRSET",
1845 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1846 [DNS_RCODE_NOTZONE] = "NOTZONE",
1847 [DNS_RCODE_BADVERS] = "BADVERS",
1848 [DNS_RCODE_BADKEY] = "BADKEY",
1849 [DNS_RCODE_BADTIME] = "BADTIME",
1850 [DNS_RCODE_BADMODE] = "BADMODE",
1851 [DNS_RCODE_BADNAME] = "BADNAME",
1852 [DNS_RCODE_BADALG] = "BADALG",
1853 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1854};
1855DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc
LP
1856
1857static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1858 [DNS_PROTOCOL_DNS] = "dns",
1859 [DNS_PROTOCOL_MDNS] = "mdns",
1860 [DNS_PROTOCOL_LLMNR] = "llmnr",
1861};
1862DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
ff3d6560
ZJS
1863
1864static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
5d45a880
TG
1865 [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
1866 [DNSSEC_ALGORITHM_DH] = "DH",
1867 [DNSSEC_ALGORITHM_DSA] = "DSA",
1868 [DNSSEC_ALGORITHM_ECC] = "ECC",
1869 [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
1870 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1",
1871 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
1872 [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
1873 [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
1874 [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
ff3d6560
ZJS
1875};
1876DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);