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