1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2014 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include "alloc-util.h"
24 #include "dns-domain.h"
27 #include "hexdecoct.h"
28 #include "resolved-dns-dnssec.h"
29 #include "resolved-dns-packet.h"
30 #include "resolved-dns-rr.h"
31 #include "string-table.h"
32 #include "string-util.h"
34 #include "terminal-util.h"
36 DnsResourceKey
* dns_resource_key_new(uint16_t class, uint16_t type
, const char *name
) {
43 k
= malloc0(sizeof(DnsResourceKey
) + l
+ 1);
51 strcpy((char*) k
+ sizeof(DnsResourceKey
), name
);
56 DnsResourceKey
* dns_resource_key_new_redirect(const DnsResourceKey
*key
, const DnsResourceRecord
*cname
) {
62 assert(IN_SET(cname
->key
->type
, DNS_TYPE_CNAME
, DNS_TYPE_DNAME
));
64 if (cname
->key
->type
== DNS_TYPE_CNAME
)
65 return dns_resource_key_new(key
->class, key
->type
, cname
->cname
.name
);
68 char *destination
= NULL
;
70 r
= dns_name_change_suffix(dns_resource_key_name(key
), dns_resource_key_name(cname
->key
), cname
->dname
.name
, &destination
);
74 return dns_resource_key_ref((DnsResourceKey
*) key
);
76 k
= dns_resource_key_new_consume(key
->class, key
->type
, destination
);
78 return mfree(destination
);
84 int dns_resource_key_new_append_suffix(DnsResourceKey
**ret
, DnsResourceKey
*key
, char *name
) {
85 DnsResourceKey
*new_key
;
93 if (dns_name_is_root(name
)) {
94 *ret
= dns_resource_key_ref(key
);
98 r
= dns_name_concat(dns_resource_key_name(key
), name
, &joined
);
102 new_key
= dns_resource_key_new_consume(key
->class, key
->type
, joined
);
112 DnsResourceKey
* dns_resource_key_new_consume(uint16_t class, uint16_t type
, char *name
) {
117 k
= new0(DnsResourceKey
, 1);
129 DnsResourceKey
* dns_resource_key_ref(DnsResourceKey
*k
) {
134 /* Static/const keys created with DNS_RESOURCE_KEY_CONST will
135 * set this to -1, they should not be reffed/unreffed */
136 assert(k
->n_ref
!= (unsigned) -1);
138 assert(k
->n_ref
> 0);
144 DnsResourceKey
* dns_resource_key_unref(DnsResourceKey
*k
) {
148 assert(k
->n_ref
!= (unsigned) -1);
149 assert(k
->n_ref
> 0);
160 const char* dns_resource_key_name(const DnsResourceKey
*key
) {
169 name
= (char*) key
+ sizeof(DnsResourceKey
);
171 if (dns_name_is_root(name
))
177 bool dns_resource_key_is_address(const DnsResourceKey
*key
) {
180 /* Check if this is an A or AAAA resource key */
182 return key
->class == DNS_CLASS_IN
&& IN_SET(key
->type
, DNS_TYPE_A
, DNS_TYPE_AAAA
);
185 bool dns_resource_key_is_dnssd_ptr(const DnsResourceKey
*key
) {
188 /* Check if this is a PTR resource key used in
189 Service Instance Enumeration as described in RFC6763 p4.1. */
191 if (key
->type
!= DNS_TYPE_PTR
)
194 return dns_name_endswith(dns_resource_key_name(key
), "_tcp.local") ||
195 dns_name_endswith(dns_resource_key_name(key
), "_udp.local");
198 int dns_resource_key_equal(const DnsResourceKey
*a
, const DnsResourceKey
*b
) {
204 r
= dns_name_equal(dns_resource_key_name(a
), dns_resource_key_name(b
));
208 if (a
->class != b
->class)
211 if (a
->type
!= b
->type
)
217 int dns_resource_key_match_rr(const DnsResourceKey
*key
, DnsResourceRecord
*rr
, const char *search_domain
) {
226 /* Checks if an rr matches the specified key. If a search
227 * domain is specified, it will also be checked if the key
228 * with the search domain suffixed might match the RR. */
230 if (rr
->key
->class != key
->class && key
->class != DNS_CLASS_ANY
)
233 if (rr
->key
->type
!= key
->type
&& key
->type
!= DNS_TYPE_ANY
)
236 r
= dns_name_equal(dns_resource_key_name(rr
->key
), dns_resource_key_name(key
));
241 _cleanup_free_
char *joined
= NULL
;
243 r
= dns_name_concat(dns_resource_key_name(key
), search_domain
, &joined
);
247 return dns_name_equal(dns_resource_key_name(rr
->key
), joined
);
253 int dns_resource_key_match_cname_or_dname(const DnsResourceKey
*key
, const DnsResourceKey
*cname
, const char *search_domain
) {
259 if (cname
->class != key
->class && key
->class != DNS_CLASS_ANY
)
262 if (cname
->type
== DNS_TYPE_CNAME
)
263 r
= dns_name_equal(dns_resource_key_name(key
), dns_resource_key_name(cname
));
264 else if (cname
->type
== DNS_TYPE_DNAME
)
265 r
= dns_name_endswith(dns_resource_key_name(key
), dns_resource_key_name(cname
));
273 _cleanup_free_
char *joined
= NULL
;
275 r
= dns_name_concat(dns_resource_key_name(key
), search_domain
, &joined
);
279 if (cname
->type
== DNS_TYPE_CNAME
)
280 return dns_name_equal(joined
, dns_resource_key_name(cname
));
281 else if (cname
->type
== DNS_TYPE_DNAME
)
282 return dns_name_endswith(joined
, dns_resource_key_name(cname
));
288 int dns_resource_key_match_soa(const DnsResourceKey
*key
, const DnsResourceKey
*soa
) {
292 /* Checks whether 'soa' is a SOA record for the specified key. */
294 if (soa
->class != key
->class)
297 if (soa
->type
!= DNS_TYPE_SOA
)
300 return dns_name_endswith(dns_resource_key_name(key
), dns_resource_key_name(soa
));
303 static void dns_resource_key_hash_func(const void *i
, struct siphash
*state
) {
304 const DnsResourceKey
*k
= i
;
308 dns_name_hash_func(dns_resource_key_name(k
), state
);
309 siphash24_compress(&k
->class, sizeof(k
->class), state
);
310 siphash24_compress(&k
->type
, sizeof(k
->type
), state
);
313 static int dns_resource_key_compare_func(const void *a
, const void *b
) {
314 const DnsResourceKey
*x
= a
, *y
= b
;
317 ret
= dns_name_compare_func(dns_resource_key_name(x
), dns_resource_key_name(y
));
321 if (x
->type
< y
->type
)
323 if (x
->type
> y
->type
)
326 if (x
->class < y
->class)
328 if (x
->class > y
->class)
334 const struct hash_ops dns_resource_key_hash_ops
= {
335 .hash
= dns_resource_key_hash_func
,
336 .compare
= dns_resource_key_compare_func
339 char* dns_resource_key_to_string(const DnsResourceKey
*key
, char *buf
, size_t buf_size
) {
343 /* If we cannot convert the CLASS/TYPE into a known string,
344 use the format recommended by RFC 3597, Section 5. */
346 c
= dns_class_to_string(key
->class);
347 t
= dns_type_to_string(key
->type
);
349 snprintf(buf
, buf_size
, "%s %s%s%.0u %s%s%.0u",
350 dns_resource_key_name(key
),
351 strempty(c
), c
? "" : "CLASS", c
? 0 : key
->class,
352 strempty(t
), t
? "" : "TYPE", t
? 0 : key
->class);
357 bool dns_resource_key_reduce(DnsResourceKey
**a
, DnsResourceKey
**b
) {
361 /* Try to replace one RR key by another if they are identical, thus saving a bit of memory. Note that we do
362 * this only for RR keys, not for RRs themselves, as they carry a lot of additional metadata (where they come
363 * from, validity data, and suchlike), and cannot be replaced so easily by other RRs that have the same
364 * superficial data. */
371 /* We refuse merging const keys */
372 if ((*a
)->n_ref
== (unsigned) -1)
374 if ((*b
)->n_ref
== (unsigned) -1)
377 /* Already the same? */
381 /* Are they really identical? */
382 if (dns_resource_key_equal(*a
, *b
) <= 0)
385 /* Keep the one which already has more references. */
386 if ((*a
)->n_ref
> (*b
)->n_ref
) {
387 dns_resource_key_unref(*b
);
388 *b
= dns_resource_key_ref(*a
);
390 dns_resource_key_unref(*a
);
391 *a
= dns_resource_key_ref(*b
);
397 DnsResourceRecord
* dns_resource_record_new(DnsResourceKey
*key
) {
398 DnsResourceRecord
*rr
;
400 rr
= new0(DnsResourceRecord
, 1);
405 rr
->key
= dns_resource_key_ref(key
);
406 rr
->expiry
= USEC_INFINITY
;
407 rr
->n_skip_labels_signer
= rr
->n_skip_labels_source
= (unsigned) -1;
412 DnsResourceRecord
* dns_resource_record_new_full(uint16_t class, uint16_t type
, const char *name
) {
413 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
415 key
= dns_resource_key_new(class, type
, name
);
419 return dns_resource_record_new(key
);
422 DnsResourceRecord
* dns_resource_record_ref(DnsResourceRecord
*rr
) {
426 assert(rr
->n_ref
> 0);
432 DnsResourceRecord
* dns_resource_record_unref(DnsResourceRecord
*rr
) {
436 assert(rr
->n_ref
> 0);
444 switch(rr
->key
->type
) {
464 dns_txt_item_free_all(rr
->txt
.items
);
473 free(rr
->mx
.exchange
);
481 free(rr
->sshfp
.fingerprint
);
484 case DNS_TYPE_DNSKEY
:
485 free(rr
->dnskey
.key
);
489 free(rr
->rrsig
.signer
);
490 free(rr
->rrsig
.signature
);
494 free(rr
->nsec
.next_domain_name
);
495 bitmap_free(rr
->nsec
.types
);
499 free(rr
->nsec3
.next_hashed_name
);
500 free(rr
->nsec3
.salt
);
501 bitmap_free(rr
->nsec3
.types
);
518 case DNS_TYPE_OPENPGPKEY
:
520 if (!rr
->unparseable
)
521 free(rr
->generic
.data
);
525 free(rr
->generic
.data
);
527 free(rr
->wire_format
);
528 dns_resource_key_unref(rr
->key
);
535 int dns_resource_record_new_reverse(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *hostname
) {
536 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
537 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
538 _cleanup_free_
char *ptr
= NULL
;
545 r
= dns_name_reverse(family
, address
, &ptr
);
549 key
= dns_resource_key_new_consume(DNS_CLASS_IN
, DNS_TYPE_PTR
, ptr
);
555 rr
= dns_resource_record_new(key
);
559 rr
->ptr
.name
= strdup(hostname
);
569 int dns_resource_record_new_address(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *name
) {
570 DnsResourceRecord
*rr
;
576 if (family
== AF_INET
) {
578 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, name
);
582 rr
->a
.in_addr
= address
->in
;
584 } else if (family
== AF_INET6
) {
586 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_AAAA
, name
);
590 rr
->aaaa
.in6_addr
= address
->in6
;
592 return -EAFNOSUPPORT
;
599 #define FIELD_EQUAL(a, b, field) \
600 ((a).field ## _size == (b).field ## _size && \
601 memcmp((a).field, (b).field, (a).field ## _size) == 0)
603 int dns_resource_record_equal(const DnsResourceRecord
*a
, const DnsResourceRecord
*b
) {
612 r
= dns_resource_key_equal(a
->key
, b
->key
);
616 if (a
->unparseable
!= b
->unparseable
)
619 switch (a
->unparseable
? _DNS_TYPE_INVALID
: a
->key
->type
) {
622 r
= dns_name_equal(a
->srv
.name
, b
->srv
.name
);
626 return a
->srv
.priority
== b
->srv
.priority
&&
627 a
->srv
.weight
== b
->srv
.weight
&&
628 a
->srv
.port
== b
->srv
.port
;
634 return dns_name_equal(a
->ptr
.name
, b
->ptr
.name
);
637 return strcaseeq(a
->hinfo
.cpu
, b
->hinfo
.cpu
) &&
638 strcaseeq(a
->hinfo
.os
, b
->hinfo
.os
);
640 case DNS_TYPE_SPF
: /* exactly the same as TXT */
642 return dns_txt_item_equal(a
->txt
.items
, b
->txt
.items
);
645 return memcmp(&a
->a
.in_addr
, &b
->a
.in_addr
, sizeof(struct in_addr
)) == 0;
648 return memcmp(&a
->aaaa
.in6_addr
, &b
->aaaa
.in6_addr
, sizeof(struct in6_addr
)) == 0;
651 r
= dns_name_equal(a
->soa
.mname
, b
->soa
.mname
);
654 r
= dns_name_equal(a
->soa
.rname
, b
->soa
.rname
);
658 return a
->soa
.serial
== b
->soa
.serial
&&
659 a
->soa
.refresh
== b
->soa
.refresh
&&
660 a
->soa
.retry
== b
->soa
.retry
&&
661 a
->soa
.expire
== b
->soa
.expire
&&
662 a
->soa
.minimum
== b
->soa
.minimum
;
665 if (a
->mx
.priority
!= b
->mx
.priority
)
668 return dns_name_equal(a
->mx
.exchange
, b
->mx
.exchange
);
671 assert(a
->loc
.version
== b
->loc
.version
);
673 return a
->loc
.size
== b
->loc
.size
&&
674 a
->loc
.horiz_pre
== b
->loc
.horiz_pre
&&
675 a
->loc
.vert_pre
== b
->loc
.vert_pre
&&
676 a
->loc
.latitude
== b
->loc
.latitude
&&
677 a
->loc
.longitude
== b
->loc
.longitude
&&
678 a
->loc
.altitude
== b
->loc
.altitude
;
681 return a
->ds
.key_tag
== b
->ds
.key_tag
&&
682 a
->ds
.algorithm
== b
->ds
.algorithm
&&
683 a
->ds
.digest_type
== b
->ds
.digest_type
&&
684 FIELD_EQUAL(a
->ds
, b
->ds
, digest
);
687 return a
->sshfp
.algorithm
== b
->sshfp
.algorithm
&&
688 a
->sshfp
.fptype
== b
->sshfp
.fptype
&&
689 FIELD_EQUAL(a
->sshfp
, b
->sshfp
, fingerprint
);
691 case DNS_TYPE_DNSKEY
:
692 return a
->dnskey
.flags
== b
->dnskey
.flags
&&
693 a
->dnskey
.protocol
== b
->dnskey
.protocol
&&
694 a
->dnskey
.algorithm
== b
->dnskey
.algorithm
&&
695 FIELD_EQUAL(a
->dnskey
, b
->dnskey
, key
);
698 /* do the fast comparisons first */
699 return a
->rrsig
.type_covered
== b
->rrsig
.type_covered
&&
700 a
->rrsig
.algorithm
== b
->rrsig
.algorithm
&&
701 a
->rrsig
.labels
== b
->rrsig
.labels
&&
702 a
->rrsig
.original_ttl
== b
->rrsig
.original_ttl
&&
703 a
->rrsig
.expiration
== b
->rrsig
.expiration
&&
704 a
->rrsig
.inception
== b
->rrsig
.inception
&&
705 a
->rrsig
.key_tag
== b
->rrsig
.key_tag
&&
706 FIELD_EQUAL(a
->rrsig
, b
->rrsig
, signature
) &&
707 dns_name_equal(a
->rrsig
.signer
, b
->rrsig
.signer
);
710 return dns_name_equal(a
->nsec
.next_domain_name
, b
->nsec
.next_domain_name
) &&
711 bitmap_equal(a
->nsec
.types
, b
->nsec
.types
);
714 return a
->nsec3
.algorithm
== b
->nsec3
.algorithm
&&
715 a
->nsec3
.flags
== b
->nsec3
.flags
&&
716 a
->nsec3
.iterations
== b
->nsec3
.iterations
&&
717 FIELD_EQUAL(a
->nsec3
, b
->nsec3
, salt
) &&
718 FIELD_EQUAL(a
->nsec3
, b
->nsec3
, next_hashed_name
) &&
719 bitmap_equal(a
->nsec3
.types
, b
->nsec3
.types
);
722 return a
->tlsa
.cert_usage
== b
->tlsa
.cert_usage
&&
723 a
->tlsa
.selector
== b
->tlsa
.selector
&&
724 a
->tlsa
.matching_type
== b
->tlsa
.matching_type
&&
725 FIELD_EQUAL(a
->tlsa
, b
->tlsa
, data
);
728 return a
->caa
.flags
== b
->caa
.flags
&&
729 streq(a
->caa
.tag
, b
->caa
.tag
) &&
730 FIELD_EQUAL(a
->caa
, b
->caa
, value
);
732 case DNS_TYPE_OPENPGPKEY
:
734 return FIELD_EQUAL(a
->generic
, b
->generic
, data
);
738 static char* format_location(uint32_t latitude
, uint32_t longitude
, uint32_t altitude
,
739 uint8_t size
, uint8_t horiz_pre
, uint8_t vert_pre
) {
741 char NS
= latitude
>= 1U<<31 ? 'N' : 'S';
742 char EW
= longitude
>= 1U<<31 ? 'E' : 'W';
744 int lat
= latitude
>= 1U<<31 ? (int) (latitude
- (1U<<31)) : (int) ((1U<<31) - latitude
);
745 int lon
= longitude
>= 1U<<31 ? (int) (longitude
- (1U<<31)) : (int) ((1U<<31) - longitude
);
746 double alt
= altitude
>= 10000000u ? altitude
- 10000000u : -(double)(10000000u - altitude
);
747 double siz
= (size
>> 4) * exp10((double) (size
& 0xF));
748 double hor
= (horiz_pre
>> 4) * exp10((double) (horiz_pre
& 0xF));
749 double ver
= (vert_pre
>> 4) * exp10((double) (vert_pre
& 0xF));
751 if (asprintf(&s
, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
754 (lat
% 60000) / 1000.,
758 (lon
% 60000) / 1000.,
769 static int format_timestamp_dns(char *buf
, size_t l
, time_t sec
) {
773 assert(l
> STRLEN("YYYYMMDDHHmmSS"));
775 if (!gmtime_r(&sec
, &tm
))
778 if (strftime(buf
, l
, "%Y%m%d%H%M%S", &tm
) <= 0)
784 static char *format_types(Bitmap
*types
) {
785 _cleanup_strv_free_
char **strv
= NULL
;
786 _cleanup_free_
char *str
= NULL
;
791 BITMAP_FOREACH(type
, types
, i
) {
792 if (dns_type_to_string(type
)) {
793 r
= strv_extend(&strv
, dns_type_to_string(type
));
799 r
= asprintf(&t
, "TYPE%u", type
);
803 r
= strv_consume(&strv
, t
);
809 str
= strv_join(strv
, " ");
813 return strjoin("( ", str
, " )");
816 static char *format_txt(DnsTxtItem
*first
) {
821 LIST_FOREACH(items
, i
, first
)
822 c
+= i
->length
* 4 + 3;
824 p
= s
= new(char, c
);
828 LIST_FOREACH(items
, i
, first
) {
836 for (j
= 0; j
< i
->length
; j
++) {
837 if (i
->data
[j
] < ' ' || i
->data
[j
] == '"' || i
->data
[j
] >= 127) {
839 *(p
++) = '0' + (i
->data
[j
] / 100);
840 *(p
++) = '0' + ((i
->data
[j
] / 10) % 10);
841 *(p
++) = '0' + (i
->data
[j
] % 10);
853 const char *dns_resource_record_to_string(DnsResourceRecord
*rr
) {
854 _cleanup_free_
char *t
= NULL
;
855 char *s
, k
[DNS_RESOURCE_KEY_STRING_MAX
];
861 return rr
->to_string
;
863 dns_resource_key_to_string(rr
->key
, k
, sizeof(k
));
865 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
868 r
= asprintf(&s
, "%s %u %u %u %s",
873 strna(rr
->srv
.name
));
882 s
= strjoin(k
, " ", rr
->ptr
.name
);
889 s
= strjoin(k
, " ", rr
->hinfo
.cpu
, " ", rr
->hinfo
.os
);
894 case DNS_TYPE_SPF
: /* exactly the same as TXT */
896 t
= format_txt(rr
->txt
.items
);
900 s
= strjoin(k
, " ", t
);
906 _cleanup_free_
char *x
= NULL
;
908 r
= in_addr_to_string(AF_INET
, (const union in_addr_union
*) &rr
->a
.in_addr
, &x
);
912 s
= strjoin(k
, " ", x
);
919 r
= in_addr_to_string(AF_INET6
, (const union in_addr_union
*) &rr
->aaaa
.in6_addr
, &t
);
923 s
= strjoin(k
, " ", t
);
929 r
= asprintf(&s
, "%s %s %s %u %u %u %u %u",
931 strna(rr
->soa
.mname
),
932 strna(rr
->soa
.rname
),
943 r
= asprintf(&s
, "%s %u %s",
952 assert(rr
->loc
.version
== 0);
954 t
= format_location(rr
->loc
.latitude
,
963 s
= strjoin(k
, " ", t
);
969 t
= hexmem(rr
->ds
.digest
, rr
->ds
.digest_size
);
973 r
= asprintf(&s
, "%s %u %u %u %s",
984 t
= hexmem(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
988 r
= asprintf(&s
, "%s %u %u %s",
997 case DNS_TYPE_DNSKEY
: {
998 _cleanup_free_
char *alg
= NULL
;
1003 key_tag
= dnssec_keytag(rr
, true);
1005 r
= dnssec_algorithm_to_string_alloc(rr
->dnskey
.algorithm
, &alg
);
1009 r
= asprintf(&s
, "%s %u %u %s %n",
1012 rr
->dnskey
.protocol
,
1018 r
= base64_append(&s
, n
,
1019 rr
->dnskey
.key
, rr
->dnskey
.key_size
,
1024 r
= asprintf(&ss
, "%s\n"
1025 " -- Flags:%s%s%s\n"
1028 rr
->dnskey
.flags
& DNSKEY_FLAG_SEP
? " SEP" : "",
1029 rr
->dnskey
.flags
& DNSKEY_FLAG_REVOKE
? " REVOKE" : "",
1030 rr
->dnskey
.flags
& DNSKEY_FLAG_ZONE_KEY
? " ZONE_KEY" : "",
1040 case DNS_TYPE_RRSIG
: {
1041 _cleanup_free_
char *alg
= NULL
;
1042 char expiration
[STRLEN("YYYYMMDDHHmmSS") + 1], inception
[STRLEN("YYYYMMDDHHmmSS") + 1];
1046 type
= dns_type_to_string(rr
->rrsig
.type_covered
);
1048 r
= dnssec_algorithm_to_string_alloc(rr
->rrsig
.algorithm
, &alg
);
1052 r
= format_timestamp_dns(expiration
, sizeof(expiration
), rr
->rrsig
.expiration
);
1056 r
= format_timestamp_dns(inception
, sizeof(inception
), rr
->rrsig
.inception
);
1061 * http://tools.ietf.org/html/rfc3597#section-5 */
1063 r
= asprintf(&s
, "%s %s%.*u %s %u %u %s %s %u %s %n",
1066 type
? 0 : 1, type
? 0u : (unsigned) rr
->rrsig
.type_covered
,
1069 rr
->rrsig
.original_ttl
,
1078 r
= base64_append(&s
, n
,
1079 rr
->rrsig
.signature
, rr
->rrsig
.signature_size
,
1088 t
= format_types(rr
->nsec
.types
);
1092 r
= asprintf(&s
, "%s %s %s",
1094 rr
->nsec
.next_domain_name
,
1100 case DNS_TYPE_NSEC3
: {
1101 _cleanup_free_
char *salt
= NULL
, *hash
= NULL
;
1103 if (rr
->nsec3
.salt_size
> 0) {
1104 salt
= hexmem(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
);
1109 hash
= base32hexmem(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, false);
1113 t
= format_types(rr
->nsec3
.types
);
1117 r
= asprintf(&s
, "%s %"PRIu8
" %"PRIu8
" %"PRIu16
" %s %s %s",
1119 rr
->nsec3
.algorithm
,
1121 rr
->nsec3
.iterations
,
1122 rr
->nsec3
.salt_size
> 0 ? salt
: "-",
1131 case DNS_TYPE_TLSA
: {
1132 const char *cert_usage
, *selector
, *matching_type
;
1134 cert_usage
= tlsa_cert_usage_to_string(rr
->tlsa
.cert_usage
);
1135 selector
= tlsa_selector_to_string(rr
->tlsa
.selector
);
1136 matching_type
= tlsa_matching_type_to_string(rr
->tlsa
.matching_type
);
1138 t
= hexmem(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
1144 " -- Cert. usage: %s\n"
1145 " -- Selector: %s\n"
1146 " -- Matching type: %s",
1148 rr
->tlsa
.cert_usage
,
1150 rr
->tlsa
.matching_type
,
1161 case DNS_TYPE_CAA
: {
1162 _cleanup_free_
char *value
;
1164 value
= octescape(rr
->caa
.value
, rr
->caa
.value_size
);
1168 r
= asprintf(&s
, "%s %u %s \"%s\"%s%s%s%.0u",
1173 rr
->caa
.flags
? "\n -- Flags:" : "",
1174 rr
->caa
.flags
& CAA_FLAG_CRITICAL
? " critical" : "",
1175 rr
->caa
.flags
& ~CAA_FLAG_CRITICAL
? " " : "",
1176 rr
->caa
.flags
& ~CAA_FLAG_CRITICAL
);
1183 case DNS_TYPE_OPENPGPKEY
: {
1186 r
= asprintf(&s
, "%s %n",
1192 r
= base64_append(&s
, n
,
1193 rr
->generic
.data
, rr
->generic
.data_size
,
1201 t
= hexmem(rr
->generic
.data
, rr
->generic
.data_size
);
1205 /* Format as documented in RFC 3597, Section 5 */
1206 r
= asprintf(&s
, "%s \\# %zu %s", k
, rr
->generic
.data_size
, t
);
1216 ssize_t
dns_resource_record_payload(DnsResourceRecord
*rr
, void **out
) {
1220 switch(rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1224 case DNS_TYPE_CNAME
:
1225 case DNS_TYPE_DNAME
:
1226 case DNS_TYPE_HINFO
:
1235 case DNS_TYPE_DNSKEY
:
1236 case DNS_TYPE_RRSIG
:
1238 case DNS_TYPE_NSEC3
:
1241 case DNS_TYPE_SSHFP
:
1242 *out
= rr
->sshfp
.fingerprint
;
1243 return rr
->sshfp
.fingerprint_size
;
1246 *out
= rr
->tlsa
.data
;
1247 return rr
->tlsa
.data_size
;
1250 case DNS_TYPE_OPENPGPKEY
:
1252 *out
= rr
->generic
.data
;
1253 return rr
->generic
.data_size
;
1257 int dns_resource_record_to_wire_format(DnsResourceRecord
*rr
, bool canonical
) {
1259 DnsPacket packet
= {
1261 .protocol
= DNS_PROTOCOL_DNS
,
1263 .refuse_compression
= true,
1264 .canonical_form
= canonical
,
1272 /* Generates the RR in wire-format, optionally in the
1273 * canonical form as discussed in the DNSSEC RFC 4034, Section
1274 * 6.2. We allocate a throw-away DnsPacket object on the stack
1275 * here, because we need some book-keeping for memory
1276 * management, and can reuse the DnsPacket serializer, that
1277 * can generate the canonical form, too, but also knows label
1278 * compression and suchlike. */
1280 if (rr
->wire_format
&& rr
->wire_format_canonical
== canonical
)
1283 r
= dns_packet_append_rr(&packet
, rr
, 0, &start
, &rds
);
1288 assert(packet
._data
);
1290 free(rr
->wire_format
);
1291 rr
->wire_format
= packet
._data
;
1292 rr
->wire_format_size
= packet
.size
;
1293 rr
->wire_format_rdata_offset
= rds
;
1294 rr
->wire_format_canonical
= canonical
;
1296 packet
._data
= NULL
;
1297 dns_packet_unref(&packet
);
1302 int dns_resource_record_signer(DnsResourceRecord
*rr
, const char **ret
) {
1309 /* Returns the RRset's signer, if it is known. */
1311 if (rr
->n_skip_labels_signer
== (unsigned) -1)
1314 n
= dns_resource_key_name(rr
->key
);
1315 r
= dns_name_skip(n
, rr
->n_skip_labels_signer
, &n
);
1325 int dns_resource_record_source(DnsResourceRecord
*rr
, const char **ret
) {
1332 /* Returns the RRset's synthesizing source, if it is known. */
1334 if (rr
->n_skip_labels_source
== (unsigned) -1)
1337 n
= dns_resource_key_name(rr
->key
);
1338 r
= dns_name_skip(n
, rr
->n_skip_labels_source
, &n
);
1348 int dns_resource_record_is_signer(DnsResourceRecord
*rr
, const char *zone
) {
1354 r
= dns_resource_record_signer(rr
, &signer
);
1358 return dns_name_equal(zone
, signer
);
1361 int dns_resource_record_is_synthetic(DnsResourceRecord
*rr
) {
1366 /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
1368 if (rr
->n_skip_labels_source
== (unsigned) -1)
1371 if (rr
->n_skip_labels_source
== 0)
1374 if (rr
->n_skip_labels_source
> 1)
1377 r
= dns_name_startswith(dns_resource_key_name(rr
->key
), "*");
1384 void dns_resource_record_hash_func(const void *i
, struct siphash
*state
) {
1385 const DnsResourceRecord
*rr
= i
;
1389 dns_resource_key_hash_func(rr
->key
, state
);
1391 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1394 siphash24_compress(&rr
->srv
.priority
, sizeof(rr
->srv
.priority
), state
);
1395 siphash24_compress(&rr
->srv
.weight
, sizeof(rr
->srv
.weight
), state
);
1396 siphash24_compress(&rr
->srv
.port
, sizeof(rr
->srv
.port
), state
);
1397 dns_name_hash_func(rr
->srv
.name
, state
);
1402 case DNS_TYPE_CNAME
:
1403 case DNS_TYPE_DNAME
:
1404 dns_name_hash_func(rr
->ptr
.name
, state
);
1407 case DNS_TYPE_HINFO
:
1408 string_hash_func(rr
->hinfo
.cpu
, state
);
1409 string_hash_func(rr
->hinfo
.os
, state
);
1413 case DNS_TYPE_SPF
: {
1416 LIST_FOREACH(items
, j
, rr
->txt
.items
) {
1417 siphash24_compress(j
->data
, j
->length
, state
);
1419 /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
1420 * followed by "". */
1421 siphash24_compress_byte(0, state
);
1427 siphash24_compress(&rr
->a
.in_addr
, sizeof(rr
->a
.in_addr
), state
);
1431 siphash24_compress(&rr
->aaaa
.in6_addr
, sizeof(rr
->aaaa
.in6_addr
), state
);
1435 dns_name_hash_func(rr
->soa
.mname
, state
);
1436 dns_name_hash_func(rr
->soa
.rname
, state
);
1437 siphash24_compress(&rr
->soa
.serial
, sizeof(rr
->soa
.serial
), state
);
1438 siphash24_compress(&rr
->soa
.refresh
, sizeof(rr
->soa
.refresh
), state
);
1439 siphash24_compress(&rr
->soa
.retry
, sizeof(rr
->soa
.retry
), state
);
1440 siphash24_compress(&rr
->soa
.expire
, sizeof(rr
->soa
.expire
), state
);
1441 siphash24_compress(&rr
->soa
.minimum
, sizeof(rr
->soa
.minimum
), state
);
1445 siphash24_compress(&rr
->mx
.priority
, sizeof(rr
->mx
.priority
), state
);
1446 dns_name_hash_func(rr
->mx
.exchange
, state
);
1450 siphash24_compress(&rr
->loc
.version
, sizeof(rr
->loc
.version
), state
);
1451 siphash24_compress(&rr
->loc
.size
, sizeof(rr
->loc
.size
), state
);
1452 siphash24_compress(&rr
->loc
.horiz_pre
, sizeof(rr
->loc
.horiz_pre
), state
);
1453 siphash24_compress(&rr
->loc
.vert_pre
, sizeof(rr
->loc
.vert_pre
), state
);
1454 siphash24_compress(&rr
->loc
.latitude
, sizeof(rr
->loc
.latitude
), state
);
1455 siphash24_compress(&rr
->loc
.longitude
, sizeof(rr
->loc
.longitude
), state
);
1456 siphash24_compress(&rr
->loc
.altitude
, sizeof(rr
->loc
.altitude
), state
);
1459 case DNS_TYPE_SSHFP
:
1460 siphash24_compress(&rr
->sshfp
.algorithm
, sizeof(rr
->sshfp
.algorithm
), state
);
1461 siphash24_compress(&rr
->sshfp
.fptype
, sizeof(rr
->sshfp
.fptype
), state
);
1462 siphash24_compress(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
, state
);
1465 case DNS_TYPE_DNSKEY
:
1466 siphash24_compress(&rr
->dnskey
.flags
, sizeof(rr
->dnskey
.flags
), state
);
1467 siphash24_compress(&rr
->dnskey
.protocol
, sizeof(rr
->dnskey
.protocol
), state
);
1468 siphash24_compress(&rr
->dnskey
.algorithm
, sizeof(rr
->dnskey
.algorithm
), state
);
1469 siphash24_compress(rr
->dnskey
.key
, rr
->dnskey
.key_size
, state
);
1472 case DNS_TYPE_RRSIG
:
1473 siphash24_compress(&rr
->rrsig
.type_covered
, sizeof(rr
->rrsig
.type_covered
), state
);
1474 siphash24_compress(&rr
->rrsig
.algorithm
, sizeof(rr
->rrsig
.algorithm
), state
);
1475 siphash24_compress(&rr
->rrsig
.labels
, sizeof(rr
->rrsig
.labels
), state
);
1476 siphash24_compress(&rr
->rrsig
.original_ttl
, sizeof(rr
->rrsig
.original_ttl
), state
);
1477 siphash24_compress(&rr
->rrsig
.expiration
, sizeof(rr
->rrsig
.expiration
), state
);
1478 siphash24_compress(&rr
->rrsig
.inception
, sizeof(rr
->rrsig
.inception
), state
);
1479 siphash24_compress(&rr
->rrsig
.key_tag
, sizeof(rr
->rrsig
.key_tag
), state
);
1480 dns_name_hash_func(rr
->rrsig
.signer
, state
);
1481 siphash24_compress(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
, state
);
1485 dns_name_hash_func(rr
->nsec
.next_domain_name
, state
);
1486 /* FIXME: we leave out the type bitmap here. Hash
1487 * would be better if we'd take it into account
1492 siphash24_compress(&rr
->ds
.key_tag
, sizeof(rr
->ds
.key_tag
), state
);
1493 siphash24_compress(&rr
->ds
.algorithm
, sizeof(rr
->ds
.algorithm
), state
);
1494 siphash24_compress(&rr
->ds
.digest_type
, sizeof(rr
->ds
.digest_type
), state
);
1495 siphash24_compress(rr
->ds
.digest
, rr
->ds
.digest_size
, state
);
1498 case DNS_TYPE_NSEC3
:
1499 siphash24_compress(&rr
->nsec3
.algorithm
, sizeof(rr
->nsec3
.algorithm
), state
);
1500 siphash24_compress(&rr
->nsec3
.flags
, sizeof(rr
->nsec3
.flags
), state
);
1501 siphash24_compress(&rr
->nsec3
.iterations
, sizeof(rr
->nsec3
.iterations
), state
);
1502 siphash24_compress(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
, state
);
1503 siphash24_compress(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, state
);
1504 /* FIXME: We leave the bitmaps out */
1508 siphash24_compress(&rr
->tlsa
.cert_usage
, sizeof(rr
->tlsa
.cert_usage
), state
);
1509 siphash24_compress(&rr
->tlsa
.selector
, sizeof(rr
->tlsa
.selector
), state
);
1510 siphash24_compress(&rr
->tlsa
.matching_type
, sizeof(rr
->tlsa
.matching_type
), state
);
1511 siphash24_compress(rr
->tlsa
.data
, rr
->tlsa
.data_size
, state
);
1515 siphash24_compress(&rr
->caa
.flags
, sizeof(rr
->caa
.flags
), state
);
1516 string_hash_func(rr
->caa
.tag
, state
);
1517 siphash24_compress(rr
->caa
.value
, rr
->caa
.value_size
, state
);
1520 case DNS_TYPE_OPENPGPKEY
:
1522 siphash24_compress(rr
->generic
.data
, rr
->generic
.data_size
, state
);
1527 static int dns_resource_record_compare_func(const void *a
, const void *b
) {
1528 const DnsResourceRecord
*x
= a
, *y
= b
;
1531 ret
= dns_resource_key_compare_func(x
->key
, y
->key
);
1535 if (dns_resource_record_equal(x
, y
))
1538 /* This is a bit dirty, we don't implement proper ordering, but
1539 * the hashtable doesn't need ordering anyway, hence we don't
1541 return x
< y
? -1 : 1;
1544 const struct hash_ops dns_resource_record_hash_ops
= {
1545 .hash
= dns_resource_record_hash_func
,
1546 .compare
= dns_resource_record_compare_func
,
1549 DnsResourceRecord
*dns_resource_record_copy(DnsResourceRecord
*rr
) {
1550 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*copy
= NULL
;
1551 DnsResourceRecord
*t
;
1555 copy
= dns_resource_record_new(rr
->key
);
1559 copy
->ttl
= rr
->ttl
;
1560 copy
->expiry
= rr
->expiry
;
1561 copy
->n_skip_labels_signer
= rr
->n_skip_labels_signer
;
1562 copy
->n_skip_labels_source
= rr
->n_skip_labels_source
;
1563 copy
->unparseable
= rr
->unparseable
;
1565 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1568 copy
->srv
.priority
= rr
->srv
.priority
;
1569 copy
->srv
.weight
= rr
->srv
.weight
;
1570 copy
->srv
.port
= rr
->srv
.port
;
1571 copy
->srv
.name
= strdup(rr
->srv
.name
);
1572 if (!copy
->srv
.name
)
1578 case DNS_TYPE_CNAME
:
1579 case DNS_TYPE_DNAME
:
1580 copy
->ptr
.name
= strdup(rr
->ptr
.name
);
1581 if (!copy
->ptr
.name
)
1585 case DNS_TYPE_HINFO
:
1586 copy
->hinfo
.cpu
= strdup(rr
->hinfo
.cpu
);
1587 if (!copy
->hinfo
.cpu
)
1590 copy
->hinfo
.os
= strdup(rr
->hinfo
.os
);
1591 if (!copy
->hinfo
.os
)
1597 copy
->txt
.items
= dns_txt_item_copy(rr
->txt
.items
);
1598 if (!copy
->txt
.items
)
1607 copy
->aaaa
= rr
->aaaa
;
1611 copy
->soa
.mname
= strdup(rr
->soa
.mname
);
1612 if (!copy
->soa
.mname
)
1614 copy
->soa
.rname
= strdup(rr
->soa
.rname
);
1615 if (!copy
->soa
.rname
)
1617 copy
->soa
.serial
= rr
->soa
.serial
;
1618 copy
->soa
.refresh
= rr
->soa
.refresh
;
1619 copy
->soa
.retry
= rr
->soa
.retry
;
1620 copy
->soa
.expire
= rr
->soa
.expire
;
1621 copy
->soa
.minimum
= rr
->soa
.minimum
;
1625 copy
->mx
.priority
= rr
->mx
.priority
;
1626 copy
->mx
.exchange
= strdup(rr
->mx
.exchange
);
1627 if (!copy
->mx
.exchange
)
1632 copy
->loc
= rr
->loc
;
1635 case DNS_TYPE_SSHFP
:
1636 copy
->sshfp
.algorithm
= rr
->sshfp
.algorithm
;
1637 copy
->sshfp
.fptype
= rr
->sshfp
.fptype
;
1638 copy
->sshfp
.fingerprint
= memdup(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
1639 if (!copy
->sshfp
.fingerprint
)
1641 copy
->sshfp
.fingerprint_size
= rr
->sshfp
.fingerprint_size
;
1644 case DNS_TYPE_DNSKEY
:
1645 copy
->dnskey
.flags
= rr
->dnskey
.flags
;
1646 copy
->dnskey
.protocol
= rr
->dnskey
.protocol
;
1647 copy
->dnskey
.algorithm
= rr
->dnskey
.algorithm
;
1648 copy
->dnskey
.key
= memdup(rr
->dnskey
.key
, rr
->dnskey
.key_size
);
1649 if (!copy
->dnskey
.key
)
1651 copy
->dnskey
.key_size
= rr
->dnskey
.key_size
;
1654 case DNS_TYPE_RRSIG
:
1655 copy
->rrsig
.type_covered
= rr
->rrsig
.type_covered
;
1656 copy
->rrsig
.algorithm
= rr
->rrsig
.algorithm
;
1657 copy
->rrsig
.labels
= rr
->rrsig
.labels
;
1658 copy
->rrsig
.original_ttl
= rr
->rrsig
.original_ttl
;
1659 copy
->rrsig
.expiration
= rr
->rrsig
.expiration
;
1660 copy
->rrsig
.inception
= rr
->rrsig
.inception
;
1661 copy
->rrsig
.key_tag
= rr
->rrsig
.key_tag
;
1662 copy
->rrsig
.signer
= strdup(rr
->rrsig
.signer
);
1663 if (!copy
->rrsig
.signer
)
1665 copy
->rrsig
.signature
= memdup(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
);
1666 if (!copy
->rrsig
.signature
)
1668 copy
->rrsig
.signature_size
= rr
->rrsig
.signature_size
;
1672 copy
->nsec
.next_domain_name
= strdup(rr
->nsec
.next_domain_name
);
1673 if (!copy
->nsec
.next_domain_name
)
1675 copy
->nsec
.types
= bitmap_copy(rr
->nsec
.types
);
1676 if (!copy
->nsec
.types
)
1681 copy
->ds
.key_tag
= rr
->ds
.key_tag
;
1682 copy
->ds
.algorithm
= rr
->ds
.algorithm
;
1683 copy
->ds
.digest_type
= rr
->ds
.digest_type
;
1684 copy
->ds
.digest
= memdup(rr
->ds
.digest
, rr
->ds
.digest_size
);
1685 if (!copy
->ds
.digest
)
1687 copy
->ds
.digest_size
= rr
->ds
.digest_size
;
1690 case DNS_TYPE_NSEC3
:
1691 copy
->nsec3
.algorithm
= rr
->nsec3
.algorithm
;
1692 copy
->nsec3
.flags
= rr
->nsec3
.flags
;
1693 copy
->nsec3
.iterations
= rr
->nsec3
.iterations
;
1694 copy
->nsec3
.salt
= memdup(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
);
1695 if (!copy
->nsec3
.salt
)
1697 copy
->nsec3
.salt_size
= rr
->nsec3
.salt_size
;
1698 copy
->nsec3
.next_hashed_name
= memdup(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
);
1699 if (!copy
->nsec3
.next_hashed_name_size
)
1701 copy
->nsec3
.next_hashed_name_size
= rr
->nsec3
.next_hashed_name_size
;
1702 copy
->nsec3
.types
= bitmap_copy(rr
->nsec3
.types
);
1703 if (!copy
->nsec3
.types
)
1708 copy
->tlsa
.cert_usage
= rr
->tlsa
.cert_usage
;
1709 copy
->tlsa
.selector
= rr
->tlsa
.selector
;
1710 copy
->tlsa
.matching_type
= rr
->tlsa
.matching_type
;
1711 copy
->tlsa
.data
= memdup(rr
->tlsa
.data
, rr
->tlsa
.data_size
);
1712 if (!copy
->tlsa
.data
)
1714 copy
->tlsa
.data_size
= rr
->tlsa
.data_size
;
1718 copy
->caa
.flags
= rr
->caa
.flags
;
1719 copy
->caa
.tag
= strdup(rr
->caa
.tag
);
1722 copy
->caa
.value
= memdup(rr
->caa
.value
, rr
->caa
.value_size
);
1723 if (!copy
->caa
.value
)
1725 copy
->caa
.value_size
= rr
->caa
.value_size
;
1730 copy
->generic
.data
= memdup(rr
->generic
.data
, rr
->generic
.data_size
);
1731 if (!copy
->generic
.data
)
1733 copy
->generic
.data_size
= rr
->generic
.data_size
;
1743 int dns_resource_record_clamp_ttl(DnsResourceRecord
**rr
, uint32_t max_ttl
) {
1744 DnsResourceRecord
*old_rr
, *new_rr
;
1750 if (old_rr
->key
->type
== DNS_TYPE_OPT
)
1753 new_ttl
= MIN(old_rr
->ttl
, max_ttl
);
1754 if (new_ttl
== old_rr
->ttl
)
1757 if (old_rr
->n_ref
== 1) {
1758 /* Patch in place */
1759 old_rr
->ttl
= new_ttl
;
1763 new_rr
= dns_resource_record_copy(old_rr
);
1767 new_rr
->ttl
= new_ttl
;
1769 dns_resource_record_unref(*rr
);
1775 DnsTxtItem
*dns_txt_item_free_all(DnsTxtItem
*i
) {
1784 return dns_txt_item_free_all(n
);
1787 bool dns_txt_item_equal(DnsTxtItem
*a
, DnsTxtItem
*b
) {
1798 if (a
->length
!= b
->length
)
1801 if (memcmp(a
->data
, b
->data
, a
->length
) != 0)
1804 return dns_txt_item_equal(a
->items_next
, b
->items_next
);
1807 DnsTxtItem
*dns_txt_item_copy(DnsTxtItem
*first
) {
1808 DnsTxtItem
*i
, *copy
= NULL
, *end
= NULL
;
1810 LIST_FOREACH(items
, i
, first
) {
1813 j
= memdup(i
, offsetof(DnsTxtItem
, data
) + i
->length
+ 1);
1815 dns_txt_item_free_all(copy
);
1819 LIST_INSERT_AFTER(items
, copy
, end
, j
);
1826 int dns_txt_item_new_empty(DnsTxtItem
**ret
) {
1829 /* RFC 6763, section 6.1 suggests to treat
1830 * empty TXT RRs as equivalent to a TXT record
1831 * with a single empty string. */
1833 i
= malloc0(offsetof(DnsTxtItem
, data
) + 1); /* for safety reasons we add an extra NUL byte */
1842 static const char* const dnssec_algorithm_table
[_DNSSEC_ALGORITHM_MAX_DEFINED
] = {
1843 /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
1844 [DNSSEC_ALGORITHM_RSAMD5
] = "RSAMD5",
1845 [DNSSEC_ALGORITHM_DH
] = "DH",
1846 [DNSSEC_ALGORITHM_DSA
] = "DSA",
1847 [DNSSEC_ALGORITHM_ECC
] = "ECC",
1848 [DNSSEC_ALGORITHM_RSASHA1
] = "RSASHA1",
1849 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1
] = "DSA-NSEC3-SHA1",
1850 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1
] = "RSASHA1-NSEC3-SHA1",
1851 [DNSSEC_ALGORITHM_RSASHA256
] = "RSASHA256",
1852 [DNSSEC_ALGORITHM_RSASHA512
] = "RSASHA512",
1853 [DNSSEC_ALGORITHM_ECC_GOST
] = "ECC-GOST",
1854 [DNSSEC_ALGORITHM_ECDSAP256SHA256
] = "ECDSAP256SHA256",
1855 [DNSSEC_ALGORITHM_ECDSAP384SHA384
] = "ECDSAP384SHA384",
1856 [DNSSEC_ALGORITHM_ED25519
] = "ED25519",
1857 [DNSSEC_ALGORITHM_ED448
] = "ED448",
1858 [DNSSEC_ALGORITHM_INDIRECT
] = "INDIRECT",
1859 [DNSSEC_ALGORITHM_PRIVATEDNS
] = "PRIVATEDNS",
1860 [DNSSEC_ALGORITHM_PRIVATEOID
] = "PRIVATEOID",
1862 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm
, int, 255);
1864 static const char* const dnssec_digest_table
[_DNSSEC_DIGEST_MAX_DEFINED
] = {
1865 /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
1866 [DNSSEC_DIGEST_SHA1
] = "SHA-1",
1867 [DNSSEC_DIGEST_SHA256
] = "SHA-256",
1868 [DNSSEC_DIGEST_GOST_R_34_11_94
] = "GOST_R_34.11-94",
1869 [DNSSEC_DIGEST_SHA384
] = "SHA-384",
1871 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest
, int, 255);