]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
resolved: llmnr, mdns: simplify error handling
[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
b5efdb8a 22#include "alloc-util.h"
4ad7f276 23#include "dns-domain.h"
74b2466e 24#include "resolved-dns-packet.h"
8b43440b
LP
25#include "string-table.h"
26#include "strv.h"
27#include "unaligned.h"
28#include "utf8.h"
29#include "util.h"
74b2466e 30
7586f4d1
TG
31#define EDNS0_OPT_DO (1<<15)
32
1716f6dc 33int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
74b2466e
LP
34 DnsPacket *p;
35 size_t a;
36
37 assert(ret);
38
a0166609 39 if (mtu <= UDP_PACKET_HEADER_SIZE)
74b2466e
LP
40 a = DNS_PACKET_SIZE_START;
41 else
a0166609 42 a = mtu - UDP_PACKET_HEADER_SIZE;
74b2466e
LP
43
44 if (a < DNS_PACKET_HEADER_SIZE)
45 a = DNS_PACKET_HEADER_SIZE;
46
c73ce96b
LP
47 /* round up to next page size */
48 a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
49
50 /* make sure we never allocate more than useful */
51 if (a > DNS_PACKET_SIZE_MAX)
52 a = DNS_PACKET_SIZE_MAX;
53
74b2466e
LP
54 p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
55 if (!p)
56 return -ENOMEM;
57
58 p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
59 p->allocated = a;
1716f6dc 60 p->protocol = protocol;
74b2466e
LP
61 p->n_ref = 1;
62
63 *ret = p;
64
65 return 0;
66}
67
24710c48 68int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu, bool dnssec_checking_disabled) {
74b2466e
LP
69 DnsPacket *p;
70 DnsPacketHeader *h;
069360a6 71 int r;
74b2466e
LP
72
73 assert(ret);
74
1716f6dc 75 r = dns_packet_new(&p, protocol, mtu);
74b2466e
LP
76 if (r < 0)
77 return r;
78
79 h = DNS_PACKET_HEADER(p);
1716f6dc 80
069360a6
LP
81 if (protocol == DNS_PROTOCOL_LLMNR)
82 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
83 0 /* opcode */,
84 0 /* c */,
85 0 /* tc */,
86 0 /* t */,
87 0 /* ra */,
88 0 /* ad */,
89 0 /* cd */,
90 0 /* rcode */));
4e5bf5e1
DM
91 else if (protocol == DNS_PROTOCOL_MDNS)
92 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
93 0 /* opcode */,
94 0 /* aa */,
95 0 /* tc */,
96 0 /* rd (ask for recursion) */,
97 0 /* ra */,
98 0 /* ad */,
99 0 /* cd */,
100 0 /* rcode */));
069360a6
LP
101 else
102 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
103 0 /* opcode */,
104 0 /* aa */,
105 0 /* tc */,
106 1 /* rd (ask for recursion) */,
107 0 /* ra */,
108 0 /* ad */,
24710c48 109 dnssec_checking_disabled /* cd */,
069360a6 110 0 /* rcode */));
74b2466e
LP
111
112 *ret = p;
113 return 0;
114}
115
116DnsPacket *dns_packet_ref(DnsPacket *p) {
117
118 if (!p)
119 return NULL;
120
a8812dd7
LP
121 assert(!p->on_stack);
122
74b2466e
LP
123 assert(p->n_ref > 0);
124 p->n_ref++;
125 return p;
126}
127
128static void dns_packet_free(DnsPacket *p) {
129 char *s;
130
131 assert(p);
132
faa133f3
LP
133 dns_question_unref(p->question);
134 dns_answer_unref(p->answer);
322345fd 135
74b2466e
LP
136 while ((s = hashmap_steal_first_key(p->names)))
137 free(s);
138 hashmap_free(p->names);
139
faa133f3 140 free(p->_data);
a8812dd7
LP
141
142 if (!p->on_stack)
143 free(p);
74b2466e
LP
144}
145
146DnsPacket *dns_packet_unref(DnsPacket *p) {
147 if (!p)
148 return NULL;
149
150 assert(p->n_ref > 0);
151
152 if (p->n_ref == 1)
153 dns_packet_free(p);
154 else
155 p->n_ref--;
156
157 return NULL;
158}
159
160int dns_packet_validate(DnsPacket *p) {
161 assert(p);
162
163 if (p->size < DNS_PACKET_HEADER_SIZE)
164 return -EBADMSG;
165
c73ce96b
LP
166 if (p->size > DNS_PACKET_SIZE_MAX)
167 return -EBADMSG;
168
623a4c97 169 return 1;
74b2466e
LP
170}
171
172int dns_packet_validate_reply(DnsPacket *p) {
74b2466e
LP
173 int r;
174
175 assert(p);
176
177 r = dns_packet_validate(p);
178 if (r < 0)
179 return r;
180
623a4c97
LP
181 if (DNS_PACKET_QR(p) != 1)
182 return 0;
183
184 if (DNS_PACKET_OPCODE(p) != 0)
74b2466e
LP
185 return -EBADMSG;
186
818ef443
DM
187 switch (p->protocol) {
188 case DNS_PROTOCOL_LLMNR:
189 /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
190 if (DNS_PACKET_QDCOUNT(p) != 1)
191 return -EBADMSG;
192
193 break;
194
4e5bf5e1
DM
195 case DNS_PROTOCOL_MDNS:
196 /* RFC 6762, Section 18 */
197 if (DNS_PACKET_RCODE(p) != 0)
198 return -EBADMSG;
199
200 break;
201
818ef443
DM
202 default:
203 break;
204 }
ea917db9 205
623a4c97
LP
206 return 1;
207}
208
209int dns_packet_validate_query(DnsPacket *p) {
210 int r;
211
212 assert(p);
213
214 r = dns_packet_validate(p);
215 if (r < 0)
216 return r;
217
218 if (DNS_PACKET_QR(p) != 0)
219 return 0;
220
3cb10d3a 221 if (DNS_PACKET_OPCODE(p) != 0)
74b2466e
LP
222 return -EBADMSG;
223
623a4c97
LP
224 if (DNS_PACKET_TC(p))
225 return -EBADMSG;
226
818ef443
DM
227 switch (p->protocol) {
228 case DNS_PROTOCOL_LLMNR:
229 /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
230 if (DNS_PACKET_QDCOUNT(p) != 1)
231 return -EBADMSG;
623a4c97 232
818ef443
DM
233 /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
234 if (DNS_PACKET_ANCOUNT(p) > 0)
235 return -EBADMSG;
623a4c97 236
818ef443
DM
237 /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
238 if (DNS_PACKET_NSCOUNT(p) > 0)
239 return -EBADMSG;
240
241 break;
242
4e5bf5e1
DM
243 case DNS_PROTOCOL_MDNS:
244 /* RFC 6762, Section 18 */
245 if (DNS_PACKET_AA(p) != 0 ||
246 DNS_PACKET_RD(p) != 0 ||
247 DNS_PACKET_RA(p) != 0 ||
248 DNS_PACKET_AD(p) != 0 ||
249 DNS_PACKET_CD(p) != 0 ||
250 DNS_PACKET_RCODE(p) != 0)
251 return -EBADMSG;
252
253 break;
254
818ef443
DM
255 default:
256 break;
257 }
623a4c97
LP
258
259 return 1;
74b2466e
LP
260}
261
262static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
263 assert(p);
264
c73ce96b
LP
265 if (p->size + add > p->allocated) {
266 size_t a;
267
268 a = PAGE_ALIGN((p->size + add) * 2);
269 if (a > DNS_PACKET_SIZE_MAX)
270 a = DNS_PACKET_SIZE_MAX;
271
272 if (p->size + add > a)
273 return -EMSGSIZE;
274
faa133f3 275 if (p->_data) {
c73ce96b
LP
276 void *d;
277
faa133f3 278 d = realloc(p->_data, a);
c73ce96b
LP
279 if (!d)
280 return -ENOMEM;
281
faa133f3 282 p->_data = d;
c73ce96b 283 } else {
faa133f3
LP
284 p->_data = malloc(a);
285 if (!p->_data)
c73ce96b
LP
286 return -ENOMEM;
287
faa133f3
LP
288 memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
289 memzero((uint8_t*) p->_data + p->size, a - p->size);
c73ce96b
LP
290 }
291
292 p->allocated = a;
293 }
74b2466e
LP
294
295 if (start)
296 *start = p->size;
297
298 if (ret)
299 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
300
301 p->size += add;
302 return 0;
303}
304
9c5e12a4 305void dns_packet_truncate(DnsPacket *p, size_t sz) {
74b2466e
LP
306 Iterator i;
307 char *s;
308 void *n;
309
310 assert(p);
311
312 if (p->size <= sz)
313 return;
314
0e03ade5 315 HASHMAP_FOREACH_KEY(n, s, p->names, i) {
74b2466e
LP
316
317 if (PTR_TO_SIZE(n) < sz)
318 continue;
319
320 hashmap_remove(p->names, s);
321 free(s);
322 }
323
324 p->size = sz;
325}
326
623a4c97
LP
327int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
328 void *q;
329 int r;
330
331 assert(p);
332
333 r = dns_packet_extend(p, l, &q, start);
334 if (r < 0)
335 return r;
336
337 memcpy(q, d, l);
338 return 0;
339}
340
74b2466e
LP
341int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
342 void *d;
343 int r;
344
345 assert(p);
346
347 r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
348 if (r < 0)
349 return r;
350
351 ((uint8_t*) d)[0] = v;
352
353 return 0;
354}
355
356int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
357 void *d;
358 int r;
359
360 assert(p);
361
362 r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
363 if (r < 0)
364 return r;
365
725ca0e5 366 unaligned_write_be16(d, v);
623a4c97
LP
367
368 return 0;
369}
370
371int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
372 void *d;
373 int r;
374
375 assert(p);
376
377 r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
378 if (r < 0)
379 return r;
380
725ca0e5 381 unaligned_write_be32(d, v);
74b2466e
LP
382
383 return 0;
384}
385
386int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
74b2466e
LP
387 assert(p);
388 assert(s);
389
c38a52da 390 return dns_packet_append_raw_string(p, s, strlen(s), start);
74b2466e
LP
391}
392
2001c805
LP
393int dns_packet_append_raw_string(DnsPacket *p, const void *s, size_t size, size_t *start) {
394 void *d;
395 int r;
396
397 assert(p);
398 assert(s || size == 0);
399
400 if (size > 255)
401 return -E2BIG;
402
403 r = dns_packet_extend(p, 1 + size, &d, start);
404 if (r < 0)
405 return r;
406
407 ((uint8_t*) d)[0] = (uint8_t) size;
408
409 if (size > 0)
410 memcpy(((uint8_t*) d) + 1, s, size);
411
412 return 0;
413}
414
74b2466e 415int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
a8812dd7 416 uint8_t *w;
74b2466e
LP
417 int r;
418
419 assert(p);
420 assert(d);
421
422 if (l > DNS_LABEL_MAX)
423 return -E2BIG;
424
a8812dd7 425 r = dns_packet_extend(p, 1 + l, (void**) &w, start);
74b2466e
LP
426 if (r < 0)
427 return r;
428
a8812dd7
LP
429 *(w++) = (uint8_t) l;
430
431 if (p->canonical_form) {
432 size_t i;
433
434 /* Generate in canonical form, as defined by DNSSEC
435 * RFC 4034, Section 6.2, i.e. all lower-case. */
436
437 for (i = 0; i < l; i++) {
438 if (d[i] >= 'A' && d[i] <= 'Z')
439 w[i] = (uint8_t) (d[i] - 'A' + 'a');
440 else
441 w[i] = (uint8_t) d[i];
442 }
443 } else
444 /* Otherwise, just copy the string unaltered. This is
445 * essential for DNS-SD, where the casing of labels
446 * matters and needs to be retained. */
447 memcpy(w, d, l);
74b2466e
LP
448
449 return 0;
450}
451
f6a5fec6
LP
452int dns_packet_append_name(
453 DnsPacket *p,
454 const char *name,
455 bool allow_compression,
456 size_t *start) {
457
74b2466e
LP
458 size_t saved_size;
459 int r;
460
461 assert(p);
462 assert(name);
463
f6a5fec6
LP
464 if (p->refuse_compression)
465 allow_compression = false;
466
74b2466e
LP
467 saved_size = p->size;
468
469 while (*name) {
470 _cleanup_free_ char *s = NULL;
471 char label[DNS_LABEL_MAX];
151226ab 472 size_t n = 0;
bdf10b5b 473 int k;
74b2466e 474
151226ab
ZJS
475 if (allow_compression)
476 n = PTR_TO_SIZE(hashmap_get(p->names, name));
74b2466e
LP
477 if (n > 0) {
478 assert(n < p->size);
479
480 if (n < 0x4000) {
481 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
482 if (r < 0)
483 goto fail;
484
485 goto done;
486 }
487 }
488
489 s = strdup(name);
490 if (!s) {
491 r = -ENOMEM;
492 goto fail;
493 }
494
495 r = dns_label_unescape(&name, label, sizeof(label));
496 if (r < 0)
497 goto fail;
498
bdf10b5b
LP
499 if (p->protocol == DNS_PROTOCOL_DNS)
500 k = dns_label_apply_idna(label, r, label, sizeof(label));
501 else
502 k = dns_label_undo_idna(label, r, label, sizeof(label));
503 if (k < 0) {
504 r = k;
505 goto fail;
506 }
507 if (k > 0)
508 r = k;
509
74b2466e
LP
510 r = dns_packet_append_label(p, label, r, &n);
511 if (r < 0)
512 goto fail;
513
151226ab 514 if (allow_compression) {
d5099efc 515 r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops);
151226ab
ZJS
516 if (r < 0)
517 goto fail;
74b2466e 518
151226ab
ZJS
519 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
520 if (r < 0)
521 goto fail;
74b2466e 522
151226ab
ZJS
523 s = NULL;
524 }
74b2466e
LP
525 }
526
527 r = dns_packet_append_uint8(p, 0, NULL);
528 if (r < 0)
529 return r;
530
531done:
532 if (start)
533 *start = saved_size;
534
535 return 0;
536
537fail:
538 dns_packet_truncate(p, saved_size);
539 return r;
540}
541
542int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
543 size_t saved_size;
544 int r;
545
546 assert(p);
547 assert(k);
548
549 saved_size = p->size;
550
151226ab 551 r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, NULL);
74b2466e
LP
552 if (r < 0)
553 goto fail;
554
555 r = dns_packet_append_uint16(p, k->type, NULL);
556 if (r < 0)
557 goto fail;
558
559 r = dns_packet_append_uint16(p, k->class, NULL);
560 if (r < 0)
561 goto fail;
562
563 if (start)
564 *start = saved_size;
565
566 return 0;
567
568fail:
569 dns_packet_truncate(p, saved_size);
570 return r;
571}
572
50f1e641
TG
573static int dns_packet_append_type_window(DnsPacket *p, uint8_t window, uint8_t length, uint8_t *types, size_t *start) {
574 size_t saved_size;
575 int r;
576
577 assert(p);
578 assert(types);
1792f223 579 assert(length > 0);
50f1e641 580
50f1e641
TG
581 saved_size = p->size;
582
1792f223
TG
583 r = dns_packet_append_uint8(p, window, NULL);
584 if (r < 0)
585 goto fail;
50f1e641 586
1792f223
TG
587 r = dns_packet_append_uint8(p, length, NULL);
588 if (r < 0)
589 goto fail;
6fa91901 590
1792f223
TG
591 r = dns_packet_append_blob(p, types, length, NULL);
592 if (r < 0)
593 goto fail;
50f1e641
TG
594
595 if (start)
596 *start = saved_size;
597
598 return 0;
599fail:
600 dns_packet_truncate(p, saved_size);
601 return r;
602}
603
604static int dns_packet_append_types(DnsPacket *p, Bitmap *types, size_t *start) {
cb57dd41 605 Iterator i;
50f1e641 606 uint8_t window = 0;
1792f223 607 uint8_t entry = 0;
50f1e641
TG
608 uint8_t bitmaps[32] = {};
609 unsigned n;
610 size_t saved_size;
611 int r;
612
613 assert(p);
614 assert(types);
615
616 saved_size = p->size;
617
cb57dd41 618 BITMAP_FOREACH(n, types, i) {
50f1e641
TG
619 assert(n <= 0xffff);
620
1792f223
TG
621 if ((n >> 8) != window && bitmaps[entry / 8] != 0) {
622 r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
50f1e641
TG
623 if (r < 0)
624 goto fail;
625
1792f223 626 zero(bitmaps);
50f1e641
TG
627 }
628
1792f223 629 window = n >> 8;
50f1e641
TG
630
631 entry = n & 255;
632
633 bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
634 }
635
1792f223 636 r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
50f1e641
TG
637 if (r < 0)
638 goto fail;
639
640 if (start)
641 *start = saved_size;
642
643 return 0;
644fail:
645 dns_packet_truncate(p, saved_size);
646 return r;
647}
648
dc913c9a 649/* Append the OPT pseudo-RR described in RFC6891 */
7586f4d1 650int dns_packet_append_opt_rr(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start) {
dc913c9a
TG
651 size_t saved_size;
652 int r;
653
654 assert(p);
655 /* we must never advertise supported packet size smaller than the legacy max */
656 assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
657
658 saved_size = p->size;
659
660 /* empty name */
661 r = dns_packet_append_uint8(p, 0, NULL);
662 if (r < 0)
663 return r;
664
665 /* type */
666 r = dns_packet_append_uint16(p, DNS_TYPE_OPT, NULL);
667 if (r < 0)
668 goto fail;
669
670 /* maximum udp packet that can be received */
671 r = dns_packet_append_uint16(p, max_udp_size, NULL);
672 if (r < 0)
673 goto fail;
674
675 /* extended RCODE and VERSION */
676 r = dns_packet_append_uint16(p, 0, NULL);
677 if (r < 0)
678 goto fail;
679
7586f4d1
TG
680 /* flags: DNSSEC OK (DO), see RFC3225 */
681 r = dns_packet_append_uint16(p, edns0_do ? EDNS0_OPT_DO : 0, NULL);
dc913c9a
TG
682 if (r < 0)
683 goto fail;
684
685 /* RDLENGTH */
686 r = dns_packet_append_uint16(p, 0, NULL);
687 if (r < 0)
688 goto fail;
689
690 if (start)
691 *start = saved_size;
692
693 return 0;
694
695fail:
696 dns_packet_truncate(p, saved_size);
697 return r;
698}
699
a8812dd7
LP
700int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start) {
701 size_t saved_size, rdlength_offset, end, rdlength, rds;
623a4c97
LP
702 int r;
703
704 assert(p);
705 assert(rr);
706
707 saved_size = p->size;
708
709 r = dns_packet_append_key(p, rr->key, NULL);
710 if (r < 0)
711 goto fail;
712
713 r = dns_packet_append_uint32(p, rr->ttl, NULL);
714 if (r < 0)
715 goto fail;
716
717 /* Initially we write 0 here */
718 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
719 if (r < 0)
720 goto fail;
721
a8812dd7
LP
722 rds = p->size - saved_size;
723
0dae31d4 724 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
623a4c97 725
9c92ce6d
LP
726 case DNS_TYPE_SRV:
727 r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
728 if (r < 0)
729 goto fail;
730
731 r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
732 if (r < 0)
733 goto fail;
734
735 r = dns_packet_append_uint16(p, rr->srv.port, NULL);
736 if (r < 0)
737 goto fail;
738
151226ab 739 r = dns_packet_append_name(p, rr->srv.name, true, NULL);
9c92ce6d
LP
740 break;
741
623a4c97
LP
742 case DNS_TYPE_PTR:
743 case DNS_TYPE_NS:
744 case DNS_TYPE_CNAME:
8ac4e9e1 745 case DNS_TYPE_DNAME:
151226ab 746 r = dns_packet_append_name(p, rr->ptr.name, true, NULL);
623a4c97
LP
747 break;
748
749 case DNS_TYPE_HINFO:
750 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
751 if (r < 0)
752 goto fail;
753
754 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
755 break;
756
9de3e329 757 case DNS_TYPE_SPF: /* exactly the same as TXT */
2001c805 758 case DNS_TYPE_TXT:
2e276efc 759
2001c805 760 if (!rr->txt.items) {
1ccda9b7
LP
761 /* RFC 6763, section 6.1 suggests to generate
762 * single empty string for an empty array. */
763
2001c805 764 r = dns_packet_append_raw_string(p, NULL, 0, NULL);
2e276efc
ZJS
765 if (r < 0)
766 goto fail;
1ccda9b7 767 } else {
2001c805
LP
768 DnsTxtItem *i;
769
770 LIST_FOREACH(items, i, rr->txt.items) {
771 r = dns_packet_append_raw_string(p, i->data, i->length, NULL);
1ccda9b7
LP
772 if (r < 0)
773 goto fail;
774 }
2e276efc
ZJS
775 }
776
6a6fc3df 777 r = 0;
2e276efc 778 break;
2e276efc 779
623a4c97
LP
780 case DNS_TYPE_A:
781 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
782 break;
783
784 case DNS_TYPE_AAAA:
785 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
786 break;
787
788 case DNS_TYPE_SOA:
151226ab 789 r = dns_packet_append_name(p, rr->soa.mname, true, NULL);
623a4c97
LP
790 if (r < 0)
791 goto fail;
792
151226ab 793 r = dns_packet_append_name(p, rr->soa.rname, true, NULL);
623a4c97
LP
794 if (r < 0)
795 goto fail;
796
797 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
798 if (r < 0)
799 goto fail;
800
801 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
802 if (r < 0)
803 goto fail;
804
805 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
806 if (r < 0)
807 goto fail;
808
809 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
810 if (r < 0)
811 goto fail;
812
813 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
814 break;
815
816 case DNS_TYPE_MX:
946c7094
ZJS
817 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
818 if (r < 0)
819 goto fail;
820
151226ab 821 r = dns_packet_append_name(p, rr->mx.exchange, true, NULL);
946c7094
ZJS
822 break;
823
0dae31d4
ZJS
824 case DNS_TYPE_LOC:
825 r = dns_packet_append_uint8(p, rr->loc.version, NULL);
826 if (r < 0)
827 goto fail;
828
829 r = dns_packet_append_uint8(p, rr->loc.size, NULL);
830 if (r < 0)
831 goto fail;
832
833 r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
834 if (r < 0)
835 goto fail;
836
837 r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
838 if (r < 0)
839 goto fail;
840
afbc4f26 841 r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
0dae31d4
ZJS
842 if (r < 0)
843 goto fail;
844
afbc4f26 845 r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
0dae31d4
ZJS
846 if (r < 0)
847 goto fail;
848
afbc4f26 849 r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
0dae31d4
ZJS
850 break;
851
abf126a3
TG
852 case DNS_TYPE_DS:
853 r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL);
854 if (r < 0)
855 goto fail;
856
857 r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL);
858 if (r < 0)
859 goto fail;
860
861 r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL);
862 if (r < 0)
863 goto fail;
864
865 r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL);
866 break;
867
623a4c97 868 case DNS_TYPE_SSHFP:
42cc2eeb
LP
869 r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
870 if (r < 0)
871 goto fail;
8db0d2f5 872
42cc2eeb
LP
873 r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
874 if (r < 0)
875 goto fail;
876
549c1a25 877 r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL);
42cc2eeb
LP
878 break;
879
8db0d2f5 880 case DNS_TYPE_DNSKEY:
f91dc240 881 r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL);
8db0d2f5
ZJS
882 if (r < 0)
883 goto fail;
884
f91dc240 885 r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL);
8db0d2f5
ZJS
886 if (r < 0)
887 goto fail;
888
889 r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
890 if (r < 0)
891 goto fail;
892
893 r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
894 break;
895
151226ab
ZJS
896 case DNS_TYPE_RRSIG:
897 r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
898 if (r < 0)
899 goto fail;
900
901 r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
902 if (r < 0)
903 goto fail;
904
905 r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
906 if (r < 0)
907 goto fail;
908
909 r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
910 if (r < 0)
911 goto fail;
912
913 r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
914 if (r < 0)
915 goto fail;
916
917 r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
918 if (r < 0)
919 goto fail;
920
0b1b17d3 921 r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL);
151226ab
ZJS
922 if (r < 0)
923 goto fail;
924
925 r = dns_packet_append_name(p, rr->rrsig.signer, false, NULL);
926 if (r < 0)
927 goto fail;
928
929 r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
930 break;
931
50f1e641
TG
932 case DNS_TYPE_NSEC:
933 r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, NULL);
934 if (r < 0)
935 goto fail;
936
937 r = dns_packet_append_types(p, rr->nsec.types, NULL);
938 if (r < 0)
939 goto fail;
940
5d45a880
TG
941 break;
942 case DNS_TYPE_NSEC3:
943 r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL);
944 if (r < 0)
945 goto fail;
946
947 r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL);
948 if (r < 0)
949 goto fail;
950
951 r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL);
952 if (r < 0)
953 goto fail;
954
955 r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL);
956 if (r < 0)
957 goto fail;
958
959 r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL);
960 if (r < 0)
961 goto fail;
962
963 r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL);
964 if (r < 0)
965 goto fail;
966
967 r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL);
968 if (r < 0)
969 goto fail;
970
971 r = dns_packet_append_types(p, rr->nsec3.types, NULL);
972 if (r < 0)
973 goto fail;
974
50f1e641 975 break;
0dae31d4 976 case _DNS_TYPE_INVALID: /* unparseable */
623a4c97 977 default:
0dae31d4 978
623a4c97
LP
979 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
980 break;
981 }
982 if (r < 0)
983 goto fail;
984
985 /* Let's calculate the actual data size and update the field */
986 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
987 if (rdlength > 0xFFFF) {
988 r = ENOSPC;
989 goto fail;
990 }
991
992 end = p->size;
993 p->size = rdlength_offset;
994 r = dns_packet_append_uint16(p, rdlength, NULL);
995 if (r < 0)
996 goto fail;
997 p->size = end;
998
351e6342
LP
999 if (start)
1000 *start = saved_size;
1001
a8812dd7
LP
1002 if (rdata_start)
1003 *rdata_start = rds;
1004
623a4c97
LP
1005 return 0;
1006
1007fail:
1008 dns_packet_truncate(p, saved_size);
1009 return r;
1010}
1011
1012
74b2466e
LP
1013int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
1014 assert(p);
1015
1016 if (p->rindex + sz > p->size)
1017 return -EMSGSIZE;
1018
1019 if (ret)
1020 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
1021
1022 if (start)
1023 *start = p->rindex;
1024
1025 p->rindex += sz;
1026 return 0;
1027}
1028
8ba9fd9c 1029void dns_packet_rewind(DnsPacket *p, size_t idx) {
74b2466e
LP
1030 assert(p);
1031 assert(idx <= p->size);
1032 assert(idx >= DNS_PACKET_HEADER_SIZE);
1033
1034 p->rindex = idx;
1035}
1036
623a4c97
LP
1037int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
1038 const void *q;
1039 int r;
1040
1041 assert(p);
1042 assert(d);
1043
1044 r = dns_packet_read(p, sz, &q, start);
1045 if (r < 0)
1046 return r;
1047
1048 memcpy(d, q, sz);
1049 return 0;
1050}
1051
f5430a3e
LP
1052static int dns_packet_read_memdup(
1053 DnsPacket *p, size_t size,
1054 void **ret, size_t *ret_size,
1055 size_t *ret_start) {
1056
1057 const void *src;
1058 size_t start;
1059 int r;
1060
1061 assert(p);
1062 assert(ret);
1063
1064 r = dns_packet_read(p, size, &src, &start);
1065 if (r < 0)
1066 return r;
1067
1068 if (size <= 0)
1069 *ret = NULL;
1070 else {
1071 void *copy;
1072
1073 copy = memdup(src, size);
1074 if (!copy)
1075 return -ENOMEM;
1076
1077 *ret = copy;
1078 }
1079
1080 if (ret_size)
1081 *ret_size = size;
1082 if (ret_start)
1083 *ret_start = start;
1084
1085 return 0;
1086}
1087
74b2466e
LP
1088int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
1089 const void *d;
1090 int r;
1091
1092 assert(p);
1093
1094 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
1095 if (r < 0)
1096 return r;
1097
1098 *ret = ((uint8_t*) d)[0];
1099 return 0;
1100}
1101
1102int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
1103 const void *d;
1104 int r;
1105
1106 assert(p);
1107
1108 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
1109 if (r < 0)
1110 return r;
1111
725ca0e5
TG
1112 *ret = unaligned_read_be16(d);
1113
74b2466e
LP
1114 return 0;
1115}
1116
1117int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
1118 const void *d;
1119 int r;
1120
1121 assert(p);
1122
1123 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
1124 if (r < 0)
1125 return r;
1126
725ca0e5 1127 *ret = unaligned_read_be32(d);
74b2466e
LP
1128
1129 return 0;
1130}
1131
1132int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
1133 size_t saved_rindex;
1134 const void *d;
1135 char *t;
1136 uint8_t c;
1137 int r;
1138
1139 assert(p);
1140
1141 saved_rindex = p->rindex;
1142
1143 r = dns_packet_read_uint8(p, &c, NULL);
1144 if (r < 0)
1145 goto fail;
1146
1147 r = dns_packet_read(p, c, &d, NULL);
1148 if (r < 0)
1149 goto fail;
1150
1151 if (memchr(d, 0, c)) {
1152 r = -EBADMSG;
1153 goto fail;
1154 }
1155
1156 t = strndup(d, c);
1157 if (!t) {
1158 r = -ENOMEM;
1159 goto fail;
1160 }
1161
1162 if (!utf8_is_valid(t)) {
1163 free(t);
1164 r = -EBADMSG;
1165 goto fail;
1166 }
1167
1168 *ret = t;
1169
1170 if (start)
1171 *start = saved_rindex;
1172
1173 return 0;
1174
1175fail:
1176 dns_packet_rewind(p, saved_rindex);
1177 return r;
1178}
1179
2001c805
LP
1180int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start) {
1181 size_t saved_rindex;
1182 uint8_t c;
1183 int r;
1184
1185 assert(p);
1186
1187 saved_rindex = p->rindex;
1188
1189 r = dns_packet_read_uint8(p, &c, NULL);
1190 if (r < 0)
1191 goto fail;
1192
1193 r = dns_packet_read(p, c, ret, NULL);
1194 if (r < 0)
1195 goto fail;
1196
1197 if (size)
1198 *size = c;
1199 if (start)
1200 *start = saved_rindex;
1201
1202 return 0;
1203
1204fail:
1205 dns_packet_rewind(p, saved_rindex);
1206 return r;
1207}
1208
f6a5fec6
LP
1209int dns_packet_read_name(
1210 DnsPacket *p,
1211 char **_ret,
1212 bool allow_compression,
1213 size_t *start) {
1214
c75dbf9b 1215 size_t saved_rindex, after_rindex = 0, jump_barrier;
74b2466e
LP
1216 _cleanup_free_ char *ret = NULL;
1217 size_t n = 0, allocated = 0;
1218 bool first = true;
1219 int r;
1220
1221 assert(p);
1222 assert(_ret);
1223
f6a5fec6
LP
1224 if (p->refuse_compression)
1225 allow_compression = false;
1226
74b2466e 1227 saved_rindex = p->rindex;
c75dbf9b 1228 jump_barrier = p->rindex;
74b2466e
LP
1229
1230 for (;;) {
1231 uint8_t c, d;
1232
1233 r = dns_packet_read_uint8(p, &c, NULL);
1234 if (r < 0)
1235 goto fail;
1236
1237 if (c == 0)
1238 /* End of name */
1239 break;
1240 else if (c <= 63) {
74b2466e
LP
1241 const char *label;
1242
1243 /* Literal label */
1244 r = dns_packet_read(p, c, (const void**) &label, NULL);
1245 if (r < 0)
1246 goto fail;
1247
422baca0 1248 if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) {
74b2466e
LP
1249 r = -ENOMEM;
1250 goto fail;
1251 }
1252
422baca0 1253 if (first)
74b2466e 1254 first = false;
422baca0
LP
1255 else
1256 ret[n++] = '.';
1257
1258 r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
1259 if (r < 0)
1260 goto fail;
74b2466e 1261
74b2466e
LP
1262 n += r;
1263 continue;
151226ab 1264 } else if (allow_compression && (c & 0xc0) == 0xc0) {
74b2466e
LP
1265 uint16_t ptr;
1266
1267 /* Pointer */
1268 r = dns_packet_read_uint8(p, &d, NULL);
1269 if (r < 0)
1270 goto fail;
1271
1272 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
c75dbf9b 1273 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
74b2466e
LP
1274 r = -EBADMSG;
1275 goto fail;
1276 }
1277
1278 if (after_rindex == 0)
1279 after_rindex = p->rindex;
1280
f131770b 1281 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
c75dbf9b 1282 jump_barrier = ptr;
74b2466e 1283 p->rindex = ptr;
59aa5821
SP
1284 } else {
1285 r = -EBADMSG;
74b2466e 1286 goto fail;
59aa5821 1287 }
74b2466e
LP
1288 }
1289
1290 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
1291 r = -ENOMEM;
1292 goto fail;
1293 }
1294
1295 ret[n] = 0;
1296
1297 if (after_rindex != 0)
1298 p->rindex= after_rindex;
1299
1300 *_ret = ret;
1301 ret = NULL;
1302
1303 if (start)
1304 *start = saved_rindex;
1305
1306 return 0;
1307
1308fail:
1309 dns_packet_rewind(p, saved_rindex);
1310 return r;
1311}
1312
50f1e641
TG
1313static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) {
1314 uint8_t window;
1315 uint8_t length;
1316 const uint8_t *bitmap;
2ad613ad 1317 uint8_t bit = 0;
50f1e641
TG
1318 unsigned i;
1319 bool found = false;
1320 size_t saved_rindex;
1321 int r;
1322
1323 assert(p);
1324 assert(types);
1325
1326 saved_rindex = p->rindex;
1327
1328 r = bitmap_ensure_allocated(types);
1329 if (r < 0)
1330 goto fail;
1331
1332 r = dns_packet_read_uint8(p, &window, NULL);
1333 if (r < 0)
1334 goto fail;
1335
1336 r = dns_packet_read_uint8(p, &length, NULL);
1337 if (r < 0)
1338 goto fail;
1339
1340 if (length == 0 || length > 32)
1341 return -EBADMSG;
1342
1343 r = dns_packet_read(p, length, (const void **)&bitmap, NULL);
1344 if (r < 0)
1345 goto fail;
1346
1347 for (i = 0; i < length; i++) {
1348 uint8_t bitmask = 1 << 7;
50f1e641
TG
1349
1350 if (!bitmap[i]) {
1351 found = false;
2ad613ad 1352 bit += 8;
50f1e641
TG
1353 continue;
1354 }
1355
1356 found = true;
1357
1358 while (bitmask) {
1359 if (bitmap[i] & bitmask) {
1360 uint16_t n;
1361
50f1e641
TG
1362 n = (uint16_t) window << 8 | (uint16_t) bit;
1363
8e6edc49
TG
1364 /* Ignore pseudo-types. see RFC4034 section 4.1.2 */
1365 if (dns_type_is_pseudo(n))
1366 continue;
1367
50f1e641
TG
1368 r = bitmap_set(*types, n);
1369 if (r < 0)
1370 goto fail;
1371 }
1372
1373 bit ++;
1374 bitmask >>= 1;
1375 }
1376 }
1377
1378 if (!found)
1379 return -EBADMSG;
1380
1381 if (start)
1382 *start = saved_rindex;
1383
1384 return 0;
1385fail:
1386 dns_packet_rewind(p, saved_rindex);
1387 return r;
1388}
1389
89492aaf
TG
1390static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
1391 size_t saved_rindex;
1392 int r;
1393
1394 saved_rindex = p->rindex;
1395
1396 while (p->rindex < saved_rindex + size) {
1397 r = dns_packet_read_type_window(p, types, NULL);
1398 if (r < 0)
1399 goto fail;
1400
1401 /* don't read past end of current RR */
1402 if (p->rindex > saved_rindex + size) {
1403 r = -EBADMSG;
1404 goto fail;
1405 }
1406 }
1407
1408 if (p->rindex != saved_rindex + size) {
1409 r = -EBADMSG;
1410 goto fail;
1411 }
1412
1413 if (start)
1414 *start = saved_rindex;
1415
1416 return 0;
1417fail:
1418 dns_packet_rewind(p, saved_rindex);
1419 return r;
1420}
1421
faa133f3
LP
1422int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
1423 _cleanup_free_ char *name = NULL;
23502de3 1424 bool cache_flush = false;
faa133f3
LP
1425 uint16_t class, type;
1426 DnsResourceKey *key;
74b2466e
LP
1427 size_t saved_rindex;
1428 int r;
1429
1430 assert(p);
1431 assert(ret);
1432
1433 saved_rindex = p->rindex;
1434
151226ab 1435 r = dns_packet_read_name(p, &name, true, NULL);
74b2466e
LP
1436 if (r < 0)
1437 goto fail;
1438
faa133f3 1439 r = dns_packet_read_uint16(p, &type, NULL);
74b2466e
LP
1440 if (r < 0)
1441 goto fail;
1442
faa133f3 1443 r = dns_packet_read_uint16(p, &class, NULL);
74b2466e
LP
1444 if (r < 0)
1445 goto fail;
1446
23502de3
DM
1447 if (p->protocol == DNS_PROTOCOL_MDNS) {
1448 /* See RFC6762, Section 10.2 */
1449
1450 if (class & MDNS_RR_CACHE_FLUSH) {
1451 class &= ~MDNS_RR_CACHE_FLUSH;
1452 cache_flush = true;
1453 }
1454 }
1455
faa133f3
LP
1456 key = dns_resource_key_new_consume(class, type, name);
1457 if (!key) {
1458 r = -ENOMEM;
1459 goto fail;
1460 }
1461
23502de3
DM
1462 key->cache_flush = cache_flush;
1463
faa133f3
LP
1464 name = NULL;
1465 *ret = key;
74b2466e
LP
1466
1467 if (start)
1468 *start = saved_rindex;
1469
1470 return 0;
1471fail:
1472 dns_packet_rewind(p, saved_rindex);
1473 return r;
1474}
1475
afbc4f26
ZJS
1476static bool loc_size_ok(uint8_t size) {
1477 uint8_t m = size >> 4, e = size & 0xF;
1478
1479 return m <= 9 && e <= 9 && (m > 0 || e == 0);
1480}
1481
74b2466e 1482int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
faa133f3
LP
1483 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1484 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e
LP
1485 size_t saved_rindex, offset;
1486 uint16_t rdlength;
74b2466e
LP
1487 int r;
1488
1489 assert(p);
1490 assert(ret);
1491
4e0296a9 1492 saved_rindex = p->rindex;
74b2466e 1493
faa133f3 1494 r = dns_packet_read_key(p, &key, NULL);
74b2466e
LP
1495 if (r < 0)
1496 goto fail;
1497
0e2bcd6a
LP
1498 if (key->class == DNS_CLASS_ANY ||
1499 key->type == DNS_TYPE_ANY) {
1500 r = -EBADMSG;
1501 goto fail;
1502 }
1503
faa133f3
LP
1504 rr = dns_resource_record_new(key);
1505 if (!rr) {
1506 r = -ENOMEM;
1507 goto fail;
1508 }
1509
74b2466e
LP
1510 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1511 if (r < 0)
1512 goto fail;
1513
1514 r = dns_packet_read_uint16(p, &rdlength, NULL);
1515 if (r < 0)
1516 goto fail;
1517
1518 if (p->rindex + rdlength > p->size) {
1519 r = -EBADMSG;
1520 goto fail;
1521 }
1522
1523 offset = p->rindex;
1524
faa133f3 1525 switch (rr->key->type) {
74b2466e 1526
9c92ce6d
LP
1527 case DNS_TYPE_SRV:
1528 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1529 if (r < 0)
1530 goto fail;
1531 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1532 if (r < 0)
1533 goto fail;
1534 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1535 if (r < 0)
1536 goto fail;
151226ab 1537 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
9c92ce6d
LP
1538 break;
1539
74b2466e
LP
1540 case DNS_TYPE_PTR:
1541 case DNS_TYPE_NS:
1542 case DNS_TYPE_CNAME:
8ac4e9e1 1543 case DNS_TYPE_DNAME:
151226ab 1544 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1545 break;
1546
dc913c9a
TG
1547 case DNS_TYPE_OPT: /* we only care about the header */
1548 r = 0;
1549 break;
1550
74b2466e
LP
1551 case DNS_TYPE_HINFO:
1552 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1553 if (r < 0)
1554 goto fail;
1555
1556 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1557 break;
1558
9de3e329 1559 case DNS_TYPE_SPF: /* exactly the same as TXT */
1ccda9b7
LP
1560 case DNS_TYPE_TXT:
1561 if (rdlength <= 0) {
2001c805 1562 DnsTxtItem *i;
1ccda9b7
LP
1563 /* RFC 6763, section 6.1 suggests to treat
1564 * empty TXT RRs as equivalent to a TXT record
1565 * with a single empty string. */
0e3434ae 1566
2001c805
LP
1567 i = malloc0(offsetof(DnsTxtItem, data) + 1); /* for safety reasons we add an extra NUL byte */
1568 if (!i)
1569 return -ENOMEM;
1570
1571 rr->txt.items = i;
1ccda9b7 1572 } else {
2001c805
LP
1573 DnsTxtItem *last = NULL;
1574
1ccda9b7 1575 while (p->rindex < offset + rdlength) {
2001c805
LP
1576 DnsTxtItem *i;
1577 const void *data;
1578 size_t sz;
2e276efc 1579
2001c805 1580 r = dns_packet_read_raw_string(p, &data, &sz, NULL);
1ccda9b7 1581 if (r < 0)
2001c805 1582 return r;
1ccda9b7 1583
2001c805
LP
1584 i = malloc0(offsetof(DnsTxtItem, data) + sz + 1); /* extra NUL byte at the end */
1585 if (!i)
1586 return -ENOMEM;
1587
1588 memcpy(i->data, data, sz);
1589 i->length = sz;
1590
1591 LIST_INSERT_AFTER(items, rr->txt.items, last, i);
1592 last = i;
1ccda9b7 1593 }
6a6fc3df
LP
1594 }
1595
1596 r = 0;
2e276efc 1597 break;
2e276efc 1598
74b2466e 1599 case DNS_TYPE_A:
623a4c97 1600 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1601 break;
1602
1603 case DNS_TYPE_AAAA:
623a4c97 1604 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1605 break;
1606
7e8e0422 1607 case DNS_TYPE_SOA:
151226ab 1608 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422
LP
1609 if (r < 0)
1610 goto fail;
1611
151226ab 1612 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422
LP
1613 if (r < 0)
1614 goto fail;
1615
1616 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1617 if (r < 0)
1618 goto fail;
1619
1620 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1621 if (r < 0)
1622 goto fail;
1623
1624 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1625 if (r < 0)
1626 goto fail;
1627
1628 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1629 if (r < 0)
1630 goto fail;
1631
1632 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1633 break;
1634
623a4c97 1635 case DNS_TYPE_MX:
946c7094
ZJS
1636 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1637 if (r < 0)
1638 goto fail;
1639
151226ab 1640 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
1641 break;
1642
0dae31d4
ZJS
1643 case DNS_TYPE_LOC: {
1644 uint8_t t;
1645 size_t pos;
1646
1647 r = dns_packet_read_uint8(p, &t, &pos);
1648 if (r < 0)
1649 goto fail;
1650
1651 if (t == 0) {
1652 rr->loc.version = t;
1653
1654 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1655 if (r < 0)
1656 goto fail;
1657
afbc4f26
ZJS
1658 if (!loc_size_ok(rr->loc.size)) {
1659 r = -EBADMSG;
1660 goto fail;
1661 }
1662
0dae31d4
ZJS
1663 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1664 if (r < 0)
1665 goto fail;
1666
afbc4f26
ZJS
1667 if (!loc_size_ok(rr->loc.horiz_pre)) {
1668 r = -EBADMSG;
1669 goto fail;
1670 }
1671
0dae31d4
ZJS
1672 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1673 if (r < 0)
1674 goto fail;
1675
afbc4f26
ZJS
1676 if (!loc_size_ok(rr->loc.vert_pre)) {
1677 r = -EBADMSG;
1678 goto fail;
1679 }
1680
0dae31d4
ZJS
1681 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1682 if (r < 0)
1683 goto fail;
1684
1685 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1686 if (r < 0)
1687 goto fail;
1688
1689 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1690 if (r < 0)
1691 goto fail;
1692
1693 break;
1694 } else {
1695 dns_packet_rewind(p, pos);
1696 rr->unparseable = true;
afbc4f26 1697 goto unparseable;
0dae31d4
ZJS
1698 }
1699 }
1700
abf126a3
TG
1701 case DNS_TYPE_DS:
1702 r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
1703 if (r < 0)
1704 goto fail;
1705
1706 r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
1707 if (r < 0)
1708 goto fail;
1709
1710 r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
1711 if (r < 0)
1712 goto fail;
1713
f5430a3e
LP
1714 r = dns_packet_read_memdup(p, rdlength - 4,
1715 &rr->ds.digest, &rr->ds.digest_size,
1716 NULL);
abf126a3
TG
1717 if (r < 0)
1718 goto fail;
1719
f1d178cc
TG
1720 if (rr->ds.digest_size <= 0) {
1721 /* the accepted size depends on the algorithm, but for now
1722 just ensure that the value is greater than zero */
1723 r = -EBADMSG;
1724 goto fail;
1725 }
1726
abf126a3 1727 break;
623a4c97 1728 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1729 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1730 if (r < 0)
1731 goto fail;
1732
1733 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1734 if (r < 0)
1735 goto fail;
1736
f5430a3e 1737 r = dns_packet_read_memdup(p, rdlength - 2,
549c1a25 1738 &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size,
f5430a3e 1739 NULL);
f1d178cc 1740
549c1a25 1741 if (rr->sshfp.fingerprint_size <= 0) {
f1d178cc
TG
1742 /* the accepted size depends on the algorithm, but for now
1743 just ensure that the value is greater than zero */
1744 r = -EBADMSG;
1745 goto fail;
1746 }
1747
8db0d2f5
ZJS
1748 break;
1749
f91dc240
LP
1750 case DNS_TYPE_DNSKEY:
1751 r = dns_packet_read_uint16(p, &rr->dnskey.flags, NULL);
8db0d2f5
ZJS
1752 if (r < 0)
1753 goto fail;
1754
f91dc240 1755 r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL);
8db0d2f5
ZJS
1756 if (r < 0)
1757 goto fail;
1758
8db0d2f5
ZJS
1759 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1760 if (r < 0)
1761 goto fail;
1762
f5430a3e
LP
1763 r = dns_packet_read_memdup(p, rdlength - 4,
1764 &rr->dnskey.key, &rr->dnskey.key_size,
1765 NULL);
f1d178cc
TG
1766
1767 if (rr->dnskey.key_size <= 0) {
1768 /* the accepted size depends on the algorithm, but for now
1769 just ensure that the value is greater than zero */
1770 r = -EBADMSG;
1771 goto fail;
1772 }
1773
42cc2eeb
LP
1774 break;
1775
151226ab
ZJS
1776 case DNS_TYPE_RRSIG:
1777 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
1778 if (r < 0)
1779 goto fail;
1780
1781 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
1782 if (r < 0)
1783 goto fail;
1784
1785 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
1786 if (r < 0)
1787 goto fail;
1788
1789 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
1790 if (r < 0)
1791 goto fail;
1792
1793 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
1794 if (r < 0)
1795 goto fail;
1796
1797 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
1798 if (r < 0)
1799 goto fail;
1800
1801 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
1802 if (r < 0)
1803 goto fail;
1804
1805 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
1806 if (r < 0)
1807 goto fail;
1808
f5430a3e
LP
1809 r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
1810 &rr->rrsig.signature, &rr->rrsig.signature_size,
1811 NULL);
f1d178cc
TG
1812
1813 if (rr->rrsig.signature_size <= 0) {
1814 /* the accepted size depends on the algorithm, but for now
1815 just ensure that the value is greater than zero */
1816 r = -EBADMSG;
1817 goto fail;
1818 }
1819
151226ab
ZJS
1820 break;
1821
d84e543d
DM
1822 case DNS_TYPE_NSEC: {
1823
1824 /*
1825 * RFC6762, section 18.14 explicly states mDNS should use name compression.
1826 * This contradicts RFC3845, section 2.1.1
1827 */
1828
1829 bool allow_compressed = p->protocol == DNS_PROTOCOL_MDNS;
1830
1831 r = dns_packet_read_name(p, &rr->nsec.next_domain_name, allow_compressed, NULL);
50f1e641
TG
1832 if (r < 0)
1833 goto fail;
1834
89492aaf
TG
1835 r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
1836 if (r < 0)
1837 goto fail;
1838
09eaf68c
TG
1839 /* We accept empty NSEC bitmaps. The bit indicating the presence of the NSEC record itself
1840 * is redundant and in e.g., RFC4956 this fact is used to define a use for NSEC records
1841 * without the NSEC bit set. */
50f1e641
TG
1842
1843 break;
d84e543d 1844 }
5d45a880
TG
1845 case DNS_TYPE_NSEC3: {
1846 uint8_t size;
1847
1848 r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
1849 if (r < 0)
1850 goto fail;
1851
1852 r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
1853 if (r < 0)
1854 goto fail;
1855
1856 r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
1857 if (r < 0)
1858 goto fail;
1859
f1d178cc 1860 /* this may be zero */
5d45a880
TG
1861 r = dns_packet_read_uint8(p, &size, NULL);
1862 if (r < 0)
1863 goto fail;
1864
f5430a3e 1865 r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
5d45a880
TG
1866 if (r < 0)
1867 goto fail;
1868
5d45a880
TG
1869 r = dns_packet_read_uint8(p, &size, NULL);
1870 if (r < 0)
1871 goto fail;
1872
f1d178cc
TG
1873 if (size <= 0) {
1874 r = -EBADMSG;
1875 goto fail;
1876 }
1877
f5430a3e 1878 r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL);
5d45a880
TG
1879 if (r < 0)
1880 goto fail;
1881
6b9308d1 1882 r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL);
5d45a880
TG
1883 if (r < 0)
1884 goto fail;
1885
0bbd72b2
TG
1886 /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
1887
5d45a880
TG
1888 break;
1889 }
74b2466e 1890 default:
afbc4f26 1891 unparseable:
f5430a3e 1892 r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
74b2466e
LP
1893 if (r < 0)
1894 goto fail;
74b2466e
LP
1895 break;
1896 }
1897 if (r < 0)
1898 goto fail;
1899 if (p->rindex != offset + rdlength) {
1900 r = -EBADMSG;
1901 goto fail;
1902 }
1903
1904 *ret = rr;
1905 rr = NULL;
1906
1907 if (start)
1908 *start = saved_rindex;
1909
1910 return 0;
1911fail:
1912 dns_packet_rewind(p, saved_rindex);
1913 return r;
1914}
1915
faa133f3
LP
1916int dns_packet_extract(DnsPacket *p) {
1917 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1918 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1919 size_t saved_rindex;
1920 unsigned n, i;
74b2466e
LP
1921 int r;
1922
a4076574
LP
1923 if (p->extracted)
1924 return 0;
1925
faa133f3 1926 saved_rindex = p->rindex;
322345fd
LP
1927 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1928
3cb10d3a 1929 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
1930 if (n > 0) {
1931 question = dns_question_new(n);
1932 if (!question) {
1933 r = -ENOMEM;
1934 goto finish;
1935 }
74b2466e 1936
faa133f3
LP
1937 for (i = 0; i < n; i++) {
1938 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e 1939
faa133f3
LP
1940 r = dns_packet_read_key(p, &key, NULL);
1941 if (r < 0)
1942 goto finish;
74b2466e 1943
faa133f3
LP
1944 r = dns_question_add(question, key);
1945 if (r < 0)
1946 goto finish;
1947 }
1948 }
322345fd 1949
faa133f3
LP
1950 n = DNS_PACKET_RRCOUNT(p);
1951 if (n > 0) {
1952 answer = dns_answer_new(n);
1953 if (!answer) {
1954 r = -ENOMEM;
1955 goto finish;
1956 }
322345fd 1957
faa133f3
LP
1958 for (i = 0; i < n; i++) {
1959 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
322345fd 1960
faa133f3
LP
1961 r = dns_packet_read_rr(p, &rr, NULL);
1962 if (r < 0)
1963 goto finish;
322345fd 1964
78c6a153 1965 r = dns_answer_add(answer, rr, p->ifindex);
faa133f3
LP
1966 if (r < 0)
1967 goto finish;
1968 }
322345fd
LP
1969 }
1970
faa133f3
LP
1971 p->question = question;
1972 question = NULL;
322345fd 1973
faa133f3
LP
1974 p->answer = answer;
1975 answer = NULL;
322345fd 1976
a4076574
LP
1977 p->extracted = true;
1978
faa133f3 1979 r = 0;
322345fd
LP
1980
1981finish:
1982 p->rindex = saved_rindex;
1983 return r;
1984}
1985
74b2466e
LP
1986static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1987 [DNS_RCODE_SUCCESS] = "SUCCESS",
1988 [DNS_RCODE_FORMERR] = "FORMERR",
1989 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1990 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1991 [DNS_RCODE_NOTIMP] = "NOTIMP",
1992 [DNS_RCODE_REFUSED] = "REFUSED",
1993 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1994 [DNS_RCODE_YXRRSET] = "YRRSET",
1995 [DNS_RCODE_NXRRSET] = "NXRRSET",
1996 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1997 [DNS_RCODE_NOTZONE] = "NOTZONE",
1998 [DNS_RCODE_BADVERS] = "BADVERS",
1999 [DNS_RCODE_BADKEY] = "BADKEY",
2000 [DNS_RCODE_BADTIME] = "BADTIME",
2001 [DNS_RCODE_BADMODE] = "BADMODE",
2002 [DNS_RCODE_BADNAME] = "BADNAME",
2003 [DNS_RCODE_BADALG] = "BADALG",
2004 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
2005};
2006DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc
LP
2007
2008static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
2009 [DNS_PROTOCOL_DNS] = "dns",
2010 [DNS_PROTOCOL_MDNS] = "mdns",
2011 [DNS_PROTOCOL_LLMNR] = "llmnr",
2012};
2013DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);