]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
resolved: rr - ignore pseudo types in NSEC(3) bitmaps
[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
278 HASHMAP_FOREACH_KEY(s, n, p->names, i) {
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);
511
50f1e641
TG
512 saved_size = p->size;
513
6fa91901 514 if (length != 0) {
50f1e641 515
6fa91901
LP
516 r = dns_packet_append_uint8(p, window, NULL);
517 if (r < 0)
518 goto fail;
50f1e641 519
6fa91901
LP
520 r = dns_packet_append_uint8(p, length, NULL);
521 if (r < 0)
522 goto fail;
523
524 r = dns_packet_append_blob(p, types, length, NULL);
525 if (r < 0)
526 goto fail;
527 }
50f1e641
TG
528
529 if (start)
530 *start = saved_size;
531
532 return 0;
533fail:
534 dns_packet_truncate(p, saved_size);
535 return r;
536}
537
538static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
cb57dd41 539 Iterator i;
50f1e641
TG
540 uint8_t window = 0;
541 uint8_t len = 0;
542 uint8_t bitmaps[32] = {};
543 unsigned n;
544 size_t saved_size;
545 int r;
546
547 assert(p);
548 assert(types);
549
550 saved_size = p->size;
551
cb57dd41 552 BITMAP_FOREACH(n, types, i) {
50f1e641
TG
553 uint8_t entry;
554
555 assert(n <= 0xffff);
556
557 if ((n << 8) != window) {
558 r = dns_packet_append_type_window(p, window, len, bitmaps, NULL);
559 if (r < 0)
560 goto fail;
561
562 if (len > 0) {
563 len = 0;
564 zero(bitmaps);
565 }
566 }
567
568 window = n << 8;
569 len ++;
570
571 entry = n & 255;
572
573 bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
574 }
575
576 r = dns_packet_append_type_window(p, window, len, bitmaps, NULL);
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
151226ab
ZJS
1064int dns_packet_read_name(DnsPacket *p, char **_ret,
1065 bool allow_compression, size_t *start) {
c75dbf9b 1066 size_t saved_rindex, after_rindex = 0, jump_barrier;
74b2466e
LP
1067 _cleanup_free_ char *ret = NULL;
1068 size_t n = 0, allocated = 0;
1069 bool first = true;
1070 int r;
1071
1072 assert(p);
1073 assert(_ret);
1074
1075 saved_rindex = p->rindex;
c75dbf9b 1076 jump_barrier = p->rindex;
74b2466e
LP
1077
1078 for (;;) {
1079 uint8_t c, d;
1080
1081 r = dns_packet_read_uint8(p, &c, NULL);
1082 if (r < 0)
1083 goto fail;
1084
1085 if (c == 0)
1086 /* End of name */
1087 break;
1088 else if (c <= 63) {
1089 _cleanup_free_ char *t = NULL;
1090 const char *label;
1091
1092 /* Literal label */
1093 r = dns_packet_read(p, c, (const void**) &label, NULL);
1094 if (r < 0)
1095 goto fail;
1096
1097 r = dns_label_escape(label, c, &t);
1098 if (r < 0)
1099 goto fail;
1100
1101 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
1102 r = -ENOMEM;
1103 goto fail;
1104 }
1105
1106 if (!first)
1107 ret[n++] = '.';
1108 else
1109 first = false;
1110
85818582 1111 memcpy(ret + n, t, r);
74b2466e
LP
1112 n += r;
1113 continue;
151226ab 1114 } else if (allow_compression && (c & 0xc0) == 0xc0) {
74b2466e
LP
1115 uint16_t ptr;
1116
1117 /* Pointer */
1118 r = dns_packet_read_uint8(p, &d, NULL);
1119 if (r < 0)
1120 goto fail;
1121
1122 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
c75dbf9b 1123 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
74b2466e
LP
1124 r = -EBADMSG;
1125 goto fail;
1126 }
1127
1128 if (after_rindex == 0)
1129 after_rindex = p->rindex;
1130
f131770b 1131 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
c75dbf9b 1132 jump_barrier = ptr;
74b2466e 1133 p->rindex = ptr;
59aa5821
SP
1134 } else {
1135 r = -EBADMSG;
74b2466e 1136 goto fail;
59aa5821 1137 }
74b2466e
LP
1138 }
1139
1140 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
1141 r = -ENOMEM;
1142 goto fail;
1143 }
1144
1145 ret[n] = 0;
1146
1147 if (after_rindex != 0)
1148 p->rindex= after_rindex;
1149
1150 *_ret = ret;
1151 ret = NULL;
1152
1153 if (start)
1154 *start = saved_rindex;
1155
1156 return 0;
1157
1158fail:
1159 dns_packet_rewind(p, saved_rindex);
1160 return r;
1161}
1162
50f1e641
TG
1163static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) {
1164 uint8_t window;
1165 uint8_t length;
1166 const uint8_t *bitmap;
1167 unsigned i;
1168 bool found = false;
1169 size_t saved_rindex;
1170 int r;
1171
1172 assert(p);
1173 assert(types);
1174
1175 saved_rindex = p->rindex;
1176
1177 r = bitmap_ensure_allocated(types);
1178 if (r < 0)
1179 goto fail;
1180
1181 r = dns_packet_read_uint8(p, &window, NULL);
1182 if (r < 0)
1183 goto fail;
1184
1185 r = dns_packet_read_uint8(p, &length, NULL);
1186 if (r < 0)
1187 goto fail;
1188
1189 if (length == 0 || length > 32)
1190 return -EBADMSG;
1191
1192 r = dns_packet_read(p, length, (const void **)&bitmap, NULL);
1193 if (r < 0)
1194 goto fail;
1195
1196 for (i = 0; i < length; i++) {
1197 uint8_t bitmask = 1 << 7;
1198 uint8_t bit = 0;
1199
1200 if (!bitmap[i]) {
1201 found = false;
1202 continue;
1203 }
1204
1205 found = true;
1206
1207 while (bitmask) {
1208 if (bitmap[i] & bitmask) {
1209 uint16_t n;
1210
50f1e641
TG
1211 n = (uint16_t) window << 8 | (uint16_t) bit;
1212
8e6edc49
TG
1213 /* Ignore pseudo-types. see RFC4034 section 4.1.2 */
1214 if (dns_type_is_pseudo(n))
1215 continue;
1216
50f1e641
TG
1217 r = bitmap_set(*types, n);
1218 if (r < 0)
1219 goto fail;
1220 }
1221
1222 bit ++;
1223 bitmask >>= 1;
1224 }
1225 }
1226
1227 if (!found)
1228 return -EBADMSG;
1229
1230 if (start)
1231 *start = saved_rindex;
1232
1233 return 0;
1234fail:
1235 dns_packet_rewind(p, saved_rindex);
1236 return r;
1237}
1238
89492aaf
TG
1239static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
1240 size_t saved_rindex;
1241 int r;
1242
1243 saved_rindex = p->rindex;
1244
1245 while (p->rindex < saved_rindex + size) {
1246 r = dns_packet_read_type_window(p, types, NULL);
1247 if (r < 0)
1248 goto fail;
1249
1250 /* don't read past end of current RR */
1251 if (p->rindex > saved_rindex + size) {
1252 r = -EBADMSG;
1253 goto fail;
1254 }
1255 }
1256
1257 if (p->rindex != saved_rindex + size) {
1258 r = -EBADMSG;
1259 goto fail;
1260 }
1261
1262 if (start)
1263 *start = saved_rindex;
1264
1265 return 0;
1266fail:
1267 dns_packet_rewind(p, saved_rindex);
1268 return r;
1269}
1270
faa133f3
LP
1271int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
1272 _cleanup_free_ char *name = NULL;
1273 uint16_t class, type;
1274 DnsResourceKey *key;
74b2466e
LP
1275 size_t saved_rindex;
1276 int r;
1277
1278 assert(p);
1279 assert(ret);
1280
1281 saved_rindex = p->rindex;
1282
151226ab 1283 r = dns_packet_read_name(p, &name, true, NULL);
74b2466e
LP
1284 if (r < 0)
1285 goto fail;
1286
faa133f3 1287 r = dns_packet_read_uint16(p, &type, NULL);
74b2466e
LP
1288 if (r < 0)
1289 goto fail;
1290
faa133f3 1291 r = dns_packet_read_uint16(p, &class, NULL);
74b2466e
LP
1292 if (r < 0)
1293 goto fail;
1294
faa133f3
LP
1295 key = dns_resource_key_new_consume(class, type, name);
1296 if (!key) {
1297 r = -ENOMEM;
1298 goto fail;
1299 }
1300
1301 name = NULL;
1302 *ret = key;
74b2466e
LP
1303
1304 if (start)
1305 *start = saved_rindex;
1306
1307 return 0;
1308fail:
1309 dns_packet_rewind(p, saved_rindex);
1310 return r;
1311}
1312
afbc4f26
ZJS
1313static bool loc_size_ok(uint8_t size) {
1314 uint8_t m = size >> 4, e = size & 0xF;
1315
1316 return m <= 9 && e <= 9 && (m > 0 || e == 0);
1317}
1318
8db0d2f5 1319static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
3ef77d04
LP
1320 assert(rr);
1321
8db0d2f5
ZJS
1322 if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
1323 return -EBADMSG;
1324
1325 rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
1326 rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
1327 return 0;
1328}
1329
74b2466e 1330int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
faa133f3
LP
1331 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1332 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e
LP
1333 size_t saved_rindex, offset;
1334 uint16_t rdlength;
74b2466e
LP
1335 int r;
1336
1337 assert(p);
1338 assert(ret);
1339
4e0296a9 1340 saved_rindex = p->rindex;
74b2466e 1341
faa133f3 1342 r = dns_packet_read_key(p, &key, NULL);
74b2466e
LP
1343 if (r < 0)
1344 goto fail;
1345
0e2bcd6a
LP
1346 if (key->class == DNS_CLASS_ANY ||
1347 key->type == DNS_TYPE_ANY) {
1348 r = -EBADMSG;
1349 goto fail;
1350 }
1351
faa133f3
LP
1352 rr = dns_resource_record_new(key);
1353 if (!rr) {
1354 r = -ENOMEM;
1355 goto fail;
1356 }
1357
74b2466e
LP
1358 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1359 if (r < 0)
1360 goto fail;
1361
1362 r = dns_packet_read_uint16(p, &rdlength, NULL);
1363 if (r < 0)
1364 goto fail;
1365
1366 if (p->rindex + rdlength > p->size) {
1367 r = -EBADMSG;
1368 goto fail;
1369 }
1370
1371 offset = p->rindex;
1372
faa133f3 1373 switch (rr->key->type) {
74b2466e 1374
9c92ce6d
LP
1375 case DNS_TYPE_SRV:
1376 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1377 if (r < 0)
1378 goto fail;
1379 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1380 if (r < 0)
1381 goto fail;
1382 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1383 if (r < 0)
1384 goto fail;
151226ab 1385 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
9c92ce6d
LP
1386 break;
1387
74b2466e
LP
1388 case DNS_TYPE_PTR:
1389 case DNS_TYPE_NS:
1390 case DNS_TYPE_CNAME:
8ac4e9e1 1391 case DNS_TYPE_DNAME:
151226ab 1392 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1393 break;
1394
1395 case DNS_TYPE_HINFO:
1396 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1397 if (r < 0)
1398 goto fail;
1399
1400 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1401 break;
1402
9de3e329 1403 case DNS_TYPE_SPF: /* exactly the same as TXT */
1ccda9b7
LP
1404 case DNS_TYPE_TXT:
1405 if (rdlength <= 0) {
1406 /* RFC 6763, section 6.1 suggests to treat
1407 * empty TXT RRs as equivalent to a TXT record
1408 * with a single empty string. */
0e3434ae 1409
1ccda9b7 1410 r = strv_extend(&rr->txt.strings, "");
2e276efc
ZJS
1411 if (r < 0)
1412 goto fail;
1ccda9b7
LP
1413 } else {
1414 while (p->rindex < offset + rdlength) {
1415 char *s;
2e276efc 1416
1ccda9b7
LP
1417 r = dns_packet_read_string(p, &s, NULL);
1418 if (r < 0)
1419 goto fail;
1420
1421 r = strv_consume(&rr->txt.strings, s);
1422 if (r < 0)
1423 goto fail;
1424 }
6a6fc3df
LP
1425 }
1426
1427 r = 0;
2e276efc 1428 break;
2e276efc 1429
74b2466e 1430 case DNS_TYPE_A:
623a4c97 1431 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1432 break;
1433
1434 case DNS_TYPE_AAAA:
623a4c97 1435 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1436 break;
1437
7e8e0422 1438 case DNS_TYPE_SOA:
151226ab 1439 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422
LP
1440 if (r < 0)
1441 goto fail;
1442
151226ab 1443 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422
LP
1444 if (r < 0)
1445 goto fail;
1446
1447 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1448 if (r < 0)
1449 goto fail;
1450
1451 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1452 if (r < 0)
1453 goto fail;
1454
1455 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1456 if (r < 0)
1457 goto fail;
1458
1459 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1460 if (r < 0)
1461 goto fail;
1462
1463 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1464 break;
1465
623a4c97 1466 case DNS_TYPE_MX:
946c7094
ZJS
1467 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1468 if (r < 0)
1469 goto fail;
1470
151226ab 1471 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
1472 break;
1473
0dae31d4
ZJS
1474 case DNS_TYPE_LOC: {
1475 uint8_t t;
1476 size_t pos;
1477
1478 r = dns_packet_read_uint8(p, &t, &pos);
1479 if (r < 0)
1480 goto fail;
1481
1482 if (t == 0) {
1483 rr->loc.version = t;
1484
1485 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1486 if (r < 0)
1487 goto fail;
1488
afbc4f26
ZJS
1489 if (!loc_size_ok(rr->loc.size)) {
1490 r = -EBADMSG;
1491 goto fail;
1492 }
1493
0dae31d4
ZJS
1494 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1495 if (r < 0)
1496 goto fail;
1497
afbc4f26
ZJS
1498 if (!loc_size_ok(rr->loc.horiz_pre)) {
1499 r = -EBADMSG;
1500 goto fail;
1501 }
1502
0dae31d4
ZJS
1503 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1504 if (r < 0)
1505 goto fail;
1506
afbc4f26
ZJS
1507 if (!loc_size_ok(rr->loc.vert_pre)) {
1508 r = -EBADMSG;
1509 goto fail;
1510 }
1511
0dae31d4
ZJS
1512 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1513 if (r < 0)
1514 goto fail;
1515
1516 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1517 if (r < 0)
1518 goto fail;
1519
1520 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1521 if (r < 0)
1522 goto fail;
1523
1524 break;
1525 } else {
1526 dns_packet_rewind(p, pos);
1527 rr->unparseable = true;
afbc4f26 1528 goto unparseable;
0dae31d4
ZJS
1529 }
1530 }
1531
abf126a3
TG
1532 case DNS_TYPE_DS:
1533 r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
1534 if (r < 0)
1535 goto fail;
1536
1537 r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
1538 if (r < 0)
1539 goto fail;
1540
1541 r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
1542 if (r < 0)
1543 goto fail;
1544
f5430a3e
LP
1545 r = dns_packet_read_memdup(p, rdlength - 4,
1546 &rr->ds.digest, &rr->ds.digest_size,
1547 NULL);
abf126a3
TG
1548 if (r < 0)
1549 goto fail;
1550
f1d178cc
TG
1551 if (rr->ds.digest_size <= 0) {
1552 /* the accepted size depends on the algorithm, but for now
1553 just ensure that the value is greater than zero */
1554 r = -EBADMSG;
1555 goto fail;
1556 }
1557
abf126a3 1558 break;
623a4c97 1559 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1560 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1561 if (r < 0)
1562 goto fail;
1563
1564 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1565 if (r < 0)
1566 goto fail;
1567
f5430a3e 1568 r = dns_packet_read_memdup(p, rdlength - 2,
549c1a25 1569 &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size,
f5430a3e 1570 NULL);
f1d178cc 1571
549c1a25 1572 if (rr->sshfp.fingerprint_size <= 0) {
f1d178cc
TG
1573 /* the accepted size depends on the algorithm, but for now
1574 just ensure that the value is greater than zero */
1575 r = -EBADMSG;
1576 goto fail;
1577 }
1578
8db0d2f5
ZJS
1579 break;
1580
1581 case DNS_TYPE_DNSKEY: {
1582 uint16_t flags;
1583 uint8_t proto;
1584
1585 r = dns_packet_read_uint16(p, &flags, NULL);
42cc2eeb
LP
1586 if (r < 0)
1587 goto fail;
1588
8db0d2f5
ZJS
1589 r = dnskey_parse_flags(rr, flags);
1590 if (r < 0)
1591 goto fail;
1592
1593 r = dns_packet_read_uint8(p, &proto, NULL);
1594 if (r < 0)
1595 goto fail;
1596
1597 /* protocol is required to be always 3 */
1598 if (proto != 3) {
1599 r = -EBADMSG;
42cc2eeb
LP
1600 goto fail;
1601 }
1602
8db0d2f5
ZJS
1603 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1604 if (r < 0)
1605 goto fail;
1606
f5430a3e
LP
1607 r = dns_packet_read_memdup(p, rdlength - 4,
1608 &rr->dnskey.key, &rr->dnskey.key_size,
1609 NULL);
f1d178cc
TG
1610
1611 if (rr->dnskey.key_size <= 0) {
1612 /* the accepted size depends on the algorithm, but for now
1613 just ensure that the value is greater than zero */
1614 r = -EBADMSG;
1615 goto fail;
1616 }
1617
42cc2eeb 1618 break;
8db0d2f5 1619 }
42cc2eeb 1620
151226ab
ZJS
1621 case DNS_TYPE_RRSIG:
1622 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
1623 if (r < 0)
1624 goto fail;
1625
1626 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
1627 if (r < 0)
1628 goto fail;
1629
1630 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
1631 if (r < 0)
1632 goto fail;
1633
1634 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
1635 if (r < 0)
1636 goto fail;
1637
1638 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
1639 if (r < 0)
1640 goto fail;
1641
1642 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
1643 if (r < 0)
1644 goto fail;
1645
1646 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
1647 if (r < 0)
1648 goto fail;
1649
1650 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
1651 if (r < 0)
1652 goto fail;
1653
f5430a3e
LP
1654 r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
1655 &rr->rrsig.signature, &rr->rrsig.signature_size,
1656 NULL);
f1d178cc
TG
1657
1658 if (rr->rrsig.signature_size <= 0) {
1659 /* the accepted size depends on the algorithm, but for now
1660 just ensure that the value is greater than zero */
1661 r = -EBADMSG;
1662 goto fail;
1663 }
1664
151226ab
ZJS
1665 break;
1666
50f1e641
TG
1667 case DNS_TYPE_NSEC:
1668 r = dns_packet_read_name(p, &rr->nsec.next_domain_name, false, NULL);
1669 if (r < 0)
1670 goto fail;
1671
89492aaf
TG
1672 r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
1673 if (r < 0)
1674 goto fail;
1675
1676 /* NSEC RRs with empty bitmpas makes no sense, but the RFC does not explicitly forbid them
1677 so we allow it */
50f1e641
TG
1678
1679 break;
5d45a880
TG
1680
1681 case DNS_TYPE_NSEC3: {
1682 uint8_t size;
1683
1684 r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
1685 if (r < 0)
1686 goto fail;
1687
1688 r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
1689 if (r < 0)
1690 goto fail;
1691
1692 r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
1693 if (r < 0)
1694 goto fail;
1695
f1d178cc 1696 /* this may be zero */
5d45a880
TG
1697 r = dns_packet_read_uint8(p, &size, NULL);
1698 if (r < 0)
1699 goto fail;
1700
f5430a3e 1701 r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
5d45a880
TG
1702 if (r < 0)
1703 goto fail;
1704
5d45a880
TG
1705 r = dns_packet_read_uint8(p, &size, NULL);
1706 if (r < 0)
1707 goto fail;
1708
f1d178cc
TG
1709 if (size <= 0) {
1710 r = -EBADMSG;
1711 goto fail;
1712 }
1713
f5430a3e 1714 r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL);
5d45a880
TG
1715 if (r < 0)
1716 goto fail;
1717
0bbd72b2 1718 r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
5d45a880
TG
1719 if (r < 0)
1720 goto fail;
1721
0bbd72b2
TG
1722 /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
1723
5d45a880
TG
1724 break;
1725 }
74b2466e 1726 default:
afbc4f26 1727 unparseable:
f5430a3e 1728 r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
74b2466e
LP
1729 if (r < 0)
1730 goto fail;
74b2466e
LP
1731 break;
1732 }
1733 if (r < 0)
1734 goto fail;
1735 if (p->rindex != offset + rdlength) {
1736 r = -EBADMSG;
1737 goto fail;
1738 }
1739
1740 *ret = rr;
1741 rr = NULL;
1742
1743 if (start)
1744 *start = saved_rindex;
1745
1746 return 0;
1747fail:
1748 dns_packet_rewind(p, saved_rindex);
1749 return r;
1750}
1751
faa133f3
LP
1752int dns_packet_extract(DnsPacket *p) {
1753 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1754 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1755 size_t saved_rindex;
1756 unsigned n, i;
74b2466e
LP
1757 int r;
1758
a4076574
LP
1759 if (p->extracted)
1760 return 0;
1761
faa133f3 1762 saved_rindex = p->rindex;
322345fd
LP
1763 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1764
3cb10d3a 1765 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
1766 if (n > 0) {
1767 question = dns_question_new(n);
1768 if (!question) {
1769 r = -ENOMEM;
1770 goto finish;
1771 }
74b2466e 1772
faa133f3
LP
1773 for (i = 0; i < n; i++) {
1774 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e 1775
faa133f3
LP
1776 r = dns_packet_read_key(p, &key, NULL);
1777 if (r < 0)
1778 goto finish;
74b2466e 1779
faa133f3
LP
1780 r = dns_question_add(question, key);
1781 if (r < 0)
1782 goto finish;
1783 }
1784 }
322345fd 1785
faa133f3
LP
1786 n = DNS_PACKET_RRCOUNT(p);
1787 if (n > 0) {
1788 answer = dns_answer_new(n);
1789 if (!answer) {
1790 r = -ENOMEM;
1791 goto finish;
1792 }
322345fd 1793
faa133f3
LP
1794 for (i = 0; i < n; i++) {
1795 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
322345fd 1796
faa133f3
LP
1797 r = dns_packet_read_rr(p, &rr, NULL);
1798 if (r < 0)
1799 goto finish;
322345fd 1800
faa133f3
LP
1801 r = dns_answer_add(answer, rr);
1802 if (r < 0)
1803 goto finish;
1804 }
322345fd
LP
1805 }
1806
faa133f3
LP
1807 p->question = question;
1808 question = NULL;
322345fd 1809
faa133f3
LP
1810 p->answer = answer;
1811 answer = NULL;
322345fd 1812
a4076574
LP
1813 p->extracted = true;
1814
faa133f3 1815 r = 0;
322345fd
LP
1816
1817finish:
1818 p->rindex = saved_rindex;
1819 return r;
1820}
1821
74b2466e
LP
1822static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1823 [DNS_RCODE_SUCCESS] = "SUCCESS",
1824 [DNS_RCODE_FORMERR] = "FORMERR",
1825 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1826 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1827 [DNS_RCODE_NOTIMP] = "NOTIMP",
1828 [DNS_RCODE_REFUSED] = "REFUSED",
1829 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1830 [DNS_RCODE_YXRRSET] = "YRRSET",
1831 [DNS_RCODE_NXRRSET] = "NXRRSET",
1832 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1833 [DNS_RCODE_NOTZONE] = "NOTZONE",
1834 [DNS_RCODE_BADVERS] = "BADVERS",
1835 [DNS_RCODE_BADKEY] = "BADKEY",
1836 [DNS_RCODE_BADTIME] = "BADTIME",
1837 [DNS_RCODE_BADMODE] = "BADMODE",
1838 [DNS_RCODE_BADNAME] = "BADNAME",
1839 [DNS_RCODE_BADALG] = "BADALG",
1840 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1841};
1842DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc
LP
1843
1844static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1845 [DNS_PROTOCOL_DNS] = "dns",
1846 [DNS_PROTOCOL_MDNS] = "mdns",
1847 [DNS_PROTOCOL_LLMNR] = "llmnr",
1848};
1849DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
ff3d6560
ZJS
1850
1851static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
5d45a880
TG
1852 [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
1853 [DNSSEC_ALGORITHM_DH] = "DH",
1854 [DNSSEC_ALGORITHM_DSA] = "DSA",
1855 [DNSSEC_ALGORITHM_ECC] = "ECC",
1856 [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
1857 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1",
1858 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
1859 [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
1860 [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
1861 [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
ff3d6560
ZJS
1862};
1863DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);