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