]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/resolve/resolved-dns-packet.c
resolved: rr - print formated timestamps in RRSIG
[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
35 if (mtu <= 0)
36 a = DNS_PACKET_SIZE_START;
37 else
38 a = mtu;
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
623a4c97 655 case DNS_TYPE_SSHFP:
42cc2eeb
LP
656 r = dns_packet_append_uint8(p, rr->sshfp.algorithm, NULL);
657 if (r < 0)
658 goto fail;
8db0d2f5 659
42cc2eeb
LP
660 r = dns_packet_append_uint8(p, rr->sshfp.fptype, NULL);
661 if (r < 0)
662 goto fail;
663
664 r = dns_packet_append_blob(p, rr->sshfp.key, rr->sshfp.key_size, NULL);
665 break;
666
8db0d2f5
ZJS
667 case DNS_TYPE_DNSKEY:
668 r = dns_packet_append_uint16(p, dnskey_to_flags(rr), NULL);
669 if (r < 0)
670 goto fail;
671
672 r = dns_packet_append_uint8(p, 3u, NULL);
673 if (r < 0)
674 goto fail;
675
676 r = dns_packet_append_uint8(p, rr->dnskey.algorithm, NULL);
677 if (r < 0)
678 goto fail;
679
680 r = dns_packet_append_blob(p, rr->dnskey.key, rr->dnskey.key_size, NULL);
681 break;
682
151226ab
ZJS
683 case DNS_TYPE_RRSIG:
684 r = dns_packet_append_uint16(p, rr->rrsig.type_covered, NULL);
685 if (r < 0)
686 goto fail;
687
688 r = dns_packet_append_uint8(p, rr->rrsig.algorithm, NULL);
689 if (r < 0)
690 goto fail;
691
692 r = dns_packet_append_uint8(p, rr->rrsig.labels, NULL);
693 if (r < 0)
694 goto fail;
695
696 r = dns_packet_append_uint32(p, rr->rrsig.original_ttl, NULL);
697 if (r < 0)
698 goto fail;
699
700 r = dns_packet_append_uint32(p, rr->rrsig.expiration, NULL);
701 if (r < 0)
702 goto fail;
703
704 r = dns_packet_append_uint32(p, rr->rrsig.inception, NULL);
705 if (r < 0)
706 goto fail;
707
0b1b17d3 708 r = dns_packet_append_uint16(p, rr->rrsig.key_tag, NULL);
151226ab
ZJS
709 if (r < 0)
710 goto fail;
711
712 r = dns_packet_append_name(p, rr->rrsig.signer, false, NULL);
713 if (r < 0)
714 goto fail;
715
716 r = dns_packet_append_blob(p, rr->rrsig.signature, rr->rrsig.signature_size, NULL);
717 break;
718
0dae31d4 719 case _DNS_TYPE_INVALID: /* unparseable */
623a4c97 720 default:
0dae31d4 721
623a4c97
LP
722 r = dns_packet_append_blob(p, rr->generic.data, rr->generic.size, NULL);
723 break;
724 }
725 if (r < 0)
726 goto fail;
727
728 /* Let's calculate the actual data size and update the field */
729 rdlength = p->size - rdlength_offset - sizeof(uint16_t);
730 if (rdlength > 0xFFFF) {
731 r = ENOSPC;
732 goto fail;
733 }
734
735 end = p->size;
736 p->size = rdlength_offset;
737 r = dns_packet_append_uint16(p, rdlength, NULL);
738 if (r < 0)
739 goto fail;
740 p->size = end;
741
351e6342
LP
742 if (start)
743 *start = saved_size;
744
623a4c97
LP
745 return 0;
746
747fail:
748 dns_packet_truncate(p, saved_size);
749 return r;
750}
751
752
74b2466e
LP
753int dns_packet_read(DnsPacket *p, size_t sz, const void **ret, size_t *start) {
754 assert(p);
755
756 if (p->rindex + sz > p->size)
757 return -EMSGSIZE;
758
759 if (ret)
760 *ret = (uint8_t*) DNS_PACKET_DATA(p) + p->rindex;
761
762 if (start)
763 *start = p->rindex;
764
765 p->rindex += sz;
766 return 0;
767}
768
8ba9fd9c 769void dns_packet_rewind(DnsPacket *p, size_t idx) {
74b2466e
LP
770 assert(p);
771 assert(idx <= p->size);
772 assert(idx >= DNS_PACKET_HEADER_SIZE);
773
774 p->rindex = idx;
775}
776
623a4c97
LP
777int dns_packet_read_blob(DnsPacket *p, void *d, size_t sz, size_t *start) {
778 const void *q;
779 int r;
780
781 assert(p);
782 assert(d);
783
784 r = dns_packet_read(p, sz, &q, start);
785 if (r < 0)
786 return r;
787
788 memcpy(d, q, sz);
789 return 0;
790}
791
74b2466e
LP
792int dns_packet_read_uint8(DnsPacket *p, uint8_t *ret, size_t *start) {
793 const void *d;
794 int r;
795
796 assert(p);
797
798 r = dns_packet_read(p, sizeof(uint8_t), &d, start);
799 if (r < 0)
800 return r;
801
802 *ret = ((uint8_t*) d)[0];
803 return 0;
804}
805
806int dns_packet_read_uint16(DnsPacket *p, uint16_t *ret, size_t *start) {
807 const void *d;
808 int r;
809
810 assert(p);
811
812 r = dns_packet_read(p, sizeof(uint16_t), &d, start);
813 if (r < 0)
814 return r;
815
725ca0e5
TG
816 *ret = unaligned_read_be16(d);
817
74b2466e
LP
818 return 0;
819}
820
821int dns_packet_read_uint32(DnsPacket *p, uint32_t *ret, size_t *start) {
822 const void *d;
823 int r;
824
825 assert(p);
826
827 r = dns_packet_read(p, sizeof(uint32_t), &d, start);
828 if (r < 0)
829 return r;
830
725ca0e5 831 *ret = unaligned_read_be32(d);
74b2466e
LP
832
833 return 0;
834}
835
836int dns_packet_read_string(DnsPacket *p, char **ret, size_t *start) {
837 size_t saved_rindex;
838 const void *d;
839 char *t;
840 uint8_t c;
841 int r;
842
843 assert(p);
844
845 saved_rindex = p->rindex;
846
847 r = dns_packet_read_uint8(p, &c, NULL);
848 if (r < 0)
849 goto fail;
850
851 r = dns_packet_read(p, c, &d, NULL);
852 if (r < 0)
853 goto fail;
854
855 if (memchr(d, 0, c)) {
856 r = -EBADMSG;
857 goto fail;
858 }
859
860 t = strndup(d, c);
861 if (!t) {
862 r = -ENOMEM;
863 goto fail;
864 }
865
866 if (!utf8_is_valid(t)) {
867 free(t);
868 r = -EBADMSG;
869 goto fail;
870 }
871
872 *ret = t;
873
874 if (start)
875 *start = saved_rindex;
876
877 return 0;
878
879fail:
880 dns_packet_rewind(p, saved_rindex);
881 return r;
882}
883
151226ab
ZJS
884int dns_packet_read_name(DnsPacket *p, char **_ret,
885 bool allow_compression, size_t *start) {
c75dbf9b 886 size_t saved_rindex, after_rindex = 0, jump_barrier;
74b2466e
LP
887 _cleanup_free_ char *ret = NULL;
888 size_t n = 0, allocated = 0;
889 bool first = true;
890 int r;
891
892 assert(p);
893 assert(_ret);
894
895 saved_rindex = p->rindex;
c75dbf9b 896 jump_barrier = p->rindex;
74b2466e
LP
897
898 for (;;) {
899 uint8_t c, d;
900
901 r = dns_packet_read_uint8(p, &c, NULL);
902 if (r < 0)
903 goto fail;
904
905 if (c == 0)
906 /* End of name */
907 break;
908 else if (c <= 63) {
909 _cleanup_free_ char *t = NULL;
910 const char *label;
911
912 /* Literal label */
913 r = dns_packet_read(p, c, (const void**) &label, NULL);
914 if (r < 0)
915 goto fail;
916
917 r = dns_label_escape(label, c, &t);
918 if (r < 0)
919 goto fail;
920
921 if (!GREEDY_REALLOC(ret, allocated, n + !first + strlen(t) + 1)) {
922 r = -ENOMEM;
923 goto fail;
924 }
925
926 if (!first)
927 ret[n++] = '.';
928 else
929 first = false;
930
85818582 931 memcpy(ret + n, t, r);
74b2466e
LP
932 n += r;
933 continue;
151226ab 934 } else if (allow_compression && (c & 0xc0) == 0xc0) {
74b2466e
LP
935 uint16_t ptr;
936
937 /* Pointer */
938 r = dns_packet_read_uint8(p, &d, NULL);
939 if (r < 0)
940 goto fail;
941
942 ptr = (uint16_t) (c & ~0xc0) << 8 | (uint16_t) d;
c75dbf9b 943 if (ptr < DNS_PACKET_HEADER_SIZE || ptr >= jump_barrier) {
74b2466e
LP
944 r = -EBADMSG;
945 goto fail;
946 }
947
948 if (after_rindex == 0)
949 after_rindex = p->rindex;
950
f131770b 951 /* Jumps are limited to a "prior occurrence" (RFC-1035 4.1.4) */
c75dbf9b 952 jump_barrier = ptr;
74b2466e 953 p->rindex = ptr;
59aa5821
SP
954 } else {
955 r = -EBADMSG;
74b2466e 956 goto fail;
59aa5821 957 }
74b2466e
LP
958 }
959
960 if (!GREEDY_REALLOC(ret, allocated, n + 1)) {
961 r = -ENOMEM;
962 goto fail;
963 }
964
965 ret[n] = 0;
966
967 if (after_rindex != 0)
968 p->rindex= after_rindex;
969
970 *_ret = ret;
971 ret = NULL;
972
973 if (start)
974 *start = saved_rindex;
975
976 return 0;
977
978fail:
979 dns_packet_rewind(p, saved_rindex);
980 return r;
981}
982
faa133f3
LP
983int dns_packet_read_key(DnsPacket *p, DnsResourceKey **ret, size_t *start) {
984 _cleanup_free_ char *name = NULL;
985 uint16_t class, type;
986 DnsResourceKey *key;
74b2466e
LP
987 size_t saved_rindex;
988 int r;
989
990 assert(p);
991 assert(ret);
992
993 saved_rindex = p->rindex;
994
151226ab 995 r = dns_packet_read_name(p, &name, true, NULL);
74b2466e
LP
996 if (r < 0)
997 goto fail;
998
faa133f3 999 r = dns_packet_read_uint16(p, &type, NULL);
74b2466e
LP
1000 if (r < 0)
1001 goto fail;
1002
faa133f3 1003 r = dns_packet_read_uint16(p, &class, NULL);
74b2466e
LP
1004 if (r < 0)
1005 goto fail;
1006
faa133f3
LP
1007 key = dns_resource_key_new_consume(class, type, name);
1008 if (!key) {
1009 r = -ENOMEM;
1010 goto fail;
1011 }
1012
1013 name = NULL;
1014 *ret = key;
74b2466e
LP
1015
1016 if (start)
1017 *start = saved_rindex;
1018
1019 return 0;
1020fail:
1021 dns_packet_rewind(p, saved_rindex);
1022 return r;
1023}
1024
8db0d2f5
ZJS
1025static int dns_packet_read_public_key(DnsPacket *p, size_t length,
1026 void **dp, size_t *lengthp,
1027 size_t *start) {
1028 int r;
1029 const void *d;
1030 void *d2;
1031
1032 r = dns_packet_read(p, length, &d, NULL);
1033 if (r < 0)
1034 return r;
1035
1036 d2 = memdup(d, length);
1037 if (!d2)
1038 return -ENOMEM;
1039
1040 *dp = d2;
1041 *lengthp = length;
1042 return 0;
1043}
1044
afbc4f26
ZJS
1045static bool loc_size_ok(uint8_t size) {
1046 uint8_t m = size >> 4, e = size & 0xF;
1047
1048 return m <= 9 && e <= 9 && (m > 0 || e == 0);
1049}
1050
8db0d2f5 1051static int dnskey_parse_flags(DnsResourceRecord *rr, uint16_t flags) {
3ef77d04
LP
1052 assert(rr);
1053
8db0d2f5
ZJS
1054 if (flags & ~(DNSKEY_FLAG_SEP | DNSKEY_FLAG_ZONE_KEY))
1055 return -EBADMSG;
1056
1057 rr->dnskey.zone_key_flag = flags & DNSKEY_FLAG_ZONE_KEY;
1058 rr->dnskey.sep_flag = flags & DNSKEY_FLAG_SEP;
1059 return 0;
1060}
1061
74b2466e 1062int dns_packet_read_rr(DnsPacket *p, DnsResourceRecord **ret, size_t *start) {
faa133f3
LP
1063 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
1064 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e
LP
1065 size_t saved_rindex, offset;
1066 uint16_t rdlength;
1067 const void *d;
1068 int r;
1069
1070 assert(p);
1071 assert(ret);
1072
4e0296a9 1073 saved_rindex = p->rindex;
74b2466e 1074
faa133f3 1075 r = dns_packet_read_key(p, &key, NULL);
74b2466e
LP
1076 if (r < 0)
1077 goto fail;
1078
0e2bcd6a
LP
1079 if (key->class == DNS_CLASS_ANY ||
1080 key->type == DNS_TYPE_ANY) {
1081 r = -EBADMSG;
1082 goto fail;
1083 }
1084
faa133f3
LP
1085 rr = dns_resource_record_new(key);
1086 if (!rr) {
1087 r = -ENOMEM;
1088 goto fail;
1089 }
1090
74b2466e
LP
1091 r = dns_packet_read_uint32(p, &rr->ttl, NULL);
1092 if (r < 0)
1093 goto fail;
1094
1095 r = dns_packet_read_uint16(p, &rdlength, NULL);
1096 if (r < 0)
1097 goto fail;
1098
1099 if (p->rindex + rdlength > p->size) {
1100 r = -EBADMSG;
1101 goto fail;
1102 }
1103
1104 offset = p->rindex;
1105
faa133f3 1106 switch (rr->key->type) {
74b2466e 1107
9c92ce6d
LP
1108 case DNS_TYPE_SRV:
1109 r = dns_packet_read_uint16(p, &rr->srv.priority, NULL);
1110 if (r < 0)
1111 goto fail;
1112 r = dns_packet_read_uint16(p, &rr->srv.weight, NULL);
1113 if (r < 0)
1114 goto fail;
1115 r = dns_packet_read_uint16(p, &rr->srv.port, NULL);
1116 if (r < 0)
1117 goto fail;
151226ab 1118 r = dns_packet_read_name(p, &rr->srv.name, true, NULL);
9c92ce6d
LP
1119 break;
1120
74b2466e
LP
1121 case DNS_TYPE_PTR:
1122 case DNS_TYPE_NS:
1123 case DNS_TYPE_CNAME:
8ac4e9e1 1124 case DNS_TYPE_DNAME:
151226ab 1125 r = dns_packet_read_name(p, &rr->ptr.name, true, NULL);
74b2466e
LP
1126 break;
1127
1128 case DNS_TYPE_HINFO:
1129 r = dns_packet_read_string(p, &rr->hinfo.cpu, NULL);
1130 if (r < 0)
1131 goto fail;
1132
1133 r = dns_packet_read_string(p, &rr->hinfo.os, NULL);
1134 break;
1135
9de3e329 1136 case DNS_TYPE_SPF: /* exactly the same as TXT */
1ccda9b7
LP
1137 case DNS_TYPE_TXT:
1138 if (rdlength <= 0) {
1139 /* RFC 6763, section 6.1 suggests to treat
1140 * empty TXT RRs as equivalent to a TXT record
1141 * with a single empty string. */
0e3434ae 1142
1ccda9b7 1143 r = strv_extend(&rr->txt.strings, "");
2e276efc
ZJS
1144 if (r < 0)
1145 goto fail;
1ccda9b7
LP
1146 } else {
1147 while (p->rindex < offset + rdlength) {
1148 char *s;
2e276efc 1149
1ccda9b7
LP
1150 r = dns_packet_read_string(p, &s, NULL);
1151 if (r < 0)
1152 goto fail;
1153
1154 r = strv_consume(&rr->txt.strings, s);
1155 if (r < 0)
1156 goto fail;
1157 }
6a6fc3df
LP
1158 }
1159
1160 r = 0;
2e276efc 1161 break;
2e276efc 1162
74b2466e 1163 case DNS_TYPE_A:
623a4c97 1164 r = dns_packet_read_blob(p, &rr->a.in_addr, sizeof(struct in_addr), NULL);
74b2466e
LP
1165 break;
1166
1167 case DNS_TYPE_AAAA:
623a4c97 1168 r = dns_packet_read_blob(p, &rr->aaaa.in6_addr, sizeof(struct in6_addr), NULL);
74b2466e
LP
1169 break;
1170
7e8e0422 1171 case DNS_TYPE_SOA:
151226ab 1172 r = dns_packet_read_name(p, &rr->soa.mname, true, NULL);
7e8e0422
LP
1173 if (r < 0)
1174 goto fail;
1175
151226ab 1176 r = dns_packet_read_name(p, &rr->soa.rname, true, NULL);
7e8e0422
LP
1177 if (r < 0)
1178 goto fail;
1179
1180 r = dns_packet_read_uint32(p, &rr->soa.serial, NULL);
1181 if (r < 0)
1182 goto fail;
1183
1184 r = dns_packet_read_uint32(p, &rr->soa.refresh, NULL);
1185 if (r < 0)
1186 goto fail;
1187
1188 r = dns_packet_read_uint32(p, &rr->soa.retry, NULL);
1189 if (r < 0)
1190 goto fail;
1191
1192 r = dns_packet_read_uint32(p, &rr->soa.expire, NULL);
1193 if (r < 0)
1194 goto fail;
1195
1196 r = dns_packet_read_uint32(p, &rr->soa.minimum, NULL);
1197 break;
1198
623a4c97 1199 case DNS_TYPE_MX:
946c7094
ZJS
1200 r = dns_packet_read_uint16(p, &rr->mx.priority, NULL);
1201 if (r < 0)
1202 goto fail;
1203
151226ab 1204 r = dns_packet_read_name(p, &rr->mx.exchange, true, NULL);
946c7094
ZJS
1205 break;
1206
0dae31d4
ZJS
1207 case DNS_TYPE_LOC: {
1208 uint8_t t;
1209 size_t pos;
1210
1211 r = dns_packet_read_uint8(p, &t, &pos);
1212 if (r < 0)
1213 goto fail;
1214
1215 if (t == 0) {
1216 rr->loc.version = t;
1217
1218 r = dns_packet_read_uint8(p, &rr->loc.size, NULL);
1219 if (r < 0)
1220 goto fail;
1221
afbc4f26
ZJS
1222 if (!loc_size_ok(rr->loc.size)) {
1223 r = -EBADMSG;
1224 goto fail;
1225 }
1226
0dae31d4
ZJS
1227 r = dns_packet_read_uint8(p, &rr->loc.horiz_pre, NULL);
1228 if (r < 0)
1229 goto fail;
1230
afbc4f26
ZJS
1231 if (!loc_size_ok(rr->loc.horiz_pre)) {
1232 r = -EBADMSG;
1233 goto fail;
1234 }
1235
0dae31d4
ZJS
1236 r = dns_packet_read_uint8(p, &rr->loc.vert_pre, NULL);
1237 if (r < 0)
1238 goto fail;
1239
afbc4f26
ZJS
1240 if (!loc_size_ok(rr->loc.vert_pre)) {
1241 r = -EBADMSG;
1242 goto fail;
1243 }
1244
0dae31d4
ZJS
1245 r = dns_packet_read_uint32(p, &rr->loc.latitude, NULL);
1246 if (r < 0)
1247 goto fail;
1248
1249 r = dns_packet_read_uint32(p, &rr->loc.longitude, NULL);
1250 if (r < 0)
1251 goto fail;
1252
1253 r = dns_packet_read_uint32(p, &rr->loc.altitude, NULL);
1254 if (r < 0)
1255 goto fail;
1256
1257 break;
1258 } else {
1259 dns_packet_rewind(p, pos);
1260 rr->unparseable = true;
afbc4f26 1261 goto unparseable;
0dae31d4
ZJS
1262 }
1263 }
1264
623a4c97 1265 case DNS_TYPE_SSHFP:
42cc2eeb
LP
1266 r = dns_packet_read_uint8(p, &rr->sshfp.algorithm, NULL);
1267 if (r < 0)
1268 goto fail;
1269
1270 r = dns_packet_read_uint8(p, &rr->sshfp.fptype, NULL);
1271 if (r < 0)
1272 goto fail;
1273
8db0d2f5
ZJS
1274 r = dns_packet_read_public_key(p, rdlength - 2,
1275 &rr->sshfp.key, &rr->sshfp.key_size,
1276 NULL);
1277 break;
1278
1279 case DNS_TYPE_DNSKEY: {
1280 uint16_t flags;
1281 uint8_t proto;
1282
1283 r = dns_packet_read_uint16(p, &flags, NULL);
42cc2eeb
LP
1284 if (r < 0)
1285 goto fail;
1286
8db0d2f5
ZJS
1287 r = dnskey_parse_flags(rr, flags);
1288 if (r < 0)
1289 goto fail;
1290
1291 r = dns_packet_read_uint8(p, &proto, NULL);
1292 if (r < 0)
1293 goto fail;
1294
1295 /* protocol is required to be always 3 */
1296 if (proto != 3) {
1297 r = -EBADMSG;
42cc2eeb
LP
1298 goto fail;
1299 }
1300
8db0d2f5
ZJS
1301 r = dns_packet_read_uint8(p, &rr->dnskey.algorithm, NULL);
1302 if (r < 0)
1303 goto fail;
1304
1305 r = dns_packet_read_public_key(p, rdlength - 4,
1306 &rr->dnskey.key, &rr->dnskey.key_size,
1307 NULL);
42cc2eeb 1308 break;
8db0d2f5 1309 }
42cc2eeb 1310
151226ab
ZJS
1311 case DNS_TYPE_RRSIG:
1312 r = dns_packet_read_uint16(p, &rr->rrsig.type_covered, NULL);
1313 if (r < 0)
1314 goto fail;
1315
1316 r = dns_packet_read_uint8(p, &rr->rrsig.algorithm, NULL);
1317 if (r < 0)
1318 goto fail;
1319
1320 r = dns_packet_read_uint8(p, &rr->rrsig.labels, NULL);
1321 if (r < 0)
1322 goto fail;
1323
1324 r = dns_packet_read_uint32(p, &rr->rrsig.original_ttl, NULL);
1325 if (r < 0)
1326 goto fail;
1327
1328 r = dns_packet_read_uint32(p, &rr->rrsig.expiration, NULL);
1329 if (r < 0)
1330 goto fail;
1331
1332 r = dns_packet_read_uint32(p, &rr->rrsig.inception, NULL);
1333 if (r < 0)
1334 goto fail;
1335
1336 r = dns_packet_read_uint16(p, &rr->rrsig.key_tag, NULL);
1337 if (r < 0)
1338 goto fail;
1339
1340 r = dns_packet_read_name(p, &rr->rrsig.signer, false, NULL);
1341 if (r < 0)
1342 goto fail;
1343
1344 r = dns_packet_read_public_key(p, offset + rdlength - p->rindex,
1345 &rr->rrsig.signature, &rr->rrsig.signature_size,
1346 NULL);
1347 break;
1348
74b2466e 1349 default:
afbc4f26 1350 unparseable:
74b2466e
LP
1351 r = dns_packet_read(p, rdlength, &d, NULL);
1352 if (r < 0)
1353 goto fail;
1354
1355 rr->generic.data = memdup(d, rdlength);
1356 if (!rr->generic.data) {
1357 r = -ENOMEM;
1358 goto fail;
1359 }
1360
1361 rr->generic.size = rdlength;
1362 break;
1363 }
1364 if (r < 0)
1365 goto fail;
1366 if (p->rindex != offset + rdlength) {
1367 r = -EBADMSG;
1368 goto fail;
1369 }
1370
1371 *ret = rr;
1372 rr = NULL;
1373
1374 if (start)
1375 *start = saved_rindex;
1376
1377 return 0;
1378fail:
1379 dns_packet_rewind(p, saved_rindex);
1380 return r;
1381}
1382
faa133f3
LP
1383int dns_packet_extract(DnsPacket *p) {
1384 _cleanup_(dns_question_unrefp) DnsQuestion *question = NULL;
1385 _cleanup_(dns_answer_unrefp) DnsAnswer *answer = NULL;
1386 size_t saved_rindex;
1387 unsigned n, i;
74b2466e
LP
1388 int r;
1389
a4076574
LP
1390 if (p->extracted)
1391 return 0;
1392
faa133f3 1393 saved_rindex = p->rindex;
322345fd
LP
1394 dns_packet_rewind(p, DNS_PACKET_HEADER_SIZE);
1395
3cb10d3a 1396 n = DNS_PACKET_QDCOUNT(p);
faa133f3
LP
1397 if (n > 0) {
1398 question = dns_question_new(n);
1399 if (!question) {
1400 r = -ENOMEM;
1401 goto finish;
1402 }
74b2466e 1403
faa133f3
LP
1404 for (i = 0; i < n; i++) {
1405 _cleanup_(dns_resource_key_unrefp) DnsResourceKey *key = NULL;
74b2466e 1406
faa133f3
LP
1407 r = dns_packet_read_key(p, &key, NULL);
1408 if (r < 0)
1409 goto finish;
74b2466e 1410
faa133f3
LP
1411 r = dns_question_add(question, key);
1412 if (r < 0)
1413 goto finish;
1414 }
1415 }
322345fd 1416
faa133f3
LP
1417 n = DNS_PACKET_RRCOUNT(p);
1418 if (n > 0) {
1419 answer = dns_answer_new(n);
1420 if (!answer) {
1421 r = -ENOMEM;
1422 goto finish;
1423 }
322345fd 1424
faa133f3
LP
1425 for (i = 0; i < n; i++) {
1426 _cleanup_(dns_resource_record_unrefp) DnsResourceRecord *rr = NULL;
322345fd 1427
faa133f3
LP
1428 r = dns_packet_read_rr(p, &rr, NULL);
1429 if (r < 0)
1430 goto finish;
322345fd 1431
faa133f3
LP
1432 r = dns_answer_add(answer, rr);
1433 if (r < 0)
1434 goto finish;
1435 }
322345fd
LP
1436 }
1437
faa133f3
LP
1438 p->question = question;
1439 question = NULL;
322345fd 1440
faa133f3
LP
1441 p->answer = answer;
1442 answer = NULL;
322345fd 1443
a4076574
LP
1444 p->extracted = true;
1445
faa133f3 1446 r = 0;
322345fd
LP
1447
1448finish:
1449 p->rindex = saved_rindex;
1450 return r;
1451}
1452
74b2466e
LP
1453static const char* const dns_rcode_table[_DNS_RCODE_MAX_DEFINED] = {
1454 [DNS_RCODE_SUCCESS] = "SUCCESS",
1455 [DNS_RCODE_FORMERR] = "FORMERR",
1456 [DNS_RCODE_SERVFAIL] = "SERVFAIL",
1457 [DNS_RCODE_NXDOMAIN] = "NXDOMAIN",
1458 [DNS_RCODE_NOTIMP] = "NOTIMP",
1459 [DNS_RCODE_REFUSED] = "REFUSED",
1460 [DNS_RCODE_YXDOMAIN] = "YXDOMAIN",
1461 [DNS_RCODE_YXRRSET] = "YRRSET",
1462 [DNS_RCODE_NXRRSET] = "NXRRSET",
1463 [DNS_RCODE_NOTAUTH] = "NOTAUTH",
1464 [DNS_RCODE_NOTZONE] = "NOTZONE",
1465 [DNS_RCODE_BADVERS] = "BADVERS",
1466 [DNS_RCODE_BADKEY] = "BADKEY",
1467 [DNS_RCODE_BADTIME] = "BADTIME",
1468 [DNS_RCODE_BADMODE] = "BADMODE",
1469 [DNS_RCODE_BADNAME] = "BADNAME",
1470 [DNS_RCODE_BADALG] = "BADALG",
1471 [DNS_RCODE_BADTRUNC] = "BADTRUNC",
1472};
1473DEFINE_STRING_TABLE_LOOKUP(dns_rcode, int);
1716f6dc
LP
1474
1475static const char* const dns_protocol_table[_DNS_PROTOCOL_MAX] = {
1476 [DNS_PROTOCOL_DNS] = "dns",
1477 [DNS_PROTOCOL_MDNS] = "mdns",
1478 [DNS_PROTOCOL_LLMNR] = "llmnr",
1479};
1480DEFINE_STRING_TABLE_LOOKUP(dns_protocol, DnsProtocol);
ff3d6560
ZJS
1481
1482static const char* const dnssec_algorithm_table[_DNSSEC_ALGORITHM_MAX_DEFINED] = {
1483 [DNSSEC_ALGORITHM_RSAMD5] = "RSAMD5",
1484 [DNSSEC_ALGORITHM_DH] = "DH",
1485 [DNSSEC_ALGORITHM_DSA] = "DSA",
1486 [DNSSEC_ALGORITHM_ECC] = "ECC",
1487 [DNSSEC_ALGORITHM_RSASHA1] = "RSASHA1",
1488 [DNSSEC_ALGORITHM_INDIRECT] = "INDIRECT",
1489 [DNSSEC_ALGORITHM_PRIVATEDNS] = "PRIVATEDNS",
1490 [DNSSEC_ALGORITHM_PRIVATEOID] = "PRIVATEOID",
1491};
1492DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm, int);