]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
resolved: rework OPT RR generation logic
[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
1583 r = dns_packet_read_uint16(p, &rdlength, NULL);
1584 if (r < 0)
1585 goto fail;
1586
1587 if (p->rindex + rdlength > p->size) {
1588 r = -EBADMSG;
1589 goto fail;
1590 }
1591
1592 offset = p->rindex;
1593
faa133f3 1594 switch (rr->key->type) {
74b2466e 1595
9c92ce6d
LP
1596 case DNS_TYPE_SRV:
1597 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1598 if (r < 0)
1599 goto fail;
1600 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1601 if (r < 0)
1602 goto fail;
1603 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1604 if (r < 0)
1605 goto fail;
151226ab 1606 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
9c92ce6d
LP
1607 break;
1608
74b2466e
LP
1609 case DNS_TYPE_PTR:
1610 case DNS_TYPE_NS:
1611 case DNS_TYPE_CNAME:
8ac4e9e1 1612 case DNS_TYPE_DNAME:
151226ab 1613 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1614 break;
1615
1616 case DNS_TYPE_HINFO:
1617 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1618 if (r < 0)
1619 goto fail;
1620
1621 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1622 break;
1623
9de3e329 1624 case DNS_TYPE_SPF: /* exactly the same as TXT */
1ccda9b7
LP
1625 case DNS_TYPE_TXT:
1626 if (rdlength <= 0) {
2001c805 1627 DnsTxtItem *i;
1ccda9b7
LP
1628 /* RFC 6763, section 6.1 suggests to treat
1629 * empty TXT RRs as equivalent to a TXT record
1630 * with a single empty string. */
0e3434ae 1631
2001c805
LP
1632 i = malloc0(offsetof(DnsTxtItem, data) + 1); /* for safety reasons we add an extra NUL byte */
1633 if (!i)
1634 return -ENOMEM;
1635
1636 rr->txt.items = i;
1ccda9b7 1637 } else {
2001c805
LP
1638 DnsTxtItem *last = NULL;
1639
1ccda9b7 1640 while (p->rindex < offset + rdlength) {
2001c805
LP
1641 DnsTxtItem *i;
1642 const void *data;
1643 size_t sz;
2e276efc 1644
2001c805 1645 r = dns_packet_read_raw_string(p, &data, &sz, NULL);
1ccda9b7 1646 if (r < 0)
2001c805 1647 return r;
1ccda9b7 1648
2001c805
LP
1649 i = malloc0(offsetof(DnsTxtItem, data) + sz + 1); /* extra NUL byte at the end */
1650 if (!i)
1651 return -ENOMEM;
1652
1653 memcpy(i->data, data, sz);
1654 i->length = sz;
1655
1656 LIST_INSERT_AFTER(items, rr->txt.items, last, i);
1657 last = i;
1ccda9b7 1658 }
6a6fc3df
LP
1659 }
1660
1661 r = 0;
2e276efc 1662 break;
2e276efc 1663
74b2466e 1664 case DNS_TYPE_A:
623a4c97 1665 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1666 break;
1667
1668 case DNS_TYPE_AAAA:
623a4c97 1669 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1670 break;
1671
7e8e0422 1672 case DNS_TYPE_SOA:
151226ab 1673 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422
LP
1674 if (r < 0)
1675 goto fail;
1676
151226ab 1677 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422
LP
1678 if (r < 0)
1679 goto fail;
1680
1681 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1682 if (r < 0)
1683 goto fail;
1684
1685 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1686 if (r < 0)
1687 goto fail;
1688
1689 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1690 if (r < 0)
1691 goto fail;
1692
1693 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1694 if (r < 0)
1695 goto fail;
1696
1697 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1698 break;
1699
623a4c97 1700 case DNS_TYPE_MX:
946c7094
ZJS
1701 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1702 if (r < 0)
1703 goto fail;
1704
151226ab 1705 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
1706 break;
1707
0dae31d4
ZJS
1708 case DNS_TYPE_LOC: {
1709 uint8_t t;
1710 size_t pos;
1711
1712 r = dns_packet_read_uint8(p, &t, &pos);
1713 if (r < 0)
1714 goto fail;
1715
1716 if (t == 0) {
1717 rr->loc.version = t;
1718
1719 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1720 if (r < 0)
1721 goto fail;
1722
afbc4f26
ZJS
1723 if (!loc_size_ok(rr->loc.size)) {
1724 r = -EBADMSG;
1725 goto fail;
1726 }
1727
0dae31d4
ZJS
1728 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1729 if (r < 0)
1730 goto fail;
1731
afbc4f26
ZJS
1732 if (!loc_size_ok(rr->loc.horiz_pre)) {
1733 r = -EBADMSG;
1734 goto fail;
1735 }
1736
0dae31d4
ZJS
1737 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1738 if (r < 0)
1739 goto fail;
1740
afbc4f26
ZJS
1741 if (!loc_size_ok(rr->loc.vert_pre)) {
1742 r = -EBADMSG;
1743 goto fail;
1744 }
1745
0dae31d4
ZJS
1746 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1747 if (r < 0)
1748 goto fail;
1749
1750 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1751 if (r < 0)
1752 goto fail;
1753
1754 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1755 if (r < 0)
1756 goto fail;
1757
1758 break;
1759 } else {
1760 dns_packet_rewind(p, pos);
1761 rr->unparseable = true;
afbc4f26 1762 goto unparseable;
0dae31d4
ZJS
1763 }
1764 }
1765
abf126a3
TG
1766 case DNS_TYPE_DS:
1767 r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
1768 if (r < 0)
1769 goto fail;
1770
1771 r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
1772 if (r < 0)
1773 goto fail;
1774
1775 r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
1776 if (r < 0)
1777 goto fail;
1778
f5430a3e
LP
1779 r = dns_packet_read_memdup(p, rdlength - 4,
1780 &rr->ds.digest, &rr->ds.digest_size,
1781 NULL);
abf126a3
TG
1782 if (r < 0)
1783 goto fail;
1784
f1d178cc
TG
1785 if (rr->ds.digest_size <= 0) {
1786 /* the accepted size depends on the algorithm, but for now
1787 just ensure that the value is greater than zero */
1788 r = -EBADMSG;
1789 goto fail;
1790 }
1791
abf126a3 1792 break;
d75acfb0 1793
623a4c97 1794 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1795 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1796 if (r < 0)
1797 goto fail;
1798
1799 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1800 if (r < 0)
1801 goto fail;
1802
f5430a3e 1803 r = dns_packet_read_memdup(p, rdlength - 2,
549c1a25 1804 &rr->sshfp.fingerprint, &rr->sshfp.fingerprint_size,
f5430a3e 1805 NULL);
f1d178cc 1806
549c1a25 1807 if (rr->sshfp.fingerprint_size <= 0) {
f1d178cc
TG
1808 /* the accepted size depends on the algorithm, but for now
1809 just ensure that the value is greater than zero */
1810 r = -EBADMSG;
1811 goto fail;
1812 }
1813
8db0d2f5
ZJS
1814 break;
1815
f91dc240
LP
1816 case DNS_TYPE_DNSKEY:
1817 r = dns_packet_read_uint16(p, &rr->dnskey.flags, NULL);
8db0d2f5
ZJS
1818 if (r < 0)
1819 goto fail;
1820
f91dc240 1821 r = dns_packet_read_uint8(p, &rr->dnskey.protocol, NULL);
8db0d2f5
ZJS
1822 if (r < 0)
1823 goto fail;
1824
8db0d2f5
ZJS
1825 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1826 if (r < 0)
1827 goto fail;
1828
f5430a3e
LP
1829 r = dns_packet_read_memdup(p, rdlength - 4,
1830 &rr->dnskey.key, &rr->dnskey.key_size,
1831 NULL);
f1d178cc
TG
1832
1833 if (rr->dnskey.key_size <= 0) {
1834 /* the accepted size depends on the algorithm, but for now
1835 just ensure that the value is greater than zero */
1836 r = -EBADMSG;
1837 goto fail;
1838 }
1839
42cc2eeb
LP
1840 break;
1841
151226ab
ZJS
1842 case DNS_TYPE_RRSIG:
1843 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
1844 if (r < 0)
1845 goto fail;
1846
1847 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
1848 if (r < 0)
1849 goto fail;
1850
1851 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
1852 if (r < 0)
1853 goto fail;
1854
1855 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
1856 if (r < 0)
1857 goto fail;
1858
1859 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
1860 if (r < 0)
1861 goto fail;
1862
1863 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
1864 if (r < 0)
1865 goto fail;
1866
1867 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
1868 if (r < 0)
1869 goto fail;
1870
1871 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
1872 if (r < 0)
1873 goto fail;
1874
f5430a3e
LP
1875 r = dns_packet_read_memdup(p, offset + rdlength - p->rindex,
1876 &rr->rrsig.signature, &rr->rrsig.signature_size,
1877 NULL);
f1d178cc
TG
1878
1879 if (rr->rrsig.signature_size <= 0) {
1880 /* the accepted size depends on the algorithm, but for now
1881 just ensure that the value is greater than zero */
1882 r = -EBADMSG;
1883 goto fail;
1884 }
1885
151226ab
ZJS
1886 break;
1887
d84e543d
DM
1888 case DNS_TYPE_NSEC: {
1889
1890 /*
e5abebab 1891 * RFC6762, section 18.14 explictly states mDNS should use name compression.
d84e543d
DM
1892 * This contradicts RFC3845, section 2.1.1
1893 */
1894
1895 bool allow_compressed = p->protocol == DNS_PROTOCOL_MDNS;
1896
1897 r = dns_packet_read_name(p, &rr->nsec.next_domain_name, allow_compressed, NULL);
50f1e641
TG
1898 if (r < 0)
1899 goto fail;
1900
89492aaf
TG
1901 r = dns_packet_read_type_windows(p, &rr->nsec.types, offset + rdlength - p->rindex, NULL);
1902 if (r < 0)
1903 goto fail;
1904
09eaf68c
TG
1905 /* We accept empty NSEC bitmaps. The bit indicating the presence of the NSEC record itself
1906 * is redundant and in e.g., RFC4956 this fact is used to define a use for NSEC records
1907 * without the NSEC bit set. */
50f1e641
TG
1908
1909 break;
d84e543d 1910 }
5d45a880
TG
1911 case DNS_TYPE_NSEC3: {
1912 uint8_t size;
1913
1914 r = dns_packet_read_uint8(p, &rr->nsec3.algorithm, NULL);
1915 if (r < 0)
1916 goto fail;
1917
1918 r = dns_packet_read_uint8(p, &rr->nsec3.flags, NULL);
1919 if (r < 0)
1920 goto fail;
1921
1922 r = dns_packet_read_uint16(p, &rr->nsec3.iterations, NULL);
1923 if (r < 0)
1924 goto fail;
1925
f1d178cc 1926 /* this may be zero */
5d45a880
TG
1927 r = dns_packet_read_uint8(p, &size, NULL);
1928 if (r < 0)
1929 goto fail;
1930
f5430a3e 1931 r = dns_packet_read_memdup(p, size, &rr->nsec3.salt, &rr->nsec3.salt_size, NULL);
5d45a880
TG
1932 if (r < 0)
1933 goto fail;
1934
5d45a880
TG
1935 r = dns_packet_read_uint8(p, &size, NULL);
1936 if (r < 0)
1937 goto fail;
1938
f1d178cc
TG
1939 if (size <= 0) {
1940 r = -EBADMSG;
1941 goto fail;
1942 }
1943
f5430a3e 1944 r = dns_packet_read_memdup(p, size, &rr->nsec3.next_hashed_name, &rr->nsec3.next_hashed_name_size, NULL);
5d45a880
TG
1945 if (r < 0)
1946 goto fail;
1947
6b9308d1 1948 r = dns_packet_read_type_windows(p, &rr->nsec3.types, offset + rdlength - p->rindex, NULL);
5d45a880
TG
1949 if (r < 0)
1950 goto fail;
1951
0bbd72b2
TG
1952 /* empty non-terminals can have NSEC3 records, so empty bitmaps are allowed */
1953
5d45a880
TG
1954 break;
1955 }
d75acfb0
LP
1956
1957 case DNS_TYPE_OPT: /* we only care about the header of OPT for now. */
74b2466e 1958 default:
afbc4f26 1959 unparseable:
f5430a3e 1960 r = dns_packet_read_memdup(p, rdlength, &rr->generic.data, &rr->generic.size, NULL);
74b2466e
LP
1961 if (r < 0)
1962 goto fail;
74b2466e
LP
1963 break;
1964 }
1965 if (r < 0)
1966 goto fail;
1967 if (p->rindex != offset + rdlength) {
1968 r = -EBADMSG;
1969 goto fail;
1970 }
1971
1972 *ret = rr;
1973 rr = NULL;
1974
d2579eec
LP
1975 if (ret_cache_flush)
1976 *ret_cache_flush = cache_flush;
74b2466e
LP
1977 if (start)
1978 *start = saved_rindex;
1979
1980 return 0;
1981fail:
1982 dns_packet_rewind(p, saved_rindex);
1983 return r;
1984}
1985
faa133f3
LP
1986int dns_packet_extract(DnsPacket *p) {
1987 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1988 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1989 size_t saved_rindex;
1990 unsigned n, i;
74b2466e
LP
1991 int r;
1992
a4076574
LP
1993 if (p->extracted)
1994 return 0;
1995
faa133f3 1996 saved_rindex = p->rindex;
322345fd
LP
1997 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1998
3cb10d3a 1999 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
2000 if (n > 0) {
2001 question = dns_question_new(n);
2002 if (!question) {
2003 r = -ENOMEM;
2004 goto finish;
2005 }
74b2466e 2006
faa133f3
LP
2007 for (i = 0; i < n; i++) {
2008 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
d2579eec 2009 bool cache_flush;
74b2466e 2010
d2579eec 2011 r = dns_packet_read_key(p, &key, &cache_flush, NULL);
faa133f3
LP
2012 if (r < 0)
2013 goto finish;
74b2466e 2014
d2579eec
LP
2015 if (cache_flush) {
2016 r = -EBADMSG;
2017 goto finish;
2018 }
2019
c463eb78
LP
2020 if (!dns_type_is_valid_query(key->type)) {
2021 r = -EBADMSG;
2022 goto finish;
2023 }
2024
faa133f3
LP
2025 r = dns_question_add(question, key);
2026 if (r < 0)
2027 goto finish;
2028 }
2029 }
322345fd 2030
faa133f3
LP
2031 n = DNS_PACKET_RRCOUNT(p);
2032 if (n > 0) {
2033 answer = dns_answer_new(n);
2034 if (!answer) {
2035 r = -ENOMEM;
2036 goto finish;
2037 }
322345fd 2038
faa133f3
LP
2039 for (i = 0; i < n; i++) {
2040 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
ff7febd5 2041 bool cache_flush;
322345fd 2042
ff7febd5 2043 r = dns_packet_read_rr(p, &rr, &cache_flush, NULL);
faa133f3
LP
2044 if (r < 0)
2045 goto finish;
322345fd 2046
d75acfb0 2047 if (rr->key->type == DNS_TYPE_OPT) {
e6b57b37 2048
ff7febd5
LP
2049 if (!dns_name_is_root(DNS_RESOURCE_KEY_NAME(rr->key))) {
2050 r = -EBADMSG;
2051 goto finish;
2052 }
2053
e6b57b37
LP
2054 /* The OPT RR is only valid in the Additional section */
2055 if (i < DNS_PACKET_ANCOUNT(p) + DNS_PACKET_NSCOUNT(p)) {
2056 r = -EBADMSG;
2057 goto finish;
2058 }
2059
2060 /* Two OPT RRs? */
2061 if (p->opt) {
2062 r = -EBADMSG;
2063 goto finish;
2064 }
d75acfb0
LP
2065
2066 p->opt = dns_resource_record_ref(rr);
2067 } else {
105e1512
LP
2068
2069 /* According to RFC 4795, section
2070 * 2.9. only the RRs from the Answer
2071 * section shall be cached. Hence mark
2072 * only those RRs as cacheable by
2073 * default, but not the ones from the
2074 * Additional or Authority
2075 * sections. */
2076
2077 r = dns_answer_add(answer, rr, p->ifindex,
d2579eec
LP
2078 (i < DNS_PACKET_ANCOUNT(p) ? DNS_ANSWER_CACHEABLE : 0) |
2079 (p->protocol == DNS_PROTOCOL_MDNS && !cache_flush ? DNS_ANSWER_SHARED_OWNER : 0));
d75acfb0
LP
2080 if (r < 0)
2081 goto finish;
2082 }
faa133f3 2083 }
322345fd
LP
2084 }
2085
faa133f3
LP
2086 p->question = question;
2087 question = NULL;
322345fd 2088
faa133f3
LP
2089 p->answer = answer;
2090 answer = NULL;
322345fd 2091
a4076574
LP
2092 p->extracted = true;
2093
faa133f3 2094 r = 0;
322345fd
LP
2095
2096finish:
2097 p->rindex = saved_rindex;
2098 return r;
2099}
2100
8af5b883
LP
2101int dns_packet_is_reply_for(DnsPacket *p, const DnsResourceKey *key) {
2102 int r;
2103
2104 assert(p);
2105 assert(key);
2106
2107 /* Checks if the specified packet is a reply for the specified
2108 * key and the specified key is the only one in the question
2109 * section. */
2110
2111 if (DNS_PACKET_QR(p) != 1)
2112 return 0;
2113
2114 /* Let's unpack the packet, if that hasn't happened yet. */
2115 r = dns_packet_extract(p);
2116 if (r < 0)
2117 return r;
2118
2119 if (p->question->n_keys != 1)
2120 return 0;
2121
2122 return dns_resource_key_equal(p->question->keys[0], key);
2123}
2124
74b2466e
LP
2125static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
2126 [DNS_RCODE_SUCCESS] = "SUCCESS",
2127 [DNS_RCODE_FORMERR] = "FORMERR",
2128 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
2129 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
2130 [DNS_RCODE_NOTIMP] = "NOTIMP",
2131 [DNS_RCODE_REFUSED] = "REFUSED",
2132 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
2133 [DNS_RCODE_YXRRSET] = "YRRSET",
2134 [DNS_RCODE_NXRRSET] = "NXRRSET",
2135 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
2136 [DNS_RCODE_NOTZONE] = "NOTZONE",
2137 [DNS_RCODE_BADVERS] = "BADVERS",
2138 [DNS_RCODE_BADKEY] = "BADKEY",
2139 [DNS_RCODE_BADTIME] = "BADTIME",
2140 [DNS_RCODE_BADMODE] = "BADMODE",
2141 [DNS_RCODE_BADNAME] = "BADNAME",
2142 [DNS_RCODE_BADALG] = "BADALG",
2143 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
2144};
2145DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc
LP
2146
2147static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
2148 [DNS_PROTOCOL_DNS] = "dns",
2149 [DNS_PROTOCOL_MDNS] = "mdns",
2150 [DNS_PROTOCOL_LLMNR] = "llmnr",
2151};
2152DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);