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