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