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