]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
basic: add a Bitmap implementation
[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
22#include "utf8.h"
c73ce96b 23#include "util.h"
2e276efc 24#include "strv.h"
725ca0e5 25#include "unaligned.h"
4ad7f276 26#include "dns-domain.h"
74b2466e
LP
27#include "resolved-dns-packet.h"
28
1716f6dc 29int dns_packet_new(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
74b2466e
LP
30 DnsPacket *p;
31 size_t a;
32
33 assert(ret);
34
a0166609 35 if (mtu <= UDP_PACKET_HEADER_SIZE)
74b2466e
LP
36 a = DNS_PACKET_SIZE_START;
37 else
a0166609 38 a = mtu - UDP_PACKET_HEADER_SIZE;
74b2466e
LP
39
40 if (a < DNS_PACKET_HEADER_SIZE)
41 a = DNS_PACKET_HEADER_SIZE;
42
c73ce96b
LP
43 /* round up to next page size */
44 a = PAGE_ALIGN(ALIGN(sizeof(DnsPacket)) + a) - ALIGN(sizeof(DnsPacket));
45
46 /* make sure we never allocate more than useful */
47 if (a > DNS_PACKET_SIZE_MAX)
48 a = DNS_PACKET_SIZE_MAX;
49
74b2466e
LP
50 p = malloc0(ALIGN(sizeof(DnsPacket)) + a);
51 if (!p)
52 return -ENOMEM;
53
54 p->size = p->rindex = DNS_PACKET_HEADER_SIZE;
55 p->allocated = a;
1716f6dc 56 p->protocol = protocol;
74b2466e
LP
57 p->n_ref = 1;
58
59 *ret = p;
60
61 return 0;
62}
63
1716f6dc 64int dns_packet_new_query(DnsPacket **ret, DnsProtocol protocol, size_t mtu) {
74b2466e
LP
65 DnsPacket *p;
66 DnsPacketHeader *h;
67 int r;
68
69 assert(ret);
70
1716f6dc 71 r = dns_packet_new(&p, protocol, mtu);
74b2466e
LP
72 if (r < 0)
73 return r;
74
75 h = DNS_PACKET_HEADER(p);
1716f6dc 76
ea917db9
LP
77 if (protocol == DNS_PROTOCOL_LLMNR)
78 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
79 0 /* opcode */,
80 0 /* c */,
81 0 /* tc */,
82 0 /* t */,
83 0 /* ra */,
84 0 /* ad */,
85 0 /* cd */,
86 0 /* rcode */));
1716f6dc 87 else
ea917db9
LP
88 h->flags = htobe16(DNS_PACKET_MAKE_FLAGS(0 /* qr */,
89 0 /* opcode */,
90 0 /* aa */,
91 0 /* tc */,
92 1 /* rd (ask for recursion) */,
93 0 /* ra */,
94 0 /* ad */,
95 0 /* cd */,
96 0 /* rcode */));
74b2466e
LP
97
98 *ret = p;
99 return 0;
100}
101
102DnsPacket *dns_packet_ref(DnsPacket *p) {
103
104 if (!p)
105 return NULL;
106
107 assert(p->n_ref > 0);
108 p->n_ref++;
109 return p;
110}
111
112static void dns_packet_free(DnsPacket *p) {
113 char *s;
114
115 assert(p);
116
faa133f3
LP
117 dns_question_unref(p->question);
118 dns_answer_unref(p->answer);
322345fd 119
74b2466e
LP
120 while ((s = hashmap_steal_first_key(p->names)))
121 free(s);
122 hashmap_free(p->names);
123
faa133f3 124 free(p->_data);
74b2466e
LP
125 free(p);
126}
127
128DnsPacket *dns_packet_unref(DnsPacket *p) {
129 if (!p)
130 return NULL;
131
132 assert(p->n_ref > 0);
133
134 if (p->n_ref == 1)
135 dns_packet_free(p);
136 else
137 p->n_ref--;
138
139 return NULL;
140}
141
142int dns_packet_validate(DnsPacket *p) {
143 assert(p);
144
145 if (p->size < DNS_PACKET_HEADER_SIZE)
146 return -EBADMSG;
147
c73ce96b
LP
148 if (p->size > DNS_PACKET_SIZE_MAX)
149 return -EBADMSG;
150
623a4c97 151 return 1;
74b2466e
LP
152}
153
154int dns_packet_validate_reply(DnsPacket *p) {
74b2466e
LP
155 int r;
156
157 assert(p);
158
159 r = dns_packet_validate(p);
160 if (r < 0)
161 return r;
162
623a4c97
LP
163 if (DNS_PACKET_QR(p) != 1)
164 return 0;
165
166 if (DNS_PACKET_OPCODE(p) != 0)
74b2466e
LP
167 return -EBADMSG;
168
818ef443
DM
169 switch (p->protocol) {
170 case DNS_PROTOCOL_LLMNR:
171 /* RFC 4795, Section 2.1.1. says to discard all replies with QDCOUNT != 1 */
172 if (DNS_PACKET_QDCOUNT(p) != 1)
173 return -EBADMSG;
174
175 break;
176
177 default:
178 break;
179 }
ea917db9 180
623a4c97
LP
181 return 1;
182}
183
184int dns_packet_validate_query(DnsPacket *p) {
185 int r;
186
187 assert(p);
188
189 r = dns_packet_validate(p);
190 if (r < 0)
191 return r;
192
193 if (DNS_PACKET_QR(p) != 0)
194 return 0;
195
3cb10d3a 196 if (DNS_PACKET_OPCODE(p) != 0)
74b2466e
LP
197 return -EBADMSG;
198
623a4c97
LP
199 if (DNS_PACKET_TC(p))
200 return -EBADMSG;
201
818ef443
DM
202 switch (p->protocol) {
203 case DNS_PROTOCOL_LLMNR:
204 /* RFC 4795, Section 2.1.1. says to discard all queries with QDCOUNT != 1 */
205 if (DNS_PACKET_QDCOUNT(p) != 1)
206 return -EBADMSG;
623a4c97 207
818ef443
DM
208 /* RFC 4795, Section 2.1.1. says to discard all queries with ANCOUNT != 0 */
209 if (DNS_PACKET_ANCOUNT(p) > 0)
210 return -EBADMSG;
623a4c97 211
818ef443
DM
212 /* RFC 4795, Section 2.1.1. says to discard all queries with NSCOUNT != 0 */
213 if (DNS_PACKET_NSCOUNT(p) > 0)
214 return -EBADMSG;
215
216 break;
217
218 default:
219 break;
220 }
623a4c97
LP
221
222 return 1;
74b2466e
LP
223}
224
225static int dns_packet_extend(DnsPacket *p, size_t add, void **ret, size_t *start) {
226 assert(p);
227
c73ce96b
LP
228 if (p->size + add > p->allocated) {
229 size_t a;
230
231 a = PAGE_ALIGN((p->size + add) * 2);
232 if (a > DNS_PACKET_SIZE_MAX)
233 a = DNS_PACKET_SIZE_MAX;
234
235 if (p->size + add > a)
236 return -EMSGSIZE;
237
faa133f3 238 if (p->_data) {
c73ce96b
LP
239 void *d;
240
faa133f3 241 d = realloc(p->_data, a);
c73ce96b
LP
242 if (!d)
243 return -ENOMEM;
244
faa133f3 245 p->_data = d;
c73ce96b 246 } else {
faa133f3
LP
247 p->_data = malloc(a);
248 if (!p->_data)
c73ce96b
LP
249 return -ENOMEM;
250
faa133f3
LP
251 memcpy(p->_data, (uint8_t*) p + ALIGN(sizeof(DnsPacket)), p->size);
252 memzero((uint8_t*) p->_data + p->size, a - p->size);
c73ce96b
LP
253 }
254
255 p->allocated = a;
256 }
74b2466e
LP
257
258 if (start)
259 *start = p->size;
260
261 if (ret)
262 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->size;
263
264 p->size += add;
265 return 0;
266}
267
268static void dns_packet_truncate(DnsPacket *p, size_t sz) {
269 Iterator i;
270 char *s;
271 void *n;
272
273 assert(p);
274
275 if (p->size <= sz)
276 return;
277
278 HASHMAP_FOREACH_KEY(s, n, p->names, i) {
279
280 if (PTR_TO_SIZE(n) < sz)
281 continue;
282
283 hashmap_remove(p->names, s);
284 free(s);
285 }
286
287 p->size = sz;
288}
289
623a4c97
LP
290int dns_packet_append_blob(DnsPacket *p, const void *d, size_t l, size_t *start) {
291 void *q;
292 int r;
293
294 assert(p);
295
296 r = dns_packet_extend(p, l, &q, start);
297 if (r < 0)
298 return r;
299
300 memcpy(q, d, l);
301 return 0;
302}
303
74b2466e
LP
304int dns_packet_append_uint8(DnsPacket *p, uint8_t v, size_t *start) {
305 void *d;
306 int r;
307
308 assert(p);
309
310 r = dns_packet_extend(p, sizeof(uint8_t), &d, start);
311 if (r < 0)
312 return r;
313
314 ((uint8_t*) d)[0] = v;
315
316 return 0;
317}
318
319int dns_packet_append_uint16(DnsPacket *p, uint16_t v, size_t *start) {
320 void *d;
321 int r;
322
323 assert(p);
324
325 r = dns_packet_extend(p, sizeof(uint16_t), &d, start);
326 if (r < 0)
327 return r;
328
725ca0e5 329 unaligned_write_be16(d, v);
623a4c97
LP
330
331 return 0;
332}
333
334int dns_packet_append_uint32(DnsPacket *p, uint32_t v, size_t *start) {
335 void *d;
336 int r;
337
338 assert(p);
339
340 r = dns_packet_extend(p, sizeof(uint32_t), &d, start);
341 if (r < 0)
342 return r;
343
725ca0e5 344 unaligned_write_be32(d, v);
74b2466e
LP
345
346 return 0;
347}
348
349int dns_packet_append_string(DnsPacket *p, const char *s, size_t *start) {
350 void *d;
351 size_t l;
352 int r;
353
354 assert(p);
355 assert(s);
356
357 l = strlen(s);
358 if (l > 255)
359 return -E2BIG;
360
361 r = dns_packet_extend(p, 1 + l, &d, start);
362 if (r < 0)
363 return r;
364
365 ((uint8_t*) d)[0] = (uint8_t) l;
366 memcpy(((uint8_t*) d) + 1, s, l);
367
368 return 0;
369}
370
371int dns_packet_append_label(DnsPacket *p, const char *d, size_t l, size_t *start) {
372 void *w;
373 int r;
374
375 assert(p);
376 assert(d);
377
378 if (l > DNS_LABEL_MAX)
379 return -E2BIG;
380
381 r = dns_packet_extend(p, 1 + l, &w, start);
382 if (r < 0)
383 return r;
384
385 ((uint8_t*) w)[0] = (uint8_t) l;
386 memcpy(((uint8_t*) w) + 1, d, l);
387
388 return 0;
389}
390
151226ab
ZJS
391int dns_packet_append_name(DnsPacket *p, const char *name,
392 bool allow_compression, size_t *start) {
74b2466e
LP
393 size_t saved_size;
394 int r;
395
396 assert(p);
397 assert(name);
398
399 saved_size = p->size;
400
401 while (*name) {
402 _cleanup_free_ char *s = NULL;
403 char label[DNS_LABEL_MAX];
151226ab 404 size_t n = 0;
bdf10b5b 405 int k;
74b2466e 406
151226ab
ZJS
407 if (allow_compression)
408 n = PTR_TO_SIZE(hashmap_get(p->names, name));
74b2466e
LP
409 if (n > 0) {
410 assert(n < p->size);
411
412 if (n < 0x4000) {
413 r = dns_packet_append_uint16(p, 0xC000 | n, NULL);
414 if (r < 0)
415 goto fail;
416
417 goto done;
418 }
419 }
420
421 s = strdup(name);
422 if (!s) {
423 r = -ENOMEM;
424 goto fail;
425 }
426
427 r = dns_label_unescape(&name, label, sizeof(label));
428 if (r < 0)
429 goto fail;
430
bdf10b5b
LP
431 if (p->protocol == DNS_PROTOCOL_DNS)
432 k = dns_label_apply_idna(label, r, label, sizeof(label));
433 else
434 k = dns_label_undo_idna(label, r, label, sizeof(label));
435 if (k < 0) {
436 r = k;
437 goto fail;
438 }
439 if (k > 0)
440 r = k;
441
74b2466e
LP
442 r = dns_packet_append_label(p, label, r, &n);
443 if (r < 0)
444 goto fail;
445
151226ab 446 if (allow_compression) {
d5099efc 447 r = hashmap_ensure_allocated(&p->names, &dns_name_hash_ops);
151226ab
ZJS
448 if (r < 0)
449 goto fail;
74b2466e 450
151226ab
ZJS
451 r = hashmap_put(p->names, s, SIZE_TO_PTR(n));
452 if (r < 0)
453 goto fail;
74b2466e 454
151226ab
ZJS
455 s = NULL;
456 }
74b2466e
LP
457 }
458
459 r = dns_packet_append_uint8(p, 0, NULL);
460 if (r < 0)
461 return r;
462
463done:
464 if (start)
465 *start = saved_size;
466
467 return 0;
468
469fail:
470 dns_packet_truncate(p, saved_size);
471 return r;
472}
473
474int dns_packet_append_key(DnsPacket *p, const DnsResourceKey *k, size_t *start) {
475 size_t saved_size;
476 int r;
477
478 assert(p);
479 assert(k);
480
481 saved_size = p->size;
482
151226ab 483 r = dns_packet_append_name(p, DNS_RESOURCE_KEY_NAME(k), true, NULL);
74b2466e
LP
484 if (r < 0)
485 goto fail;
486
487 r = dns_packet_append_uint16(p, k->type, NULL);
488 if (r < 0)
489 goto fail;
490
491 r = dns_packet_append_uint16(p, k->class, NULL);
492 if (r < 0)
493 goto fail;
494
495 if (start)
496 *start = saved_size;
497
498 return 0;
499
500fail:
501 dns_packet_truncate(p, saved_size);
502 return r;
503}
504
623a4c97
LP
505int dns_packet_append_rr(DnsPacket *p, const DnsResourceRecord *rr, size_t *start) {
506 size_t saved_size, rdlength_offset, end, rdlength;
507 int r;
508
509 assert(p);
510 assert(rr);
511
512 saved_size = p->size;
513
514 r = dns_packet_append_key(p, rr->key, NULL);
515 if (r < 0)
516 goto fail;
517
518 r = dns_packet_append_uint32(p, rr->ttl, NULL);
519 if (r < 0)
520 goto fail;
521
522 /* Initially we write 0 here */
523 r = dns_packet_append_uint16(p, 0, &rdlength_offset);
524 if (r < 0)
525 goto fail;
526
0dae31d4 527 switch (rr->unparseable ? _DNS_TYPE_INVALID : rr->key->type) {
623a4c97 528
9c92ce6d
LP
529 case DNS_TYPE_SRV:
530 r = dns_packet_append_uint16(p, rr->srv.priority, NULL);
531 if (r < 0)
532 goto fail;
533
534 r = dns_packet_append_uint16(p, rr->srv.weight, NULL);
535 if (r < 0)
536 goto fail;
537
538 r = dns_packet_append_uint16(p, rr->srv.port, NULL);
539 if (r < 0)
540 goto fail;
541
151226ab 542 r = dns_packet_append_name(p, rr->srv.name, true, NULL);
9c92ce6d
LP
543 break;
544
623a4c97
LP
545 case DNS_TYPE_PTR:
546 case DNS_TYPE_NS:
547 case DNS_TYPE_CNAME:
8ac4e9e1 548 case DNS_TYPE_DNAME:
151226ab 549 r = dns_packet_append_name(p, rr->ptr.name, true, NULL);
623a4c97
LP
550 break;
551
552 case DNS_TYPE_HINFO:
553 r = dns_packet_append_string(p, rr->hinfo.cpu, NULL);
554 if (r < 0)
555 goto fail;
556
557 r = dns_packet_append_string(p, rr->hinfo.os, NULL);
558 break;
559
9de3e329 560 case DNS_TYPE_SPF: /* exactly the same as TXT */
2e276efc
ZJS
561 case DNS_TYPE_TXT: {
562 char **s;
563
1ccda9b7
LP
564 if (strv_isempty(rr->txt.strings)) {
565 /* RFC 6763, section 6.1 suggests to generate
566 * single empty string for an empty array. */
567
568 r = dns_packet_append_string(p, "", NULL);
2e276efc
ZJS
569 if (r < 0)
570 goto fail;
1ccda9b7
LP
571 } else {
572 STRV_FOREACH(s, rr->txt.strings) {
573 r = dns_packet_append_string(p, *s, NULL);
574 if (r < 0)
575 goto fail;
576 }
2e276efc
ZJS
577 }
578
6a6fc3df 579 r = 0;
2e276efc
ZJS
580 break;
581 }
582
623a4c97
LP
583 case DNS_TYPE_A:
584 r = dns_packet_append_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
585 break;
586
587 case DNS_TYPE_AAAA:
588 r = dns_packet_append_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
589 break;
590
591 case DNS_TYPE_SOA:
151226ab 592 r = dns_packet_append_name(p, rr->soa.mname, true, NULL);
623a4c97
LP
593 if (r < 0)
594 goto fail;
595
151226ab 596 r = dns_packet_append_name(p, rr->soa.rname, true, NULL);
623a4c97
LP
597 if (r < 0)
598 goto fail;
599
600 r = dns_packet_append_uint32(p, rr->soa.serial, NULL);
601 if (r < 0)
602 goto fail;
603
604 r = dns_packet_append_uint32(p, rr->soa.refresh, NULL);
605 if (r < 0)
606 goto fail;
607
608 r = dns_packet_append_uint32(p, rr->soa.retry, NULL);
609 if (r < 0)
610 goto fail;
611
612 r = dns_packet_append_uint32(p, rr->soa.expire, NULL);
613 if (r < 0)
614 goto fail;
615
616 r = dns_packet_append_uint32(p, rr->soa.minimum, NULL);
617 break;
618
619 case DNS_TYPE_MX:
946c7094
ZJS
620 r = dns_packet_append_uint16(p, rr->mx.priority, NULL);
621 if (r < 0)
622 goto fail;
623
151226ab 624 r = dns_packet_append_name(p, rr->mx.exchange, true, NULL);
946c7094
ZJS
625 break;
626
0dae31d4
ZJS
627 case DNS_TYPE_LOC:
628 r = dns_packet_append_uint8(p, rr->loc.version, NULL);
629 if (r < 0)
630 goto fail;
631
632 r = dns_packet_append_uint8(p, rr->loc.size, NULL);
633 if (r < 0)
634 goto fail;
635
636 r = dns_packet_append_uint8(p, rr->loc.horiz_pre, NULL);
637 if (r < 0)
638 goto fail;
639
640 r = dns_packet_append_uint8(p, rr->loc.vert_pre, NULL);
641 if (r < 0)
642 goto fail;
643
afbc4f26 644 r = dns_packet_append_uint32(p, rr->loc.latitude, NULL);
0dae31d4
ZJS
645 if (r < 0)
646 goto fail;
647
afbc4f26 648 r = dns_packet_append_uint32(p, rr->loc.longitude, NULL);
0dae31d4
ZJS
649 if (r < 0)
650 goto fail;
651
afbc4f26 652 r = dns_packet_append_uint32(p, rr->loc.altitude, NULL);
0dae31d4
ZJS
653 break;
654
abf126a3
TG
655 case DNS_TYPE_DS:
656 r = dns_packet_append_uint16(p, rr->ds.key_tag, NULL);
657 if (r < 0)
658 goto fail;
659
660 r = dns_packet_append_uint8(p, rr->ds.algorithm, NULL);
661 if (r < 0)
662 goto fail;
663
664 r = dns_packet_append_uint8(p, rr->ds.digest_type, NULL);
665 if (r < 0)
666 goto fail;
667
668 r = dns_packet_append_blob(p, rr->ds.digest, rr->ds.digest_size, NULL);
669 break;
670
623a4c97 671 case DNS_TYPE_SSHFP:
42cc2eeb
LP
672 r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
673 if (r < 0)
674 goto fail;
8db0d2f5 675
42cc2eeb
LP
676 r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
677 if (r < 0)
678 goto fail;
679
680 r = dns_packet_append_blob(p, rr->sshfp.key, rr->sshfp.key_size, NULL);
681 break;
682
8db0d2f5
ZJS
683 case DNS_TYPE_DNSKEY:
684 r = dns_packet_append_uint16(p, dnskey_to_flags(rr), NULL);
685 if (r < 0)
686 goto fail;
687
688 r = dns_packet_append_uint8(p, 3u, NULL);
689 if (r < 0)
690 goto fail;
691
692 r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
693 if (r < 0)
694 goto fail;
695
696 r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
697 break;
698
151226ab
ZJS
699 case DNS_TYPE_RRSIG:
700 r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
701 if (r < 0)
702 goto fail;
703
704 r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
705 if (r < 0)
706 goto fail;
707
708 r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
709 if (r < 0)
710 goto fail;
711
712 r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
713 if (r < 0)
714 goto fail;
715
716 r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
717 if (r < 0)
718 goto fail;
719
720 r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
721 if (r < 0)
722 goto fail;
723
0b1b17d3 724 r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL);
151226ab
ZJS
725 if (r < 0)
726 goto fail;
727
728 r = dns_packet_append_name(p, rr->rrsig.signer, false, NULL);
729 if (r < 0)
730 goto fail;
731
732 r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
733 break;
734
0dae31d4 735 case _DNS_TYPE_INVALID: /* unparseable */
623a4c97 736 default:
0dae31d4 737
623a4c97
LP
738 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
739 break;
740 }
741 if (r < 0)
742 goto fail;
743
744 /* Let's calculate the actual data size and update the field */
745 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
746 if (rdlength > 0xFFFF) {
747 r = ENOSPC;
748 goto fail;
749 }
750
751 end = p->size;
752 p->size = rdlength_offset;
753 r = dns_packet_append_uint16(p, rdlength, NULL);
754 if (r < 0)
755 goto fail;
756 p->size = end;
757
351e6342
LP
758 if (start)
759 *start = saved_size;
760
623a4c97
LP
761 return 0;
762
763fail:
764 dns_packet_truncate(p, saved_size);
765 return r;
766}
767
768
74b2466e
LP
769int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
770 assert(p);
771
772 if (p->rindex + sz > p->size)
773 return -EMSGSIZE;
774
775 if (ret)
776 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
777
778 if (start)
779 *start = p->rindex;
780
781 p->rindex += sz;
782 return 0;
783}
784
8ba9fd9c 785void dns_packet_rewind(DnsPacket *p, size_t idx) {
74b2466e
LP
786 assert(p);
787 assert(idx <= p->size);
788 assert(idx >= DNS_PACKET_HEADER_SIZE);
789
790 p->rindex = idx;
791}
792
623a4c97
LP
793int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
794 const void *q;
795 int r;
796
797 assert(p);
798 assert(d);
799
800 r = dns_packet_read(p, sz, &q, start);
801 if (r < 0)
802 return r;
803
804 memcpy(d, q, sz);
805 return 0;
806}
807
74b2466e
LP
808int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
809 const void *d;
810 int r;
811
812 assert(p);
813
814 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
815 if (r < 0)
816 return r;
817
818 *ret = ((uint8_t*) d)[0];
819 return 0;
820}
821
822int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
823 const void *d;
824 int r;
825
826 assert(p);
827
828 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
829 if (r < 0)
830 return r;
831
725ca0e5
TG
832 *ret = unaligned_read_be16(d);
833
74b2466e
LP
834 return 0;
835}
836
837int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
838 const void *d;
839 int r;
840
841 assert(p);
842
843 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
844 if (r < 0)
845 return r;
846
725ca0e5 847 *ret = unaligned_read_be32(d);
74b2466e
LP
848
849 return 0;
850}
851
852int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
853 size_t saved_rindex;
854 const void *d;
855 char *t;
856 uint8_t c;
857 int r;
858
859 assert(p);
860
861 saved_rindex = p->rindex;
862
863 r = dns_packet_read_uint8(p, &c, NULL);
864 if (r < 0)
865 goto fail;
866
867 r = dns_packet_read(p, c, &d, NULL);
868 if (r < 0)
869 goto fail;
870
871 if (memchr(d, 0, c)) {
872 r = -EBADMSG;
873 goto fail;
874 }
875
876 t = strndup(d, c);
877 if (!t) {
878 r = -ENOMEM;
879 goto fail;
880 }
881
882 if (!utf8_is_valid(t)) {
883 free(t);
884 r = -EBADMSG;
885 goto fail;
886 }
887
888 *ret = t;
889
890 if (start)
891 *start = saved_rindex;
892
893 return 0;
894
895fail:
896 dns_packet_rewind(p, saved_rindex);
897 return r;
898}
899
151226ab
ZJS
900int dns_packet_read_name(DnsPacket *p, char **_ret,
901 bool allow_compression, size_t *start) {
c75dbf9b 902 size_t saved_rindex, after_rindex = 0, jump_barrier;
74b2466e
LP
903 _cleanup_free_ char *ret = NULL;
904 size_t n = 0, allocated = 0;
905 bool first = true;
906 int r;
907
908 assert(p);
909 assert(_ret);
910
911 saved_rindex = p->rindex;
c75dbf9b 912 jump_barrier = p->rindex;
74b2466e
LP
913
914 for (;;) {
915 uint8_t c, d;
916
917 r = dns_packet_read_uint8(p, &c, NULL);
918 if (r < 0)
919 goto fail;
920
921 if (c == 0)
922 /* End of name */
923 break;
924 else if (c <= 63) {
925 _cleanup_free_ char *t = NULL;
926 const char *label;
927
928 /* Literal label */
929 r = dns_packet_read(p, c, (const void**) &label, NULL);
930 if (r < 0)
931 goto fail;
932
933 r = dns_label_escape(label, c, &t);
934 if (r < 0)
935 goto fail;
936
937 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
938 r = -ENOMEM;
939 goto fail;
940 }
941
942 if (!first)
943 ret[n++] = '.';
944 else
945 first = false;
946
85818582 947 memcpy(ret + n, t, r);
74b2466e
LP
948 n += r;
949 continue;
151226ab 950 } else if (allow_compression && (c & 0xc0) == 0xc0) {
74b2466e
LP
951 uint16_t ptr;
952
953 /* Pointer */
954 r = dns_packet_read_uint8(p, &d, NULL);
955 if (r < 0)
956 goto fail;
957
958 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
c75dbf9b 959 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
74b2466e
LP
960 r = -EBADMSG;
961 goto fail;
962 }
963
964 if (after_rindex == 0)
965 after_rindex = p->rindex;
966
f131770b 967 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
c75dbf9b 968 jump_barrier = ptr;
74b2466e 969 p->rindex = ptr;
59aa5821
SP
970 } else {
971 r = -EBADMSG;
74b2466e 972 goto fail;
59aa5821 973 }
74b2466e
LP
974 }
975
976 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
977 r = -ENOMEM;
978 goto fail;
979 }
980
981 ret[n] = 0;
982
983 if (after_rindex != 0)
984 p->rindex= after_rindex;
985
986 *_ret = ret;
987 ret = NULL;
988
989 if (start)
990 *start = saved_rindex;
991
992 return 0;
993
994fail:
995 dns_packet_rewind(p, saved_rindex);
996 return r;
997}
998
faa133f3
LP
999int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
1000 _cleanup_free_ char *name = NULL;
1001 uint16_t class, type;
1002 DnsResourceKey *key;
74b2466e
LP
1003 size_t saved_rindex;
1004 int r;
1005
1006 assert(p);
1007 assert(ret);
1008
1009 saved_rindex = p->rindex;
1010
151226ab 1011 r = dns_packet_read_name(p, &name, true, NULL);
74b2466e
LP
1012 if (r < 0)
1013 goto fail;
1014
faa133f3 1015 r = dns_packet_read_uint16(p, &type, NULL);
74b2466e
LP
1016 if (r < 0)
1017 goto fail;
1018
faa133f3 1019 r = dns_packet_read_uint16(p, &class, NULL);
74b2466e
LP
1020 if (r < 0)
1021 goto fail;
1022
faa133f3
LP
1023 key = dns_resource_key_new_consume(class, type, name);
1024 if (!key) {
1025 r = -ENOMEM;
1026 goto fail;
1027 }
1028
1029 name = NULL;
1030 *ret = key;
74b2466e
LP
1031
1032 if (start)
1033 *start = saved_rindex;
1034
1035 return 0;
1036fail:
1037 dns_packet_rewind(p, saved_rindex);
1038 return r;
1039}
1040
8db0d2f5
ZJS
1041static int dns_packet_read_public_key(DnsPacket *p, size_t length,
1042 void **dp, size_t *lengthp,
1043 size_t *start) {
1044 int r;
1045 const void *d;
1046 void *d2;
1047
1048 r = dns_packet_read(p, length, &d, NULL);
1049 if (r < 0)
1050 return r;
1051
1052 d2 = memdup(d, length);
1053 if (!d2)
1054 return -ENOMEM;
1055
1056 *dp = d2;
1057 *lengthp = length;
1058 return 0;
1059}
1060
afbc4f26
ZJS
1061static bool loc_size_ok(uint8_t size) {
1062 uint8_t m = size >> 4, e = size & 0xF;
1063
1064 return m <= 9 && e <= 9 && (m > 0 || e == 0);
1065}
1066
8db0d2f5 1067static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
3ef77d04
LP
1068 assert(rr);
1069
8db0d2f5
ZJS
1070 if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
1071 return -EBADMSG;
1072
1073 rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
1074 rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
1075 return 0;
1076}
1077
74b2466e 1078int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
faa133f3
LP
1079 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1080 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e
LP
1081 size_t saved_rindex, offset;
1082 uint16_t rdlength;
1083 const void *d;
1084 int r;
1085
1086 assert(p);
1087 assert(ret);
1088
4e0296a9 1089 saved_rindex = p->rindex;
74b2466e 1090
faa133f3 1091 r = dns_packet_read_key(p, &key, NULL);
74b2466e
LP
1092 if (r < 0)
1093 goto fail;
1094
0e2bcd6a
LP
1095 if (key->class == DNS_CLASS_ANY ||
1096 key->type == DNS_TYPE_ANY) {
1097 r = -EBADMSG;
1098 goto fail;
1099 }
1100
faa133f3
LP
1101 rr = dns_resource_record_new(key);
1102 if (!rr) {
1103 r = -ENOMEM;
1104 goto fail;
1105 }
1106
74b2466e
LP
1107 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1108 if (r < 0)
1109 goto fail;
1110
1111 r = dns_packet_read_uint16(p, &rdlength, NULL);
1112 if (r < 0)
1113 goto fail;
1114
1115 if (p->rindex + rdlength > p->size) {
1116 r = -EBADMSG;
1117 goto fail;
1118 }
1119
1120 offset = p->rindex;
1121
faa133f3 1122 switch (rr->key->type) {
74b2466e 1123
9c92ce6d
LP
1124 case DNS_TYPE_SRV:
1125 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1126 if (r < 0)
1127 goto fail;
1128 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1129 if (r < 0)
1130 goto fail;
1131 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1132 if (r < 0)
1133 goto fail;
151226ab 1134 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
9c92ce6d
LP
1135 break;
1136
74b2466e
LP
1137 case DNS_TYPE_PTR:
1138 case DNS_TYPE_NS:
1139 case DNS_TYPE_CNAME:
8ac4e9e1 1140 case DNS_TYPE_DNAME:
151226ab 1141 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1142 break;
1143
1144 case DNS_TYPE_HINFO:
1145 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1146 if (r < 0)
1147 goto fail;
1148
1149 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1150 break;
1151
9de3e329 1152 case DNS_TYPE_SPF: /* exactly the same as TXT */
1ccda9b7
LP
1153 case DNS_TYPE_TXT:
1154 if (rdlength <= 0) {
1155 /* RFC 6763, section 6.1 suggests to treat
1156 * empty TXT RRs as equivalent to a TXT record
1157 * with a single empty string. */
0e3434ae 1158
1ccda9b7 1159 r = strv_extend(&rr->txt.strings, "");
2e276efc
ZJS
1160 if (r < 0)
1161 goto fail;
1ccda9b7
LP
1162 } else {
1163 while (p->rindex < offset + rdlength) {
1164 char *s;
2e276efc 1165
1ccda9b7
LP
1166 r = dns_packet_read_string(p, &s, NULL);
1167 if (r < 0)
1168 goto fail;
1169
1170 r = strv_consume(&rr->txt.strings, s);
1171 if (r < 0)
1172 goto fail;
1173 }
6a6fc3df
LP
1174 }
1175
1176 r = 0;
2e276efc 1177 break;
2e276efc 1178
74b2466e 1179 case DNS_TYPE_A:
623a4c97 1180 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1181 break;
1182
1183 case DNS_TYPE_AAAA:
623a4c97 1184 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1185 break;
1186
7e8e0422 1187 case DNS_TYPE_SOA:
151226ab 1188 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422
LP
1189 if (r < 0)
1190 goto fail;
1191
151226ab 1192 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422
LP
1193 if (r < 0)
1194 goto fail;
1195
1196 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1197 if (r < 0)
1198 goto fail;
1199
1200 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1201 if (r < 0)
1202 goto fail;
1203
1204 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1205 if (r < 0)
1206 goto fail;
1207
1208 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1209 if (r < 0)
1210 goto fail;
1211
1212 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1213 break;
1214
623a4c97 1215 case DNS_TYPE_MX:
946c7094
ZJS
1216 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1217 if (r < 0)
1218 goto fail;
1219
151226ab 1220 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
1221 break;
1222
0dae31d4
ZJS
1223 case DNS_TYPE_LOC: {
1224 uint8_t t;
1225 size_t pos;
1226
1227 r = dns_packet_read_uint8(p, &t, &pos);
1228 if (r < 0)
1229 goto fail;
1230
1231 if (t == 0) {
1232 rr->loc.version = t;
1233
1234 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1235 if (r < 0)
1236 goto fail;
1237
afbc4f26
ZJS
1238 if (!loc_size_ok(rr->loc.size)) {
1239 r = -EBADMSG;
1240 goto fail;
1241 }
1242
0dae31d4
ZJS
1243 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1244 if (r < 0)
1245 goto fail;
1246
afbc4f26
ZJS
1247 if (!loc_size_ok(rr->loc.horiz_pre)) {
1248 r = -EBADMSG;
1249 goto fail;
1250 }
1251
0dae31d4
ZJS
1252 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1253 if (r < 0)
1254 goto fail;
1255
afbc4f26
ZJS
1256 if (!loc_size_ok(rr->loc.vert_pre)) {
1257 r = -EBADMSG;
1258 goto fail;
1259 }
1260
0dae31d4
ZJS
1261 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1262 if (r < 0)
1263 goto fail;
1264
1265 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1266 if (r < 0)
1267 goto fail;
1268
1269 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1270 if (r < 0)
1271 goto fail;
1272
1273 break;
1274 } else {
1275 dns_packet_rewind(p, pos);
1276 rr->unparseable = true;
afbc4f26 1277 goto unparseable;
0dae31d4
ZJS
1278 }
1279 }
1280
abf126a3
TG
1281 case DNS_TYPE_DS:
1282 r = dns_packet_read_uint16(p, &rr->ds.key_tag, NULL);
1283 if (r < 0)
1284 goto fail;
1285
1286 r = dns_packet_read_uint8(p, &rr->ds.algorithm, NULL);
1287 if (r < 0)
1288 goto fail;
1289
1290 r = dns_packet_read_uint8(p, &rr->ds.digest_type, NULL);
1291 if (r < 0)
1292 goto fail;
1293
1294 r = dns_packet_read_public_key(p, rdlength - 4,
1295 &rr->ds.digest, &rr->ds.digest_size,
1296 NULL);
1297 if (r < 0)
1298 goto fail;
1299
1300 break;
623a4c97 1301 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1302 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1303 if (r < 0)
1304 goto fail;
1305
1306 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1307 if (r < 0)
1308 goto fail;
1309
8db0d2f5
ZJS
1310 r = dns_packet_read_public_key(p, rdlength - 2,
1311 &rr->sshfp.key, &rr->sshfp.key_size,
1312 NULL);
1313 break;
1314
1315 case DNS_TYPE_DNSKEY: {
1316 uint16_t flags;
1317 uint8_t proto;
1318
1319 r = dns_packet_read_uint16(p, &flags, NULL);
42cc2eeb
LP
1320 if (r < 0)
1321 goto fail;
1322
8db0d2f5
ZJS
1323 r = dnskey_parse_flags(rr, flags);
1324 if (r < 0)
1325 goto fail;
1326
1327 r = dns_packet_read_uint8(p, &proto, NULL);
1328 if (r < 0)
1329 goto fail;
1330
1331 /* protocol is required to be always 3 */
1332 if (proto != 3) {
1333 r = -EBADMSG;
42cc2eeb
LP
1334 goto fail;
1335 }
1336
8db0d2f5
ZJS
1337 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1338 if (r < 0)
1339 goto fail;
1340
1341 r = dns_packet_read_public_key(p, rdlength - 4,
1342 &rr->dnskey.key, &rr->dnskey.key_size,
1343 NULL);
42cc2eeb 1344 break;
8db0d2f5 1345 }
42cc2eeb 1346
151226ab
ZJS
1347 case DNS_TYPE_RRSIG:
1348 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
1349 if (r < 0)
1350 goto fail;
1351
1352 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
1353 if (r < 0)
1354 goto fail;
1355
1356 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
1357 if (r < 0)
1358 goto fail;
1359
1360 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
1361 if (r < 0)
1362 goto fail;
1363
1364 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
1365 if (r < 0)
1366 goto fail;
1367
1368 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
1369 if (r < 0)
1370 goto fail;
1371
1372 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
1373 if (r < 0)
1374 goto fail;
1375
1376 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
1377 if (r < 0)
1378 goto fail;
1379
1380 r = dns_packet_read_public_key(p, offset + rdlength - p->rindex,
1381 &rr->rrsig.signature, &rr->rrsig.signature_size,
1382 NULL);
1383 break;
1384
74b2466e 1385 default:
afbc4f26 1386 unparseable:
74b2466e
LP
1387 r = dns_packet_read(p, rdlength, &d, NULL);
1388 if (r < 0)
1389 goto fail;
1390
1391 rr->generic.data = memdup(d, rdlength);
1392 if (!rr->generic.data) {
1393 r = -ENOMEM;
1394 goto fail;
1395 }
1396
1397 rr->generic.size = rdlength;
1398 break;
1399 }
1400 if (r < 0)
1401 goto fail;
1402 if (p->rindex != offset + rdlength) {
1403 r = -EBADMSG;
1404 goto fail;
1405 }
1406
1407 *ret = rr;
1408 rr = NULL;
1409
1410 if (start)
1411 *start = saved_rindex;
1412
1413 return 0;
1414fail:
1415 dns_packet_rewind(p, saved_rindex);
1416 return r;
1417}
1418
faa133f3
LP
1419int dns_packet_extract(DnsPacket *p) {
1420 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1421 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1422 size_t saved_rindex;
1423 unsigned n, i;
74b2466e
LP
1424 int r;
1425
a4076574
LP
1426 if (p->extracted)
1427 return 0;
1428
faa133f3 1429 saved_rindex = p->rindex;
322345fd
LP
1430 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1431
3cb10d3a 1432 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
1433 if (n > 0) {
1434 question = dns_question_new(n);
1435 if (!question) {
1436 r = -ENOMEM;
1437 goto finish;
1438 }
74b2466e 1439
faa133f3
LP
1440 for (i = 0; i < n; i++) {
1441 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e 1442
faa133f3
LP
1443 r = dns_packet_read_key(p, &key, NULL);
1444 if (r < 0)
1445 goto finish;
74b2466e 1446
faa133f3
LP
1447 r = dns_question_add(question, key);
1448 if (r < 0)
1449 goto finish;
1450 }
1451 }
322345fd 1452
faa133f3
LP
1453 n = DNS_PACKET_RRCOUNT(p);
1454 if (n > 0) {
1455 answer = dns_answer_new(n);
1456 if (!answer) {
1457 r = -ENOMEM;
1458 goto finish;
1459 }
322345fd 1460
faa133f3
LP
1461 for (i = 0; i < n; i++) {
1462 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
322345fd 1463
faa133f3
LP
1464 r = dns_packet_read_rr(p, &rr, NULL);
1465 if (r < 0)
1466 goto finish;
322345fd 1467
faa133f3
LP
1468 r = dns_answer_add(answer, rr);
1469 if (r < 0)
1470 goto finish;
1471 }
322345fd
LP
1472 }
1473
faa133f3
LP
1474 p->question = question;
1475 question = NULL;
322345fd 1476
faa133f3
LP
1477 p->answer = answer;
1478 answer = NULL;
322345fd 1479
a4076574
LP
1480 p->extracted = true;
1481
faa133f3 1482 r = 0;
322345fd
LP
1483
1484finish:
1485 p->rindex = saved_rindex;
1486 return r;
1487}
1488
74b2466e
LP
1489static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1490 [DNS_RCODE_SUCCESS] = "SUCCESS",
1491 [DNS_RCODE_FORMERR] = "FORMERR",
1492 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1493 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1494 [DNS_RCODE_NOTIMP] = "NOTIMP",
1495 [DNS_RCODE_REFUSED] = "REFUSED",
1496 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1497 [DNS_RCODE_YXRRSET] = "YRRSET",
1498 [DNS_RCODE_NXRRSET] = "NXRRSET",
1499 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1500 [DNS_RCODE_NOTZONE] = "NOTZONE",
1501 [DNS_RCODE_BADVERS] = "BADVERS",
1502 [DNS_RCODE_BADKEY] = "BADKEY",
1503 [DNS_RCODE_BADTIME] = "BADTIME",
1504 [DNS_RCODE_BADMODE] = "BADMODE",
1505 [DNS_RCODE_BADNAME] = "BADNAME",
1506 [DNS_RCODE_BADALG] = "BADALG",
1507 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1508};
1509DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc
LP
1510
1511static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1512 [DNS_PROTOCOL_DNS] = "dns",
1513 [DNS_PROTOCOL_MDNS] = "mdns",
1514 [DNS_PROTOCOL_LLMNR] = "llmnr",
1515};
1516DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
ff3d6560
ZJS
1517
1518static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
1519 [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
1520 [DNSSEC_ALGORITHM_DH] = "DH",
1521 [DNSSEC_ALGORITHM_DSA] = "DSA",
1522 [DNSSEC_ALGORITHM_ECC] = "ECC",
1523 [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
1524 [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
1525 [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
1526 [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
1527};
1528DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);