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