]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
resolved: constify a parameter
[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
663 entry = n & 255;
664
665 bitmaps[entry / 8] |= 1 << (7 - (entry % 8));
666 }
667
1792f223 668 r = dns_packet_append_type_window(p, window, entry / 8 + 1, bitmaps, NULL);
50f1e641
TG
669 if (r < 0)
670 goto fail;
671
672 if (start)
673 *start = saved_size;
674
675 return 0;
676fail:
677 dns_packet_truncate(p, saved_size);
678 return r;
679}
680
dc913c9a 681/* Append the OPT pseudo-RR described in RFC6891 */
7586f4d1 682int dns_packet_append_opt_rr(DnsPacket *p, uint16_t max_udp_size, bool edns0_do, size_t *start) {
dc913c9a
TG
683 size_t saved_size;
684 int r;
685
686 assert(p);
687 /* we must never advertise supported packet size smaller than the legacy max */
688 assert(max_udp_size >= DNS_PACKET_UNICAST_SIZE_MAX);
689
690 saved_size = p->size;
691
692 /* empty name */
693 r = dns_packet_append_uint8(p, 0, NULL);
694 if (r < 0)
695 return r;
696
697 /* type */
698 r = dns_packet_append_uint16(p, DNS_TYPE_OPT, NULL);
699 if (r < 0)
700 goto fail;
701
702 /* maximum udp packet that can be received */
703 r = dns_packet_append_uint16(p, max_udp_size, NULL);
704 if (r < 0)
705 goto fail;
706
707 /* extended RCODE and VERSION */
708 r = dns_packet_append_uint16(p, 0, NULL);
709 if (r < 0)
710 goto fail;
711
7586f4d1
TG
712 /* flags: DNSSEC OK (DO), see RFC3225 */
713 r = dns_packet_append_uint16(p, edns0_do ? EDNS0_OPT_DO : 0, NULL);
dc913c9a
TG
714 if (r < 0)
715 goto fail;
716
717 /* RDLENGTH */
718 r = dns_packet_append_uint16(p, 0, NULL);
719 if (r < 0)
720 goto fail;
721
722 if (start)
723 *start = saved_size;
724
725 return 0;
726
727fail:
728 dns_packet_truncate(p, saved_size);
729 return r;
730}
731
a8812dd7
LP
732int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start, size_t *rdata_start) {
733 size_t saved_size, rdlength_offset, end, rdlength, rds;
623a4c97
LP
734 int r;
735
736 assert(p);
737 assert(rr);
738
739 saved_size = p->size;
740
741 r = dns_packet_append_key(p, rr->key, NULL);
742 if (r < 0)
743 goto fail;
744
745 r = dns_packet_append_uint32(p, rr->ttl, NULL);
746 if (r < 0)
747 goto fail;
748
749 /* Initially we write 0 here */
750 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
751 if (r < 0)
752 goto fail;
753
a8812dd7
LP
754 rds = p->size - saved_size;
755
0dae31d4 756 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
623a4c97 757
9c92ce6d
LP
758 case DNS_TYPE_SRV:
759 r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
760 if (r < 0)
761 goto fail;
762
763 r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
764 if (r < 0)
765 goto fail;
766
767 r = dns_packet_append_uint16(p, rr->srv.port, NULL);
768 if (r < 0)
769 goto fail;
770
a3db237b 771 r = dns_packet_append_name(p, rr->srv.name, true, false, NULL);
9c92ce6d
LP
772 break;
773
623a4c97
LP
774 case DNS_TYPE_PTR:
775 case DNS_TYPE_NS:
776 case DNS_TYPE_CNAME:
8ac4e9e1 777 case DNS_TYPE_DNAME:
a3db237b 778 r = dns_packet_append_name(p, rr->ptr.name, true, false, NULL);
623a4c97
LP
779 break;
780
781 case DNS_TYPE_HINFO:
782 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
783 if (r < 0)
784 goto fail;
785
786 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
787 break;
788
9de3e329 789 case DNS_TYPE_SPF: /* exactly the same as TXT */
2001c805 790 case DNS_TYPE_TXT:
2e276efc 791
2001c805 792 if (!rr->txt.items) {
1ccda9b7
LP
793 /* RFC 6763, section 6.1 suggests to generate
794 * single empty string for an empty array. */
795
2001c805 796 r = dns_packet_append_raw_string(p, NULL, 0, NULL);
2e276efc
ZJS
797 if (r < 0)
798 goto fail;
1ccda9b7 799 } else {
2001c805
LP
800 DnsTxtItem *i;
801
802 LIST_FOREACH(items, i, rr->txt.items) {
803 r = dns_packet_append_raw_string(p, i->data, i->length, NULL);
1ccda9b7
LP
804 if (r < 0)
805 goto fail;
806 }
2e276efc
ZJS
807 }
808
6a6fc3df 809 r = 0;
2e276efc 810 break;
2e276efc 811
623a4c97
LP
812 case DNS_TYPE_A:
813 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
814 break;
815
816 case DNS_TYPE_AAAA:
817 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
818 break;
819
820 case DNS_TYPE_SOA:
a3db237b 821 r = dns_packet_append_name(p, rr->soa.mname, true, false, NULL);
623a4c97
LP
822 if (r < 0)
823 goto fail;
824
a3db237b 825 r = dns_packet_append_name(p, rr->soa.rname, true, false, NULL);
623a4c97
LP
826 if (r < 0)
827 goto fail;
828
829 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
830 if (r < 0)
831 goto fail;
832
833 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
834 if (r < 0)
835 goto fail;
836
837 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
838 if (r < 0)
839 goto fail;
840
841 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
842 if (r < 0)
843 goto fail;
844
845 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
846 break;
847
848 case DNS_TYPE_MX:
946c7094
ZJS
849 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
850 if (r < 0)
851 goto fail;
852
a3db237b 853 r = dns_packet_append_name(p, rr->mx.exchange, true, false, NULL);
946c7094
ZJS
854 break;
855
0dae31d4
ZJS
856 case DNS_TYPE_LOC:
857 r = dns_packet_append_uint8(p, rr->loc.version, NULL);
858 if (r < 0)
859 goto fail;
860
861 r = dns_packet_append_uint8(p, rr->loc.size, NULL);
862 if (r < 0)
863 goto fail;
864
865 r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
866 if (r < 0)
867 goto fail;
868
869 r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
870 if (r < 0)
871 goto fail;
872
afbc4f26 873 r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
0dae31d4
ZJS
874 if (r < 0)
875 goto fail;
876
afbc4f26 877 r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
0dae31d4
ZJS
878 if (r < 0)
879 goto fail;
880
afbc4f26 881 r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
0dae31d4
ZJS
882 break;
883
abf126a3
TG
884 case DNS_TYPE_DS:
885 r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL);
886 if (r < 0)
887 goto fail;
888
889 r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL);
890 if (r < 0)
891 goto fail;
892
893 r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL);
894 if (r < 0)
895 goto fail;
896
897 r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL);
898 break;
899
623a4c97 900 case DNS_TYPE_SSHFP:
42cc2eeb
LP
901 r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
902 if (r < 0)
903 goto fail;
8db0d2f5 904
42cc2eeb
LP
905 r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
906 if (r < 0)
907 goto fail;
908
549c1a25 909 r = dns_packet_append_blob(p, rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, NULL);
42cc2eeb
LP
910 break;
911
8db0d2f5 912 case DNS_TYPE_DNSKEY:
f91dc240 913 r = dns_packet_append_uint16(p, rr->dnskey.flags, NULL);
8db0d2f5
ZJS
914 if (r < 0)
915 goto fail;
916
f91dc240 917 r = dns_packet_append_uint8(p, rr->dnskey.protocol, NULL);
8db0d2f5
ZJS
918 if (r < 0)
919 goto fail;
920
921 r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
922 if (r < 0)
923 goto fail;
924
925 r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
926 break;
927
151226ab
ZJS
928 case DNS_TYPE_RRSIG:
929 r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
930 if (r < 0)
931 goto fail;
932
933 r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
934 if (r < 0)
935 goto fail;
936
937 r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
938 if (r < 0)
939 goto fail;
940
941 r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
942 if (r < 0)
943 goto fail;
944
945 r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
946 if (r < 0)
947 goto fail;
948
949 r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
950 if (r < 0)
951 goto fail;
952
0b1b17d3 953 r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL);
151226ab
ZJS
954 if (r < 0)
955 goto fail;
956
a3db237b 957 r = dns_packet_append_name(p, rr->rrsig.signer, false, true, NULL);
151226ab
ZJS
958 if (r < 0)
959 goto fail;
960
961 r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
962 break;
963
50f1e641 964 case DNS_TYPE_NSEC:
a3db237b 965 r = dns_packet_append_name(p, rr->nsec.next_domain_name, false, false, NULL);
50f1e641
TG
966 if (r < 0)
967 goto fail;
968
969 r = dns_packet_append_types(p, rr->nsec.types, NULL);
970 if (r < 0)
971 goto fail;
972
5d45a880 973 break;
d75acfb0 974
5d45a880
TG
975 case DNS_TYPE_NSEC3:
976 r = dns_packet_append_uint8(p, rr->nsec3.algorithm, NULL);
977 if (r < 0)
978 goto fail;
979
980 r = dns_packet_append_uint8(p, rr->nsec3.flags, NULL);
981 if (r < 0)
982 goto fail;
983
984 r = dns_packet_append_uint16(p, rr->nsec3.iterations, NULL);
985 if (r < 0)
986 goto fail;
987
988 r = dns_packet_append_uint8(p, rr->nsec3.salt_size, NULL);
989 if (r < 0)
990 goto fail;
991
992 r = dns_packet_append_blob(p, rr->nsec3.salt, rr->nsec3.salt_size, NULL);
993 if (r < 0)
994 goto fail;
995
996 r = dns_packet_append_uint8(p, rr->nsec3.next_hashed_name_size, NULL);
997 if (r < 0)
998 goto fail;
999
1000 r = dns_packet_append_blob(p, rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, NULL);
1001 if (r < 0)
1002 goto fail;
1003
1004 r = dns_packet_append_types(p, rr->nsec3.types, NULL);
1005 if (r < 0)
1006 goto fail;
1007
50f1e641 1008 break;
d75acfb0
LP
1009
1010 case DNS_TYPE_OPT:
0dae31d4 1011 case _DNS_TYPE_INVALID: /* unparseable */
623a4c97 1012 default:
0dae31d4 1013
623a4c97
LP
1014 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
1015 break;
1016 }
1017 if (r < 0)
1018 goto fail;
1019
1020 /* Let's calculate the actual data size and update the field */
1021 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
1022 if (rdlength > 0xFFFF) {
1023 r = ENOSPC;
1024 goto fail;
1025 }
1026
1027 end = p->size;
1028 p->size = rdlength_offset;
1029 r = dns_packet_append_uint16(p, rdlength, NULL);
1030 if (r < 0)
1031 goto fail;
1032 p->size = end;
1033
351e6342
LP
1034 if (start)
1035 *start = saved_size;
1036
a8812dd7
LP
1037 if (rdata_start)
1038 *rdata_start = rds;
1039
623a4c97
LP
1040 return 0;
1041
1042fail:
1043 dns_packet_truncate(p, saved_size);
1044 return r;
1045}
1046
1047
74b2466e
LP
1048int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
1049 assert(p);
1050
1051 if (p->rindex + sz > p->size)
1052 return -EMSGSIZE;
1053
1054 if (ret)
1055 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
1056
1057 if (start)
1058 *start = p->rindex;
1059
1060 p->rindex += sz;
1061 return 0;
1062}
1063
8ba9fd9c 1064void dns_packet_rewind(DnsPacket *p, size_t idx) {
74b2466e
LP
1065 assert(p);
1066 assert(idx <= p->size);
1067 assert(idx >= DNS_PACKET_HEADER_SIZE);
1068
1069 p->rindex = idx;
1070}
1071
623a4c97
LP
1072int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
1073 const void *q;
1074 int r;
1075
1076 assert(p);
1077 assert(d);
1078
1079 r = dns_packet_read(p, sz, &q, start);
1080 if (r < 0)
1081 return r;
1082
1083 memcpy(d, q, sz);
1084 return 0;
1085}
1086
f5430a3e
LP
1087static int dns_packet_read_memdup(
1088 DnsPacket *p, size_t size,
1089 void **ret, size_t *ret_size,
1090 size_t *ret_start) {
1091
1092 const void *src;
1093 size_t start;
1094 int r;
1095
1096 assert(p);
1097 assert(ret);
1098
1099 r = dns_packet_read(p, size, &src, &start);
1100 if (r < 0)
1101 return r;
1102
1103 if (size <= 0)
1104 *ret = NULL;
1105 else {
1106 void *copy;
1107
1108 copy = memdup(src, size);
1109 if (!copy)
1110 return -ENOMEM;
1111
1112 *ret = copy;
1113 }
1114
1115 if (ret_size)
1116 *ret_size = size;
1117 if (ret_start)
1118 *ret_start = start;
1119
1120 return 0;
1121}
1122
74b2466e
LP
1123int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
1124 const void *d;
1125 int r;
1126
1127 assert(p);
1128
1129 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
1130 if (r < 0)
1131 return r;
1132
1133 *ret = ((uint8_t*) d)[0];
1134 return 0;
1135}
1136
1137int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
1138 const void *d;
1139 int r;
1140
1141 assert(p);
1142
1143 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
1144 if (r < 0)
1145 return r;
1146
725ca0e5
TG
1147 *ret = unaligned_read_be16(d);
1148
74b2466e
LP
1149 return 0;
1150}
1151
1152int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
1153 const void *d;
1154 int r;
1155
1156 assert(p);
1157
1158 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
1159 if (r < 0)
1160 return r;
1161
725ca0e5 1162 *ret = unaligned_read_be32(d);
74b2466e
LP
1163
1164 return 0;
1165}
1166
1167int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
1168 size_t saved_rindex;
1169 const void *d;
1170 char *t;
1171 uint8_t c;
1172 int r;
1173
1174 assert(p);
1175
1176 saved_rindex = p->rindex;
1177
1178 r = dns_packet_read_uint8(p, &c, NULL);
1179 if (r < 0)
1180 goto fail;
1181
1182 r = dns_packet_read(p, c, &d, NULL);
1183 if (r < 0)
1184 goto fail;
1185
1186 if (memchr(d, 0, c)) {
1187 r = -EBADMSG;
1188 goto fail;
1189 }
1190
1191 t = strndup(d, c);
1192 if (!t) {
1193 r = -ENOMEM;
1194 goto fail;
1195 }
1196
1197 if (!utf8_is_valid(t)) {
1198 free(t);
1199 r = -EBADMSG;
1200 goto fail;
1201 }
1202
1203 *ret = t;
1204
1205 if (start)
1206 *start = saved_rindex;
1207
1208 return 0;
1209
1210fail:
1211 dns_packet_rewind(p, saved_rindex);
1212 return r;
1213}
1214
2001c805
LP
1215int dns_packet_read_raw_string(DnsPacket *p, const void **ret, size_t *size, size_t *start) {
1216 size_t saved_rindex;
1217 uint8_t c;
1218 int r;
1219
1220 assert(p);
1221
1222 saved_rindex = p->rindex;
1223
1224 r = dns_packet_read_uint8(p, &c, NULL);
1225 if (r < 0)
1226 goto fail;
1227
1228 r = dns_packet_read(p, c, ret, NULL);
1229 if (r < 0)
1230 goto fail;
1231
1232 if (size)
1233 *size = c;
1234 if (start)
1235 *start = saved_rindex;
1236
1237 return 0;
1238
1239fail:
1240 dns_packet_rewind(p, saved_rindex);
1241 return r;
1242}
1243
f6a5fec6
LP
1244int dns_packet_read_name(
1245 DnsPacket *p,
1246 char **_ret,
1247 bool allow_compression,
1248 size_t *start) {
1249
c75dbf9b 1250 size_t saved_rindex, after_rindex = 0, jump_barrier;
74b2466e
LP
1251 _cleanup_free_ char *ret = NULL;
1252 size_t n = 0, allocated = 0;
1253 bool first = true;
1254 int r;
1255
1256 assert(p);
1257 assert(_ret);
1258
f6a5fec6
LP
1259 if (p->refuse_compression)
1260 allow_compression = false;
1261
74b2466e 1262 saved_rindex = p->rindex;
c75dbf9b 1263 jump_barrier = p->rindex;
74b2466e
LP
1264
1265 for (;;) {
1266 uint8_t c, d;
1267
1268 r = dns_packet_read_uint8(p, &c, NULL);
1269 if (r < 0)
1270 goto fail;
1271
1272 if (c == 0)
1273 /* End of name */
1274 break;
1275 else if (c <= 63) {
74b2466e
LP
1276 const char *label;
1277
1278 /* Literal label */
1279 r = dns_packet_read(p, c, (const void**) &label, NULL);
1280 if (r < 0)
1281 goto fail;
1282
422baca0 1283 if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) {
74b2466e
LP
1284 r = -ENOMEM;
1285 goto fail;
1286 }
1287
422baca0 1288 if (first)
74b2466e 1289 first = false;
422baca0
LP
1290 else
1291 ret[n++] = '.';
1292
1293 r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX);
1294 if (r < 0)
1295 goto fail;
74b2466e 1296
74b2466e
LP
1297 n += r;
1298 continue;
151226ab 1299 } else if (allow_compression && (c & 0xc0) == 0xc0) {
74b2466e
LP
1300 uint16_t ptr;
1301
1302 /* Pointer */
1303 r = dns_packet_read_uint8(p, &d, NULL);
1304 if (r < 0)
1305 goto fail;
1306
1307 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
c75dbf9b 1308 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
74b2466e
LP
1309 r = -EBADMSG;
1310 goto fail;
1311 }
1312
1313 if (after_rindex == 0)
1314 after_rindex = p->rindex;
1315
f131770b 1316 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
c75dbf9b 1317 jump_barrier = ptr;
74b2466e 1318 p->rindex = ptr;
59aa5821
SP
1319 } else {
1320 r = -EBADMSG;
74b2466e 1321 goto fail;
59aa5821 1322 }
74b2466e
LP
1323 }
1324
1325 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
1326 r = -ENOMEM;
1327 goto fail;
1328 }
1329
1330 ret[n] = 0;
1331
1332 if (after_rindex != 0)
1333 p->rindex= after_rindex;
1334
1335 *_ret = ret;
1336 ret = NULL;
1337
1338 if (start)
1339 *start = saved_rindex;
1340
1341 return 0;
1342
1343fail:
1344 dns_packet_rewind(p, saved_rindex);
1345 return r;
1346}
1347
50f1e641
TG
1348static int dns_packet_read_type_window(DnsPacket *p, Bitmap **types, size_t *start) {
1349 uint8_t window;
1350 uint8_t length;
1351 const uint8_t *bitmap;
2ad613ad 1352 uint8_t bit = 0;
50f1e641
TG
1353 unsigned i;
1354 bool found = false;
1355 size_t saved_rindex;
1356 int r;
1357
1358 assert(p);
1359 assert(types);
1360
1361 saved_rindex = p->rindex;
1362
1363 r = bitmap_ensure_allocated(types);
1364 if (r < 0)
1365 goto fail;
1366
1367 r = dns_packet_read_uint8(p, &window, NULL);
1368 if (r < 0)
1369 goto fail;
1370
1371 r = dns_packet_read_uint8(p, &length, NULL);
1372 if (r < 0)
1373 goto fail;
1374
1375 if (length == 0 || length > 32)
1376 return -EBADMSG;
1377
1378 r = dns_packet_read(p, length, (const void **)&bitmap, NULL);
1379 if (r < 0)
1380 goto fail;
1381
1382 for (i = 0; i < length; i++) {
1383 uint8_t bitmask = 1 << 7;
50f1e641
TG
1384
1385 if (!bitmap[i]) {
1386 found = false;
2ad613ad 1387 bit += 8;
50f1e641
TG
1388 continue;
1389 }
1390
1391 found = true;
1392
1393 while (bitmask) {
1394 if (bitmap[i] & bitmask) {
1395 uint16_t n;
1396
50f1e641
TG
1397 n = (uint16_t) window << 8 | (uint16_t) bit;
1398
8e6edc49
TG
1399 /* Ignore pseudo-types. see RFC4034 section 4.1.2 */
1400 if (dns_type_is_pseudo(n))
1401 continue;
1402
50f1e641
TG
1403 r = bitmap_set(*types, n);
1404 if (r < 0)
1405 goto fail;
1406 }
1407
1408 bit ++;
1409 bitmask >>= 1;
1410 }
1411 }
1412
1413 if (!found)
1414 return -EBADMSG;
1415
1416 if (start)
1417 *start = saved_rindex;
1418
1419 return 0;
1420fail:
1421 dns_packet_rewind(p, saved_rindex);
1422 return r;
1423}
1424
89492aaf
TG
1425static int dns_packet_read_type_windows(DnsPacket *p, Bitmap **types, size_t size, size_t *start) {
1426 size_t saved_rindex;
1427 int r;
1428
1429 saved_rindex = p->rindex;
1430
1431 while (p->rindex < saved_rindex + size) {
1432 r = dns_packet_read_type_window(p, types, NULL);
1433 if (r < 0)
1434 goto fail;
1435
1436 /* don't read past end of current RR */
1437 if (p->rindex > saved_rindex + size) {
1438 r = -EBADMSG;
1439 goto fail;
1440 }
1441 }
1442
1443 if (p->rindex != saved_rindex + size) {
1444 r = -EBADMSG;
1445 goto fail;
1446 }
1447
1448 if (start)
1449 *start = saved_rindex;
1450
1451 return 0;
1452fail:
1453 dns_packet_rewind(p, saved_rindex);
1454 return r;
1455}
1456
faa133f3
LP
1457int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
1458 _cleanup_free_ char *name = NULL;
02c2857b 1459 bool cache_flush = true;
faa133f3
LP
1460 uint16_t class, type;
1461 DnsResourceKey *key;
74b2466e
LP
1462 size_t saved_rindex;
1463 int r;
1464
1465 assert(p);
1466 assert(ret);
1467
1468 saved_rindex = p->rindex;
1469
151226ab 1470 r = dns_packet_read_name(p, &name, true, NULL);
74b2466e
LP
1471 if (r < 0)
1472 goto fail;
1473
faa133f3 1474 r = dns_packet_read_uint16(p, &type, NULL);
74b2466e
LP
1475 if (r < 0)
1476 goto fail;
1477
faa133f3 1478 r = dns_packet_read_uint16(p, &class, NULL);
74b2466e
LP
1479 if (r < 0)
1480 goto fail;
1481
23502de3
DM
1482 if (p->protocol == DNS_PROTOCOL_MDNS) {
1483 /* See RFC6762, Section 10.2 */
1484
02c2857b 1485 if (class & MDNS_RR_CACHE_FLUSH)
23502de3 1486 class &= ~MDNS_RR_CACHE_FLUSH;
02c2857b
TG
1487 else
1488 cache_flush = false;
23502de3
DM
1489 }
1490
faa133f3
LP
1491 key = dns_resource_key_new_consume(class, type, name);
1492 if (!key) {
1493 r = -ENOMEM;
1494 goto fail;
1495 }
1496
23502de3
DM
1497 key->cache_flush = cache_flush;
1498
faa133f3
LP
1499 name = NULL;
1500 *ret = key;
74b2466e
LP
1501
1502 if (start)
1503 *start = saved_rindex;
1504
1505 return 0;
1506fail:
1507 dns_packet_rewind(p, saved_rindex);
1508 return r;
1509}
1510
afbc4f26
ZJS
1511static bool loc_size_ok(uint8_t size) {
1512 uint8_t m = size >> 4, e = size & 0xF;
1513
1514 return m <= 9 && e <= 9 && (m > 0 || e == 0);
1515}
1516
74b2466e 1517int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
faa133f3
LP
1518 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1519 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e
LP
1520 size_t saved_rindex, offset;
1521 uint16_t rdlength;
74b2466e
LP
1522 int r;
1523
1524 assert(p);
1525 assert(ret);
1526
4e0296a9 1527 saved_rindex = p->rindex;
74b2466e 1528
faa133f3 1529 r = dns_packet_read_key(p, &key, NULL);
74b2466e
LP
1530 if (r < 0)
1531 goto fail;
1532
0e2bcd6a 1533 if (key->class == DNS_CLASS_ANY ||
c463eb78 1534 !dns_type_is_valid_rr(key->type)) {
0e2bcd6a
LP
1535 r = -EBADMSG;
1536 goto fail;
1537 }
1538
faa133f3
LP
1539 rr = dns_resource_record_new(key);
1540 if (!rr) {
1541 r = -ENOMEM;
1542 goto fail;
1543 }
1544
74b2466e
LP
1545 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1546 if (r < 0)
1547 goto fail;
1548
1549 r = dns_packet_read_uint16(p, &rdlength, NULL);
1550 if (r < 0)
1551 goto fail;
1552
1553 if (p->rindex + rdlength > p->size) {
1554 r = -EBADMSG;
1555 goto fail;
1556 }
1557
1558 offset = p->rindex;
1559
faa133f3 1560 switch (rr->key->type) {
74b2466e 1561
9c92ce6d
LP
1562 case DNS_TYPE_SRV:
1563 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1564 if (r < 0)
1565 goto fail;
1566 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1567 if (r < 0)
1568 goto fail;
1569 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1570 if (r < 0)
1571 goto fail;
151226ab 1572 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
9c92ce6d
LP
1573 break;
1574
74b2466e
LP
1575 case DNS_TYPE_PTR:
1576 case DNS_TYPE_NS:
1577 case DNS_TYPE_CNAME:
8ac4e9e1 1578 case DNS_TYPE_DNAME:
151226ab 1579 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1580 break;
1581
1582 case DNS_TYPE_HINFO:
1583 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1584 if (r < 0)
1585 goto fail;
1586
1587 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1588 break;
1589
9de3e329 1590 case DNS_TYPE_SPF: /* exactly the same as TXT */
1ccda9b7
LP
1591 case DNS_TYPE_TXT:
1592 if (rdlength <= 0) {
2001c805 1593 DnsTxtItem *i;
1ccda9b7
LP
1594 /* RFC 6763, section 6.1 suggests to treat
1595 * empty TXT RRs as equivalent to a TXT record
1596 * with a single empty string. */
0e3434ae 1597
2001c805
LP
1598 i = malloc0(offsetof(DnsTxtItem, data) + 1); /* for safety reasons we add an extra NUL byte */
1599 if (!i)
1600 return -ENOMEM;
1601
1602 rr->txt.items = i;
1ccda9b7 1603 } else {
2001c805
LP
1604 DnsTxtItem *last = NULL;
1605
1ccda9b7 1606 while (p->rindex < offset + rdlength) {
2001c805
LP
1607 DnsTxtItem *i;
1608 const void *data;
1609 size_t sz;
2e276efc 1610
2001c805 1611 r = dns_packet_read_raw_string(p, &data, &sz, NULL);
1ccda9b7 1612 if (r < 0)
2001c805 1613 return r;
1ccda9b7 1614
2001c805
LP
1615 i = malloc0(offsetof(DnsTxtItem, data) + sz + 1); /* extra NUL byte at the end */
1616 if (!i)
1617 return -ENOMEM;
1618
1619 memcpy(i->data, data, sz);
1620 i->length = sz;
1621
1622 LIST_INSERT_AFTER(items, rr->txt.items, last, i);
1623 last = i;
1ccda9b7 1624 }
6a6fc3df
LP
1625 }
1626
1627 r = 0;
2e276efc 1628 break;
2e276efc 1629
74b2466e 1630 case DNS_TYPE_A:
623a4c97 1631 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1632 break;
1633
1634 case DNS_TYPE_AAAA:
623a4c97 1635 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1636 break;
1637
7e8e0422 1638 case DNS_TYPE_SOA:
151226ab 1639 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422
LP
1640 if (r < 0)
1641 goto fail;
1642
151226ab 1643 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422
LP
1644 if (r < 0)
1645 goto fail;
1646
1647 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1648 if (r < 0)
1649 goto fail;
1650
1651 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1652 if (r < 0)
1653 goto fail;
1654
1655 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1656 if (r < 0)
1657 goto fail;
1658
1659 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1660 if (r < 0)
1661 goto fail;
1662
1663 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1664 break;
1665
623a4c97 1666 case DNS_TYPE_MX:
946c7094
ZJS
1667 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1668 if (r < 0)
1669 goto fail;
1670
151226ab 1671 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
1672 break;
1673
0dae31d4
ZJS
1674 case DNS_TYPE_LOC: {
1675 uint8_t t;
1676 size_t pos;
1677
1678 r = dns_packet_read_uint8(p, &t, &pos);
1679 if (r < 0)
1680 goto fail;
1681
1682 if (t == 0) {
1683 rr->loc.version = t;
1684
1685 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1686 if (r < 0)
1687 goto fail;
1688
afbc4f26
ZJS
1689 if (!loc_size_ok(rr->loc.size)) {
1690 r = -EBADMSG;
1691 goto fail;
1692 }
1693
0dae31d4
ZJS
1694 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1695 if (r < 0)
1696 goto fail;
1697
afbc4f26
ZJS
1698 if (!loc_size_ok(rr->loc.horiz_pre)) {
1699 r = -EBADMSG;
1700 goto fail;
1701 }
1702
0dae31d4
ZJS
1703 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1704 if (r < 0)
1705 goto fail;
1706
afbc4f26
ZJS
1707 if (!loc_size_ok(rr->loc.vert_pre)) {
1708 r = -EBADMSG;
1709 goto fail;
1710 }
1711
0dae31d4
ZJS
1712 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1713 if (r < 0)
1714 goto fail;
1715
1716 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1717 if (r < 0)
1718 goto fail;
1719
1720 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1721 if (r < 0)
1722 goto fail;
1723
1724 break;
1725 } else {
1726 dns_packet_rewind(p, pos);
1727 rr->unparseable = true;
afbc4f26 1728 goto unparseable;
0dae31d4
ZJS
1729 }
1730 }
1731
abf126a3
TG
1732 case DNS_TYPE_DS:
1733 r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
1734 if (r < 0)
1735 goto fail;
1736
1737 r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
1738 if (r < 0)
1739 goto fail;
1740
1741 r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
1742 if (r < 0)
1743 goto fail;
1744
f5430a3e
LP
1745 r = dns_packet_read_memdup(p, rdlength - 4,
1746 &rr->ds.digest, &rr->ds.digest_size,
1747 NULL);
abf126a3
TG
1748 if (r < 0)
1749 goto fail;
1750
f1d178cc
TG
1751 if (rr->ds.digest_size <= 0) {
1752 /* the accepted size depends on the algorithm, but for now
1753 just ensure that the value is greater than zero */
1754 r = -EBADMSG;
1755 goto fail;
1756 }
1757
abf126a3 1758 break;
d75acfb0 1759
623a4c97 1760 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1761 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1762 if (r < 0)
1763 goto fail;
1764
1765 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1766 if (r < 0)
1767 goto fail;
1768
f5430a3e 1769 r = dns_packet_read_memdup(p, rdlength - 2,
549c1a25 1770 &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size,
f5430a3e 1771 NULL);
f1d178cc 1772
549c1a25 1773 if (rr->sshfp.fingerprint_size <= 0) {
f1d178cc
TG
1774 /* the accepted size depends on the algorithm, but for now
1775 just ensure that the value is greater than zero */
1776 r = -EBADMSG;
1777 goto fail;
1778 }
1779
8db0d2f5
ZJS
1780 break;
1781
f91dc240
LP
1782 case DNS_TYPE_DNSKEY:
1783 r = dns_packet_read_uint16(p, &rr->dnskey.flags, NULL);
8db0d2f5
ZJS
1784 if (r < 0)
1785 goto fail;
1786
f91dc240 1787 r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL);
8db0d2f5
ZJS
1788 if (r < 0)
1789 goto fail;
1790
8db0d2f5
ZJS
1791 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1792 if (r < 0)
1793 goto fail;
1794
f5430a3e
LP
1795 r = dns_packet_read_memdup(p, rdlength - 4,
1796 &rr->dnskey.key, &rr->dnskey.key_size,
1797 NULL);
f1d178cc
TG
1798
1799 if (rr->dnskey.key_size <= 0) {
1800 /* the accepted size depends on the algorithm, but for now
1801 just ensure that the value is greater than zero */
1802 r = -EBADMSG;
1803 goto fail;
1804 }
1805
42cc2eeb
LP
1806 break;
1807
151226ab
ZJS
1808 case DNS_TYPE_RRSIG:
1809 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
1810 if (r < 0)
1811 goto fail;
1812
1813 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
1814 if (r < 0)
1815 goto fail;
1816
1817 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
1818 if (r < 0)
1819 goto fail;
1820
1821 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
1822 if (r < 0)
1823 goto fail;
1824
1825 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
1826 if (r < 0)
1827 goto fail;
1828
1829 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
1830 if (r < 0)
1831 goto fail;
1832
1833 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
1834 if (r < 0)
1835 goto fail;
1836
1837 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
1838 if (r < 0)
1839 goto fail;
1840
f5430a3e
LP
1841 r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
1842 &rr->rrsig.signature, &rr->rrsig.signature_size,
1843 NULL);
f1d178cc
TG
1844
1845 if (rr->rrsig.signature_size <= 0) {
1846 /* the accepted size depends on the algorithm, but for now
1847 just ensure that the value is greater than zero */
1848 r = -EBADMSG;
1849 goto fail;
1850 }
1851
151226ab
ZJS
1852 break;
1853
d84e543d
DM
1854 case DNS_TYPE_NSEC: {
1855
1856 /*
e5abebab 1857 * RFC6762, section 18.14 explictly states mDNS should use name compression.
d84e543d
DM
1858 * This contradicts RFC3845, section 2.1.1
1859 */
1860
1861 bool allow_compressed = p->protocol == DNS_PROTOCOL_MDNS;
1862
1863 r = dns_packet_read_name(p, &rr->nsec.next_domain_name, allow_compressed, NULL);
50f1e641
TG
1864 if (r < 0)
1865 goto fail;
1866
89492aaf
TG
1867 r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
1868 if (r < 0)
1869 goto fail;
1870
09eaf68c
TG
1871 /* We accept empty NSEC bitmaps. The bit indicating the presence of the NSEC record itself
1872 * is redundant and in e.g., RFC4956 this fact is used to define a use for NSEC records
1873 * without the NSEC bit set. */
50f1e641
TG
1874
1875 break;
d84e543d 1876 }
5d45a880
TG
1877 case DNS_TYPE_NSEC3: {
1878 uint8_t size;
1879
1880 r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
1881 if (r < 0)
1882 goto fail;
1883
1884 r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
1885 if (r < 0)
1886 goto fail;
1887
1888 r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
1889 if (r < 0)
1890 goto fail;
1891
f1d178cc 1892 /* this may be zero */
5d45a880
TG
1893 r = dns_packet_read_uint8(p, &size, NULL);
1894 if (r < 0)
1895 goto fail;
1896
f5430a3e 1897 r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
5d45a880
TG
1898 if (r < 0)
1899 goto fail;
1900
5d45a880
TG
1901 r = dns_packet_read_uint8(p, &size, NULL);
1902 if (r < 0)
1903 goto fail;
1904
f1d178cc
TG
1905 if (size <= 0) {
1906 r = -EBADMSG;
1907 goto fail;
1908 }
1909
f5430a3e 1910 r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL);
5d45a880
TG
1911 if (r < 0)
1912 goto fail;
1913
6b9308d1 1914 r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL);
5d45a880
TG
1915 if (r < 0)
1916 goto fail;
1917
0bbd72b2
TG
1918 /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
1919
5d45a880
TG
1920 break;
1921 }
d75acfb0
LP
1922
1923 case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */
74b2466e 1924 default:
afbc4f26 1925 unparseable:
f5430a3e 1926 r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
74b2466e
LP
1927 if (r < 0)
1928 goto fail;
74b2466e
LP
1929 break;
1930 }
1931 if (r < 0)
1932 goto fail;
1933 if (p->rindex != offset + rdlength) {
1934 r = -EBADMSG;
1935 goto fail;
1936 }
1937
1938 *ret = rr;
1939 rr = NULL;
1940
1941 if (start)
1942 *start = saved_rindex;
1943
1944 return 0;
1945fail:
1946 dns_packet_rewind(p, saved_rindex);
1947 return r;
1948}
1949
faa133f3
LP
1950int dns_packet_extract(DnsPacket *p) {
1951 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1952 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1953 size_t saved_rindex;
1954 unsigned n, i;
74b2466e
LP
1955 int r;
1956
a4076574
LP
1957 if (p->extracted)
1958 return 0;
1959
faa133f3 1960 saved_rindex = p->rindex;
322345fd
LP
1961 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1962
3cb10d3a 1963 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
1964 if (n > 0) {
1965 question = dns_question_new(n);
1966 if (!question) {
1967 r = -ENOMEM;
1968 goto finish;
1969 }
74b2466e 1970
faa133f3
LP
1971 for (i = 0; i < n; i++) {
1972 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e 1973
faa133f3
LP
1974 r = dns_packet_read_key(p, &key, NULL);
1975 if (r < 0)
1976 goto finish;
74b2466e 1977
c463eb78
LP
1978 if (!dns_type_is_valid_query(key->type)) {
1979 r = -EBADMSG;
1980 goto finish;
1981 }
1982
faa133f3
LP
1983 r = dns_question_add(question, key);
1984 if (r < 0)
1985 goto finish;
1986 }
1987 }
322345fd 1988
faa133f3
LP
1989 n = DNS_PACKET_RRCOUNT(p);
1990 if (n > 0) {
1991 answer = dns_answer_new(n);
1992 if (!answer) {
1993 r = -ENOMEM;
1994 goto finish;
1995 }
322345fd 1996
faa133f3
LP
1997 for (i = 0; i < n; i++) {
1998 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
322345fd 1999
faa133f3
LP
2000 r = dns_packet_read_rr(p, &rr, NULL);
2001 if (r < 0)
2002 goto finish;
322345fd 2003
d75acfb0 2004 if (rr->key->type == DNS_TYPE_OPT) {
e6b57b37
LP
2005
2006 /* The OPT RR is only valid in the Additional section */
2007 if (i < DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)) {
2008 r = -EBADMSG;
2009 goto finish;
2010 }
2011
2012 /* Two OPT RRs? */
2013 if (p->opt) {
2014 r = -EBADMSG;
2015 goto finish;
2016 }
d75acfb0
LP
2017
2018 p->opt = dns_resource_record_ref(rr);
2019 } else {
2020 r = dns_answer_add(answer, rr, p->ifindex);
2021 if (r < 0)
2022 goto finish;
2023 }
faa133f3 2024 }
322345fd
LP
2025 }
2026
faa133f3
LP
2027 p->question = question;
2028 question = NULL;
322345fd 2029
faa133f3
LP
2030 p->answer = answer;
2031 answer = NULL;
322345fd 2032
a4076574
LP
2033 p->extracted = true;
2034
faa133f3 2035 r = 0;
322345fd
LP
2036
2037finish:
2038 p->rindex = saved_rindex;
2039 return r;
2040}
2041
8af5b883
LP
2042int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
2043 int r;
2044
2045 assert(p);
2046 assert(key);
2047
2048 /* Checks if the specified packet is a reply for the specified
2049 * key and the specified key is the only one in the question
2050 * section. */
2051
2052 if (DNS_PACKET_QR(p) != 1)
2053 return 0;
2054
2055 /* Let's unpack the packet, if that hasn't happened yet. */
2056 r = dns_packet_extract(p);
2057 if (r < 0)
2058 return r;
2059
2060 if (p->question->n_keys != 1)
2061 return 0;
2062
2063 return dns_resource_key_equal(p->question->keys[0], key);
2064}
2065
74b2466e
LP
2066static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
2067 [DNS_RCODE_SUCCESS] = "SUCCESS",
2068 [DNS_RCODE_FORMERR] = "FORMERR",
2069 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
2070 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
2071 [DNS_RCODE_NOTIMP] = "NOTIMP",
2072 [DNS_RCODE_REFUSED] = "REFUSED",
2073 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
2074 [DNS_RCODE_YXRRSET] = "YRRSET",
2075 [DNS_RCODE_NXRRSET] = "NXRRSET",
2076 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
2077 [DNS_RCODE_NOTZONE] = "NOTZONE",
2078 [DNS_RCODE_BADVERS] = "BADVERS",
2079 [DNS_RCODE_BADKEY] = "BADKEY",
2080 [DNS_RCODE_BADTIME] = "BADTIME",
2081 [DNS_RCODE_BADMODE] = "BADMODE",
2082 [DNS_RCODE_BADNAME] = "BADNAME",
2083 [DNS_RCODE_BADALG] = "BADALG",
2084 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
2085};
2086DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc
LP
2087
2088static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
2089 [DNS_PROTOCOL_DNS] = "dns",
2090 [DNS_PROTOCOL_MDNS] = "mdns",
2091 [DNS_PROTOCOL_LLMNR] = "llmnr",
2092};
2093DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);