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