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