]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
Merge pull request #665 from poettering/reword-journal-size-msg
[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) {
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
764 r = dns_packet_append_blob(p, rr->sshfp.key, rr->sshfp.key_size, NULL);
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
74b2466e
LP
936int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
937 const void *d;
938 int r;
939
940 assert(p);
941
942 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
943 if (r < 0)
944 return r;
945
946 *ret = ((uint8_t*) d)[0];
947 return 0;
948}
949
950int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
951 const void *d;
952 int r;
953
954 assert(p);
955
956 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
957 if (r < 0)
958 return r;
959
725ca0e5
TG
960 *ret = unaligned_read_be16(d);
961
74b2466e
LP
962 return 0;
963}
964
965int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
966 const void *d;
967 int r;
968
969 assert(p);
970
971 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
972 if (r < 0)
973 return r;
974
725ca0e5 975 *ret = unaligned_read_be32(d);
74b2466e
LP
976
977 return 0;
978}
979
980int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
981 size_t saved_rindex;
982 const void *d;
983 char *t;
984 uint8_t c;
985 int r;
986
987 assert(p);
988
989 saved_rindex = p->rindex;
990
991 r = dns_packet_read_uint8(p, &c, NULL);
992 if (r < 0)
993 goto fail;
994
995 r = dns_packet_read(p, c, &d, NULL);
996 if (r < 0)
997 goto fail;
998
999 if (memchr(d, 0, c)) {
1000 r = -EBADMSG;
1001 goto fail;
1002 }
1003
1004 t = strndup(d, c);
1005 if (!t) {
1006 r = -ENOMEM;
1007 goto fail;
1008 }
1009
1010 if (!utf8_is_valid(t)) {
1011 free(t);
1012 r = -EBADMSG;
1013 goto fail;
1014 }
1015
1016 *ret = t;
1017
1018 if (start)
1019 *start = saved_rindex;
1020
1021 return 0;
1022
1023fail:
1024 dns_packet_rewind(p, saved_rindex);
1025 return r;
1026}
1027
151226ab
ZJS
1028int dns_packet_read_name(DnsPacket *p, char **_ret,
1029 bool allow_compression, size_t *start) {
c75dbf9b 1030 size_t saved_rindex, after_rindex = 0, jump_barrier;
74b2466e
LP
1031 _cleanup_free_ char *ret = NULL;
1032 size_t n = 0, allocated = 0;
1033 bool first = true;
1034 int r;
1035
1036 assert(p);
1037 assert(_ret);
1038
1039 saved_rindex = p->rindex;
c75dbf9b 1040 jump_barrier = p->rindex;
74b2466e
LP
1041
1042 for (;;) {
1043 uint8_t c, d;
1044
1045 r = dns_packet_read_uint8(p, &c, NULL);
1046 if (r < 0)
1047 goto fail;
1048
1049 if (c == 0)
1050 /* End of name */
1051 break;
1052 else if (c <= 63) {
1053 _cleanup_free_ char *t = NULL;
1054 const char *label;
1055
1056 /* Literal label */
1057 r = dns_packet_read(p, c, (const void**) &label, NULL);
1058 if (r < 0)
1059 goto fail;
1060
1061 r = dns_label_escape(label, c, &t);
1062 if (r < 0)
1063 goto fail;
1064
1065 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
1066 r = -ENOMEM;
1067 goto fail;
1068 }
1069
1070 if (!first)
1071 ret[n++] = '.';
1072 else
1073 first = false;
1074
85818582 1075 memcpy(ret + n, t, r);
74b2466e
LP
1076 n += r;
1077 continue;
151226ab 1078 } else if (allow_compression && (c & 0xc0) == 0xc0) {
74b2466e
LP
1079 uint16_t ptr;
1080
1081 /* Pointer */
1082 r = dns_packet_read_uint8(p, &d, NULL);
1083 if (r < 0)
1084 goto fail;
1085
1086 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
c75dbf9b 1087 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
74b2466e
LP
1088 r = -EBADMSG;
1089 goto fail;
1090 }
1091
1092 if (after_rindex == 0)
1093 after_rindex = p->rindex;
1094
f131770b 1095 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
c75dbf9b 1096 jump_barrier = ptr;
74b2466e 1097 p->rindex = ptr;
59aa5821
SP
1098 } else {
1099 r = -EBADMSG;
74b2466e 1100 goto fail;
59aa5821 1101 }
74b2466e
LP
1102 }
1103
1104 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
1105 r = -ENOMEM;
1106 goto fail;
1107 }
1108
1109 ret[n] = 0;
1110
1111 if (after_rindex != 0)
1112 p->rindex= after_rindex;
1113
1114 *_ret = ret;
1115 ret = NULL;
1116
1117 if (start)
1118 *start = saved_rindex;
1119
1120 return 0;
1121
1122fail:
1123 dns_packet_rewind(p, saved_rindex);
1124 return r;
1125}
1126
50f1e641
TG
1127static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) {
1128 uint8_t window;
1129 uint8_t length;
1130 const uint8_t *bitmap;
1131 unsigned i;
1132 bool found = false;
1133 size_t saved_rindex;
1134 int r;
1135
1136 assert(p);
1137 assert(types);
1138
1139 saved_rindex = p->rindex;
1140
1141 r = bitmap_ensure_allocated(types);
1142 if (r < 0)
1143 goto fail;
1144
1145 r = dns_packet_read_uint8(p, &window, NULL);
1146 if (r < 0)
1147 goto fail;
1148
1149 r = dns_packet_read_uint8(p, &length, NULL);
1150 if (r < 0)
1151 goto fail;
1152
1153 if (length == 0 || length > 32)
1154 return -EBADMSG;
1155
1156 r = dns_packet_read(p, length, (const void **)&bitmap, NULL);
1157 if (r < 0)
1158 goto fail;
1159
1160 for (i = 0; i < length; i++) {
1161 uint8_t bitmask = 1 << 7;
1162 uint8_t bit = 0;
1163
1164 if (!bitmap[i]) {
1165 found = false;
1166 continue;
1167 }
1168
1169 found = true;
1170
1171 while (bitmask) {
1172 if (bitmap[i] & bitmask) {
1173 uint16_t n;
1174
1175 /* XXX: ignore pseudo-types? see RFC4034 section 4.1.2 */
1176 n = (uint16_t) window << 8 | (uint16_t) bit;
1177
1178 r = bitmap_set(*types, n);
1179 if (r < 0)
1180 goto fail;
1181 }
1182
1183 bit ++;
1184 bitmask >>= 1;
1185 }
1186 }
1187
1188 if (!found)
1189 return -EBADMSG;
1190
1191 if (start)
1192 *start = saved_rindex;
1193
1194 return 0;
1195fail:
1196 dns_packet_rewind(p, saved_rindex);
1197 return r;
1198}
1199
faa133f3
LP
1200int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
1201 _cleanup_free_ char *name = NULL;
1202 uint16_t class, type;
1203 DnsResourceKey *key;
74b2466e
LP
1204 size_t saved_rindex;
1205 int r;
1206
1207 assert(p);
1208 assert(ret);
1209
1210 saved_rindex = p->rindex;
1211
151226ab 1212 r = dns_packet_read_name(p, &name, true, NULL);
74b2466e
LP
1213 if (r < 0)
1214 goto fail;
1215
faa133f3 1216 r = dns_packet_read_uint16(p, &type, NULL);
74b2466e
LP
1217 if (r < 0)
1218 goto fail;
1219
faa133f3 1220 r = dns_packet_read_uint16(p, &class, NULL);
74b2466e
LP
1221 if (r < 0)
1222 goto fail;
1223
faa133f3
LP
1224 key = dns_resource_key_new_consume(class, type, name);
1225 if (!key) {
1226 r = -ENOMEM;
1227 goto fail;
1228 }
1229
1230 name = NULL;
1231 *ret = key;
74b2466e
LP
1232
1233 if (start)
1234 *start = saved_rindex;
1235
1236 return 0;
1237fail:
1238 dns_packet_rewind(p, saved_rindex);
1239 return r;
1240}
1241
8db0d2f5
ZJS
1242static int dns_packet_read_public_key(DnsPacket *p, size_t length,
1243 void **dp, size_t *lengthp,
1244 size_t *start) {
1245 int r;
1246 const void *d;
1247 void *d2;
1248
1249 r = dns_packet_read(p, length, &d, NULL);
1250 if (r < 0)
1251 return r;
1252
1253 d2 = memdup(d, length);
1254 if (!d2)
1255 return -ENOMEM;
1256
1257 *dp = d2;
1258 *lengthp = length;
1259 return 0;
1260}
1261
afbc4f26
ZJS
1262static bool loc_size_ok(uint8_t size) {
1263 uint8_t m = size >> 4, e = size & 0xF;
1264
1265 return m <= 9 && e <= 9 && (m > 0 || e == 0);
1266}
1267
8db0d2f5 1268static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
3ef77d04
LP
1269 assert(rr);
1270
8db0d2f5
ZJS
1271 if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
1272 return -EBADMSG;
1273
1274 rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
1275 rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
1276 return 0;
1277}
1278
74b2466e 1279int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
faa133f3
LP
1280 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1281 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e
LP
1282 size_t saved_rindex, offset;
1283 uint16_t rdlength;
1284 const void *d;
1285 int r;
1286
1287 assert(p);
1288 assert(ret);
1289
4e0296a9 1290 saved_rindex = p->rindex;
74b2466e 1291
faa133f3 1292 r = dns_packet_read_key(p, &key, NULL);
74b2466e
LP
1293 if (r < 0)
1294 goto fail;
1295
0e2bcd6a
LP
1296 if (key->class == DNS_CLASS_ANY ||
1297 key->type == DNS_TYPE_ANY) {
1298 r = -EBADMSG;
1299 goto fail;
1300 }
1301
faa133f3
LP
1302 rr = dns_resource_record_new(key);
1303 if (!rr) {
1304 r = -ENOMEM;
1305 goto fail;
1306 }
1307
74b2466e
LP
1308 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1309 if (r < 0)
1310 goto fail;
1311
1312 r = dns_packet_read_uint16(p, &rdlength, NULL);
1313 if (r < 0)
1314 goto fail;
1315
1316 if (p->rindex + rdlength > p->size) {
1317 r = -EBADMSG;
1318 goto fail;
1319 }
1320
1321 offset = p->rindex;
1322
faa133f3 1323 switch (rr->key->type) {
74b2466e 1324
9c92ce6d
LP
1325 case DNS_TYPE_SRV:
1326 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1327 if (r < 0)
1328 goto fail;
1329 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1330 if (r < 0)
1331 goto fail;
1332 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1333 if (r < 0)
1334 goto fail;
151226ab 1335 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
9c92ce6d
LP
1336 break;
1337
74b2466e
LP
1338 case DNS_TYPE_PTR:
1339 case DNS_TYPE_NS:
1340 case DNS_TYPE_CNAME:
8ac4e9e1 1341 case DNS_TYPE_DNAME:
151226ab 1342 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1343 break;
1344
1345 case DNS_TYPE_HINFO:
1346 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1347 if (r < 0)
1348 goto fail;
1349
1350 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1351 break;
1352
9de3e329 1353 case DNS_TYPE_SPF: /* exactly the same as TXT */
1ccda9b7
LP
1354 case DNS_TYPE_TXT:
1355 if (rdlength <= 0) {
1356 /* RFC 6763, section 6.1 suggests to treat
1357 * empty TXT RRs as equivalent to a TXT record
1358 * with a single empty string. */
0e3434ae 1359
1ccda9b7 1360 r = strv_extend(&rr->txt.strings, "");
2e276efc
ZJS
1361 if (r < 0)
1362 goto fail;
1ccda9b7
LP
1363 } else {
1364 while (p->rindex < offset + rdlength) {
1365 char *s;
2e276efc 1366
1ccda9b7
LP
1367 r = dns_packet_read_string(p, &s, NULL);
1368 if (r < 0)
1369 goto fail;
1370
1371 r = strv_consume(&rr->txt.strings, s);
1372 if (r < 0)
1373 goto fail;
1374 }
6a6fc3df
LP
1375 }
1376
1377 r = 0;
2e276efc 1378 break;
2e276efc 1379
74b2466e 1380 case DNS_TYPE_A:
623a4c97 1381 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1382 break;
1383
1384 case DNS_TYPE_AAAA:
623a4c97 1385 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1386 break;
1387
7e8e0422 1388 case DNS_TYPE_SOA:
151226ab 1389 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422
LP
1390 if (r < 0)
1391 goto fail;
1392
151226ab 1393 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422
LP
1394 if (r < 0)
1395 goto fail;
1396
1397 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1398 if (r < 0)
1399 goto fail;
1400
1401 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1402 if (r < 0)
1403 goto fail;
1404
1405 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1406 if (r < 0)
1407 goto fail;
1408
1409 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1410 if (r < 0)
1411 goto fail;
1412
1413 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1414 break;
1415
623a4c97 1416 case DNS_TYPE_MX:
946c7094
ZJS
1417 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1418 if (r < 0)
1419 goto fail;
1420
151226ab 1421 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
1422 break;
1423
0dae31d4
ZJS
1424 case DNS_TYPE_LOC: {
1425 uint8_t t;
1426 size_t pos;
1427
1428 r = dns_packet_read_uint8(p, &t, &pos);
1429 if (r < 0)
1430 goto fail;
1431
1432 if (t == 0) {
1433 rr->loc.version = t;
1434
1435 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1436 if (r < 0)
1437 goto fail;
1438
afbc4f26
ZJS
1439 if (!loc_size_ok(rr->loc.size)) {
1440 r = -EBADMSG;
1441 goto fail;
1442 }
1443
0dae31d4
ZJS
1444 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1445 if (r < 0)
1446 goto fail;
1447
afbc4f26
ZJS
1448 if (!loc_size_ok(rr->loc.horiz_pre)) {
1449 r = -EBADMSG;
1450 goto fail;
1451 }
1452
0dae31d4
ZJS
1453 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1454 if (r < 0)
1455 goto fail;
1456
afbc4f26
ZJS
1457 if (!loc_size_ok(rr->loc.vert_pre)) {
1458 r = -EBADMSG;
1459 goto fail;
1460 }
1461
0dae31d4
ZJS
1462 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1463 if (r < 0)
1464 goto fail;
1465
1466 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1467 if (r < 0)
1468 goto fail;
1469
1470 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1471 if (r < 0)
1472 goto fail;
1473
1474 break;
1475 } else {
1476 dns_packet_rewind(p, pos);
1477 rr->unparseable = true;
afbc4f26 1478 goto unparseable;
0dae31d4
ZJS
1479 }
1480 }
1481
abf126a3
TG
1482 case DNS_TYPE_DS:
1483 r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
1484 if (r < 0)
1485 goto fail;
1486
1487 r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
1488 if (r < 0)
1489 goto fail;
1490
1491 r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
1492 if (r < 0)
1493 goto fail;
1494
1495 r = dns_packet_read_public_key(p, rdlength - 4,
1496 &rr->ds.digest, &rr->ds.digest_size,
1497 NULL);
1498 if (r < 0)
1499 goto fail;
1500
1501 break;
623a4c97 1502 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1503 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1504 if (r < 0)
1505 goto fail;
1506
1507 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1508 if (r < 0)
1509 goto fail;
1510
8db0d2f5
ZJS
1511 r = dns_packet_read_public_key(p, rdlength - 2,
1512 &rr->sshfp.key, &rr->sshfp.key_size,
1513 NULL);
1514 break;
1515
1516 case DNS_TYPE_DNSKEY: {
1517 uint16_t flags;
1518 uint8_t proto;
1519
1520 r = dns_packet_read_uint16(p, &flags, NULL);
42cc2eeb
LP
1521 if (r < 0)
1522 goto fail;
1523
8db0d2f5
ZJS
1524 r = dnskey_parse_flags(rr, flags);
1525 if (r < 0)
1526 goto fail;
1527
1528 r = dns_packet_read_uint8(p, &proto, NULL);
1529 if (r < 0)
1530 goto fail;
1531
1532 /* protocol is required to be always 3 */
1533 if (proto != 3) {
1534 r = -EBADMSG;
42cc2eeb
LP
1535 goto fail;
1536 }
1537
8db0d2f5
ZJS
1538 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1539 if (r < 0)
1540 goto fail;
1541
1542 r = dns_packet_read_public_key(p, rdlength - 4,
1543 &rr->dnskey.key, &rr->dnskey.key_size,
1544 NULL);
42cc2eeb 1545 break;
8db0d2f5 1546 }
42cc2eeb 1547
151226ab
ZJS
1548 case DNS_TYPE_RRSIG:
1549 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
1550 if (r < 0)
1551 goto fail;
1552
1553 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
1554 if (r < 0)
1555 goto fail;
1556
1557 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
1558 if (r < 0)
1559 goto fail;
1560
1561 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
1562 if (r < 0)
1563 goto fail;
1564
1565 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
1566 if (r < 0)
1567 goto fail;
1568
1569 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
1570 if (r < 0)
1571 goto fail;
1572
1573 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
1574 if (r < 0)
1575 goto fail;
1576
1577 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
1578 if (r < 0)
1579 goto fail;
1580
1581 r = dns_packet_read_public_key(p, offset + rdlength - p->rindex,
1582 &rr->rrsig.signature, &rr->rrsig.signature_size,
1583 NULL);
1584 break;
1585
50f1e641
TG
1586 case DNS_TYPE_NSEC:
1587 r = dns_packet_read_name(p, &rr->nsec.next_domain_name, false, NULL);
1588 if (r < 0)
1589 goto fail;
1590
1591 while (p->rindex != offset + rdlength) {
1592 r = dns_packet_read_type_window(p, &rr->nsec.types, NULL);
1593 if (r < 0)
1594 goto fail;
1595 }
1596
1597 break;
5d45a880
TG
1598
1599 case DNS_TYPE_NSEC3: {
1600 uint8_t size;
1601
1602 r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
1603 if (r < 0)
1604 goto fail;
1605
1606 r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
1607 if (r < 0)
1608 goto fail;
1609
1610 r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
1611 if (r < 0)
1612 goto fail;
1613
1614 r = dns_packet_read_uint8(p, &size, NULL);
1615 if (r < 0)
1616 goto fail;
1617
1618 rr->nsec3.salt_size = size;
1619
1620 r = dns_packet_read_blob(p, &d, rr->nsec3.salt_size, NULL);
1621 if (r < 0)
1622 goto fail;
1623
1624 rr->nsec3.salt = memdup(d, rr->nsec3.salt_size);
1625 if (!rr->nsec3.salt) {
1626 r = -ENOMEM;
1627 goto fail;
1628 }
1629
1630 r = dns_packet_read_uint8(p, &size, NULL);
1631 if (r < 0)
1632 goto fail;
1633
1634 rr->nsec3.next_hashed_name_size = size;
1635
1636 r = dns_packet_read(p, rr->nsec3.next_hashed_name_size, &d, NULL);
1637 if (r < 0)
1638 goto fail;
1639
1640 rr->nsec3.next_hashed_name = memdup(d, rr->nsec3.next_hashed_name_size);
1641 if (!rr->nsec3.next_hashed_name) {
1642 r = -ENOMEM;
1643 goto fail;
1644 }
1645
1646 r = dns_packet_append_types(p, rr->nsec3.types, NULL);
1647 if (r < 0)
1648 goto fail;
1649
1650 break;
1651 }
74b2466e 1652 default:
afbc4f26 1653 unparseable:
74b2466e
LP
1654 r = dns_packet_read(p, rdlength, &d, NULL);
1655 if (r < 0)
1656 goto fail;
1657
1658 rr->generic.data = memdup(d, rdlength);
1659 if (!rr->generic.data) {
1660 r = -ENOMEM;
1661 goto fail;
1662 }
1663
1664 rr->generic.size = rdlength;
1665 break;
1666 }
1667 if (r < 0)
1668 goto fail;
1669 if (p->rindex != offset + rdlength) {
1670 r = -EBADMSG;
1671 goto fail;
1672 }
1673
1674 *ret = rr;
1675 rr = NULL;
1676
1677 if (start)
1678 *start = saved_rindex;
1679
1680 return 0;
1681fail:
1682 dns_packet_rewind(p, saved_rindex);
1683 return r;
1684}
1685
faa133f3
LP
1686int dns_packet_extract(DnsPacket *p) {
1687 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1688 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1689 size_t saved_rindex;
1690 unsigned n, i;
74b2466e
LP
1691 int r;
1692
a4076574
LP
1693 if (p->extracted)
1694 return 0;
1695
faa133f3 1696 saved_rindex = p->rindex;
322345fd
LP
1697 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1698
3cb10d3a 1699 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
1700 if (n > 0) {
1701 question = dns_question_new(n);
1702 if (!question) {
1703 r = -ENOMEM;
1704 goto finish;
1705 }
74b2466e 1706
faa133f3
LP
1707 for (i = 0; i < n; i++) {
1708 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e 1709
faa133f3
LP
1710 r = dns_packet_read_key(p, &key, NULL);
1711 if (r < 0)
1712 goto finish;
74b2466e 1713
faa133f3
LP
1714 r = dns_question_add(question, key);
1715 if (r < 0)
1716 goto finish;
1717 }
1718 }
322345fd 1719
faa133f3
LP
1720 n = DNS_PACKET_RRCOUNT(p);
1721 if (n > 0) {
1722 answer = dns_answer_new(n);
1723 if (!answer) {
1724 r = -ENOMEM;
1725 goto finish;
1726 }
322345fd 1727
faa133f3
LP
1728 for (i = 0; i < n; i++) {
1729 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
322345fd 1730
faa133f3
LP
1731 r = dns_packet_read_rr(p, &rr, NULL);
1732 if (r < 0)
1733 goto finish;
322345fd 1734
faa133f3
LP
1735 r = dns_answer_add(answer, rr);
1736 if (r < 0)
1737 goto finish;
1738 }
322345fd
LP
1739 }
1740
faa133f3
LP
1741 p->question = question;
1742 question = NULL;
322345fd 1743
faa133f3
LP
1744 p->answer = answer;
1745 answer = NULL;
322345fd 1746
a4076574
LP
1747 p->extracted = true;
1748
faa133f3 1749 r = 0;
322345fd
LP
1750
1751finish:
1752 p->rindex = saved_rindex;
1753 return r;
1754}
1755
74b2466e
LP
1756static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1757 [DNS_RCODE_SUCCESS] = "SUCCESS",
1758 [DNS_RCODE_FORMERR] = "FORMERR",
1759 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1760 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1761 [DNS_RCODE_NOTIMP] = "NOTIMP",
1762 [DNS_RCODE_REFUSED] = "REFUSED",
1763 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1764 [DNS_RCODE_YXRRSET] = "YRRSET",
1765 [DNS_RCODE_NXRRSET] = "NXRRSET",
1766 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1767 [DNS_RCODE_NOTZONE] = "NOTZONE",
1768 [DNS_RCODE_BADVERS] = "BADVERS",
1769 [DNS_RCODE_BADKEY] = "BADKEY",
1770 [DNS_RCODE_BADTIME] = "BADTIME",
1771 [DNS_RCODE_BADMODE] = "BADMODE",
1772 [DNS_RCODE_BADNAME] = "BADNAME",
1773 [DNS_RCODE_BADALG] = "BADALG",
1774 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1775};
1776DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc
LP
1777
1778static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1779 [DNS_PROTOCOL_DNS] = "dns",
1780 [DNS_PROTOCOL_MDNS] = "mdns",
1781 [DNS_PROTOCOL_LLMNR] = "llmnr",
1782};
1783DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
ff3d6560
ZJS
1784
1785static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
5d45a880
TG
1786 [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
1787 [DNSSEC_ALGORITHM_DH] = "DH",
1788 [DNSSEC_ALGORITHM_DSA] = "DSA",
1789 [DNSSEC_ALGORITHM_ECC] = "ECC",
1790 [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
1791 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1] = "DSA-NSEC3-SHA1",
1792 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1] = "RSASHA1-NSEC3-SHA1",
1793 [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
1794 [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
1795 [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
ff3d6560
ZJS
1796};
1797DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);