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