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
);
568 int dns_resource_record_new_address(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *name
) {
569 DnsResourceRecord
*rr
;
575 if (family
== AF_INET
) {
577 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, name
);
581 rr
->a
.in_addr
= address
->in
;
583 } else if (family
== AF_INET6
) {
585 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_AAAA
, name
);
589 rr
->aaaa
.in6_addr
= address
->in6
;
591 return -EAFNOSUPPORT
;
598 #define FIELD_EQUAL(a, b, field) \
599 ((a).field ## _size == (b).field ## _size && \
600 memcmp((a).field, (b).field, (a).field ## _size) == 0)
602 int dns_resource_record_equal(const DnsResourceRecord
*a
, const DnsResourceRecord
*b
) {
611 r
= dns_resource_key_equal(a
->key
, b
->key
);
615 if (a
->unparseable
!= b
->unparseable
)
618 switch (a
->unparseable
? _DNS_TYPE_INVALID
: a
->key
->type
) {
621 r
= dns_name_equal(a
->srv
.name
, b
->srv
.name
);
625 return a
->srv
.priority
== b
->srv
.priority
&&
626 a
->srv
.weight
== b
->srv
.weight
&&
627 a
->srv
.port
== b
->srv
.port
;
633 return dns_name_equal(a
->ptr
.name
, b
->ptr
.name
);
636 return strcaseeq(a
->hinfo
.cpu
, b
->hinfo
.cpu
) &&
637 strcaseeq(a
->hinfo
.os
, b
->hinfo
.os
);
639 case DNS_TYPE_SPF
: /* exactly the same as TXT */
641 return dns_txt_item_equal(a
->txt
.items
, b
->txt
.items
);
644 return memcmp(&a
->a
.in_addr
, &b
->a
.in_addr
, sizeof(struct in_addr
)) == 0;
647 return memcmp(&a
->aaaa
.in6_addr
, &b
->aaaa
.in6_addr
, sizeof(struct in6_addr
)) == 0;
650 r
= dns_name_equal(a
->soa
.mname
, b
->soa
.mname
);
653 r
= dns_name_equal(a
->soa
.rname
, b
->soa
.rname
);
657 return a
->soa
.serial
== b
->soa
.serial
&&
658 a
->soa
.refresh
== b
->soa
.refresh
&&
659 a
->soa
.retry
== b
->soa
.retry
&&
660 a
->soa
.expire
== b
->soa
.expire
&&
661 a
->soa
.minimum
== b
->soa
.minimum
;
664 if (a
->mx
.priority
!= b
->mx
.priority
)
667 return dns_name_equal(a
->mx
.exchange
, b
->mx
.exchange
);
670 assert(a
->loc
.version
== b
->loc
.version
);
672 return a
->loc
.size
== b
->loc
.size
&&
673 a
->loc
.horiz_pre
== b
->loc
.horiz_pre
&&
674 a
->loc
.vert_pre
== b
->loc
.vert_pre
&&
675 a
->loc
.latitude
== b
->loc
.latitude
&&
676 a
->loc
.longitude
== b
->loc
.longitude
&&
677 a
->loc
.altitude
== b
->loc
.altitude
;
680 return a
->ds
.key_tag
== b
->ds
.key_tag
&&
681 a
->ds
.algorithm
== b
->ds
.algorithm
&&
682 a
->ds
.digest_type
== b
->ds
.digest_type
&&
683 FIELD_EQUAL(a
->ds
, b
->ds
, digest
);
686 return a
->sshfp
.algorithm
== b
->sshfp
.algorithm
&&
687 a
->sshfp
.fptype
== b
->sshfp
.fptype
&&
688 FIELD_EQUAL(a
->sshfp
, b
->sshfp
, fingerprint
);
690 case DNS_TYPE_DNSKEY
:
691 return a
->dnskey
.flags
== b
->dnskey
.flags
&&
692 a
->dnskey
.protocol
== b
->dnskey
.protocol
&&
693 a
->dnskey
.algorithm
== b
->dnskey
.algorithm
&&
694 FIELD_EQUAL(a
->dnskey
, b
->dnskey
, key
);
697 /* do the fast comparisons first */
698 return a
->rrsig
.type_covered
== b
->rrsig
.type_covered
&&
699 a
->rrsig
.algorithm
== b
->rrsig
.algorithm
&&
700 a
->rrsig
.labels
== b
->rrsig
.labels
&&
701 a
->rrsig
.original_ttl
== b
->rrsig
.original_ttl
&&
702 a
->rrsig
.expiration
== b
->rrsig
.expiration
&&
703 a
->rrsig
.inception
== b
->rrsig
.inception
&&
704 a
->rrsig
.key_tag
== b
->rrsig
.key_tag
&&
705 FIELD_EQUAL(a
->rrsig
, b
->rrsig
, signature
) &&
706 dns_name_equal(a
->rrsig
.signer
, b
->rrsig
.signer
);
709 return dns_name_equal(a
->nsec
.next_domain_name
, b
->nsec
.next_domain_name
) &&
710 bitmap_equal(a
->nsec
.types
, b
->nsec
.types
);
713 return a
->nsec3
.algorithm
== b
->nsec3
.algorithm
&&
714 a
->nsec3
.flags
== b
->nsec3
.flags
&&
715 a
->nsec3
.iterations
== b
->nsec3
.iterations
&&
716 FIELD_EQUAL(a
->nsec3
, b
->nsec3
, salt
) &&
717 FIELD_EQUAL(a
->nsec3
, b
->nsec3
, next_hashed_name
) &&
718 bitmap_equal(a
->nsec3
.types
, b
->nsec3
.types
);
721 return a
->tlsa
.cert_usage
== b
->tlsa
.cert_usage
&&
722 a
->tlsa
.selector
== b
->tlsa
.selector
&&
723 a
->tlsa
.matching_type
== b
->tlsa
.matching_type
&&
724 FIELD_EQUAL(a
->tlsa
, b
->tlsa
, data
);
727 return a
->caa
.flags
== b
->caa
.flags
&&
728 streq(a
->caa
.tag
, b
->caa
.tag
) &&
729 FIELD_EQUAL(a
->caa
, b
->caa
, value
);
731 case DNS_TYPE_OPENPGPKEY
:
733 return FIELD_EQUAL(a
->generic
, b
->generic
, data
);
737 static char* format_location(uint32_t latitude
, uint32_t longitude
, uint32_t altitude
,
738 uint8_t size
, uint8_t horiz_pre
, uint8_t vert_pre
) {
740 char NS
= latitude
>= 1U<<31 ? 'N' : 'S';
741 char EW
= longitude
>= 1U<<31 ? 'E' : 'W';
743 int lat
= latitude
>= 1U<<31 ? (int) (latitude
- (1U<<31)) : (int) ((1U<<31) - latitude
);
744 int lon
= longitude
>= 1U<<31 ? (int) (longitude
- (1U<<31)) : (int) ((1U<<31) - longitude
);
745 double alt
= altitude
>= 10000000u ? altitude
- 10000000u : -(double)(10000000u - altitude
);
746 double siz
= (size
>> 4) * exp10((double) (size
& 0xF));
747 double hor
= (horiz_pre
>> 4) * exp10((double) (horiz_pre
& 0xF));
748 double ver
= (vert_pre
>> 4) * exp10((double) (vert_pre
& 0xF));
750 if (asprintf(&s
, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
753 (lat
% 60000) / 1000.,
757 (lon
% 60000) / 1000.,
768 static int format_timestamp_dns(char *buf
, size_t l
, time_t sec
) {
772 assert(l
> STRLEN("YYYYMMDDHHmmSS"));
774 if (!gmtime_r(&sec
, &tm
))
777 if (strftime(buf
, l
, "%Y%m%d%H%M%S", &tm
) <= 0)
783 static char *format_types(Bitmap
*types
) {
784 _cleanup_strv_free_
char **strv
= NULL
;
785 _cleanup_free_
char *str
= NULL
;
790 BITMAP_FOREACH(type
, types
, i
) {
791 if (dns_type_to_string(type
)) {
792 r
= strv_extend(&strv
, dns_type_to_string(type
));
798 r
= asprintf(&t
, "TYPE%u", type
);
802 r
= strv_consume(&strv
, t
);
808 str
= strv_join(strv
, " ");
812 return strjoin("( ", str
, " )");
815 static char *format_txt(DnsTxtItem
*first
) {
820 LIST_FOREACH(items
, i
, first
)
821 c
+= i
->length
* 4 + 3;
823 p
= s
= new(char, c
);
827 LIST_FOREACH(items
, i
, first
) {
835 for (j
= 0; j
< i
->length
; j
++) {
836 if (i
->data
[j
] < ' ' || i
->data
[j
] == '"' || i
->data
[j
] >= 127) {
838 *(p
++) = '0' + (i
->data
[j
] / 100);
839 *(p
++) = '0' + ((i
->data
[j
] / 10) % 10);
840 *(p
++) = '0' + (i
->data
[j
] % 10);
852 const char *dns_resource_record_to_string(DnsResourceRecord
*rr
) {
853 _cleanup_free_
char *t
= NULL
;
854 char *s
, k
[DNS_RESOURCE_KEY_STRING_MAX
];
860 return rr
->to_string
;
862 dns_resource_key_to_string(rr
->key
, k
, sizeof(k
));
864 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
867 r
= asprintf(&s
, "%s %u %u %u %s",
872 strna(rr
->srv
.name
));
881 s
= strjoin(k
, " ", rr
->ptr
.name
);
888 s
= strjoin(k
, " ", rr
->hinfo
.cpu
, " ", rr
->hinfo
.os
);
893 case DNS_TYPE_SPF
: /* exactly the same as TXT */
895 t
= format_txt(rr
->txt
.items
);
899 s
= strjoin(k
, " ", t
);
905 _cleanup_free_
char *x
= NULL
;
907 r
= in_addr_to_string(AF_INET
, (const union in_addr_union
*) &rr
->a
.in_addr
, &x
);
911 s
= strjoin(k
, " ", x
);
918 r
= in_addr_to_string(AF_INET6
, (const union in_addr_union
*) &rr
->aaaa
.in6_addr
, &t
);
922 s
= strjoin(k
, " ", t
);
928 r
= asprintf(&s
, "%s %s %s %u %u %u %u %u",
930 strna(rr
->soa
.mname
),
931 strna(rr
->soa
.rname
),
942 r
= asprintf(&s
, "%s %u %s",
951 assert(rr
->loc
.version
== 0);
953 t
= format_location(rr
->loc
.latitude
,
962 s
= strjoin(k
, " ", t
);
968 t
= hexmem(rr
->ds
.digest
, rr
->ds
.digest_size
);
972 r
= asprintf(&s
, "%s %u %u %u %s",
983 t
= hexmem(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
987 r
= asprintf(&s
, "%s %u %u %s",
996 case DNS_TYPE_DNSKEY
: {
997 _cleanup_free_
char *alg
= NULL
;
1002 key_tag
= dnssec_keytag(rr
, true);
1004 r
= dnssec_algorithm_to_string_alloc(rr
->dnskey
.algorithm
, &alg
);
1008 r
= asprintf(&s
, "%s %u %u %s %n",
1011 rr
->dnskey
.protocol
,
1017 r
= base64_append(&s
, n
,
1018 rr
->dnskey
.key
, rr
->dnskey
.key_size
,
1023 r
= asprintf(&ss
, "%s\n"
1024 " -- Flags:%s%s%s\n"
1027 rr
->dnskey
.flags
& DNSKEY_FLAG_SEP
? " SEP" : "",
1028 rr
->dnskey
.flags
& DNSKEY_FLAG_REVOKE
? " REVOKE" : "",
1029 rr
->dnskey
.flags
& DNSKEY_FLAG_ZONE_KEY
? " ZONE_KEY" : "",
1039 case DNS_TYPE_RRSIG
: {
1040 _cleanup_free_
char *alg
= NULL
;
1041 char expiration
[STRLEN("YYYYMMDDHHmmSS") + 1], inception
[STRLEN("YYYYMMDDHHmmSS") + 1];
1045 type
= dns_type_to_string(rr
->rrsig
.type_covered
);
1047 r
= dnssec_algorithm_to_string_alloc(rr
->rrsig
.algorithm
, &alg
);
1051 r
= format_timestamp_dns(expiration
, sizeof(expiration
), rr
->rrsig
.expiration
);
1055 r
= format_timestamp_dns(inception
, sizeof(inception
), rr
->rrsig
.inception
);
1060 * http://tools.ietf.org/html/rfc3597#section-5 */
1062 r
= asprintf(&s
, "%s %s%.*u %s %u %u %s %s %u %s %n",
1065 type
? 0 : 1, type
? 0u : (unsigned) rr
->rrsig
.type_covered
,
1068 rr
->rrsig
.original_ttl
,
1077 r
= base64_append(&s
, n
,
1078 rr
->rrsig
.signature
, rr
->rrsig
.signature_size
,
1087 t
= format_types(rr
->nsec
.types
);
1091 r
= asprintf(&s
, "%s %s %s",
1093 rr
->nsec
.next_domain_name
,
1099 case DNS_TYPE_NSEC3
: {
1100 _cleanup_free_
char *salt
= NULL
, *hash
= NULL
;
1102 if (rr
->nsec3
.salt_size
> 0) {
1103 salt
= hexmem(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
);
1108 hash
= base32hexmem(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, false);
1112 t
= format_types(rr
->nsec3
.types
);
1116 r
= asprintf(&s
, "%s %"PRIu8
" %"PRIu8
" %"PRIu16
" %s %s %s",
1118 rr
->nsec3
.algorithm
,
1120 rr
->nsec3
.iterations
,
1121 rr
->nsec3
.salt_size
> 0 ? salt
: "-",
1130 case DNS_TYPE_TLSA
: {
1131 const char *cert_usage
, *selector
, *matching_type
;
1133 cert_usage
= tlsa_cert_usage_to_string(rr
->tlsa
.cert_usage
);
1134 selector
= tlsa_selector_to_string(rr
->tlsa
.selector
);
1135 matching_type
= tlsa_matching_type_to_string(rr
->tlsa
.matching_type
);
1137 t
= hexmem(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
1143 " -- Cert. usage: %s\n"
1144 " -- Selector: %s\n"
1145 " -- Matching type: %s",
1147 rr
->tlsa
.cert_usage
,
1149 rr
->tlsa
.matching_type
,
1160 case DNS_TYPE_CAA
: {
1161 _cleanup_free_
char *value
;
1163 value
= octescape(rr
->caa
.value
, rr
->caa
.value_size
);
1167 r
= asprintf(&s
, "%s %u %s \"%s\"%s%s%s%.0u",
1172 rr
->caa
.flags
? "\n -- Flags:" : "",
1173 rr
->caa
.flags
& CAA_FLAG_CRITICAL
? " critical" : "",
1174 rr
->caa
.flags
& ~CAA_FLAG_CRITICAL
? " " : "",
1175 rr
->caa
.flags
& ~CAA_FLAG_CRITICAL
);
1182 case DNS_TYPE_OPENPGPKEY
: {
1185 r
= asprintf(&s
, "%s %n",
1191 r
= base64_append(&s
, n
,
1192 rr
->generic
.data
, rr
->generic
.data_size
,
1200 t
= hexmem(rr
->generic
.data
, rr
->generic
.data_size
);
1204 /* Format as documented in RFC 3597, Section 5 */
1205 r
= asprintf(&s
, "%s \\# %zu %s", k
, rr
->generic
.data_size
, t
);
1215 ssize_t
dns_resource_record_payload(DnsResourceRecord
*rr
, void **out
) {
1219 switch(rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1223 case DNS_TYPE_CNAME
:
1224 case DNS_TYPE_DNAME
:
1225 case DNS_TYPE_HINFO
:
1234 case DNS_TYPE_DNSKEY
:
1235 case DNS_TYPE_RRSIG
:
1237 case DNS_TYPE_NSEC3
:
1240 case DNS_TYPE_SSHFP
:
1241 *out
= rr
->sshfp
.fingerprint
;
1242 return rr
->sshfp
.fingerprint_size
;
1245 *out
= rr
->tlsa
.data
;
1246 return rr
->tlsa
.data_size
;
1249 case DNS_TYPE_OPENPGPKEY
:
1251 *out
= rr
->generic
.data
;
1252 return rr
->generic
.data_size
;
1256 int dns_resource_record_to_wire_format(DnsResourceRecord
*rr
, bool canonical
) {
1258 DnsPacket packet
= {
1260 .protocol
= DNS_PROTOCOL_DNS
,
1262 .refuse_compression
= true,
1263 .canonical_form
= canonical
,
1271 /* Generates the RR in wire-format, optionally in the
1272 * canonical form as discussed in the DNSSEC RFC 4034, Section
1273 * 6.2. We allocate a throw-away DnsPacket object on the stack
1274 * here, because we need some book-keeping for memory
1275 * management, and can reuse the DnsPacket serializer, that
1276 * can generate the canonical form, too, but also knows label
1277 * compression and suchlike. */
1279 if (rr
->wire_format
&& rr
->wire_format_canonical
== canonical
)
1282 r
= dns_packet_append_rr(&packet
, rr
, 0, &start
, &rds
);
1287 assert(packet
._data
);
1289 free(rr
->wire_format
);
1290 rr
->wire_format
= packet
._data
;
1291 rr
->wire_format_size
= packet
.size
;
1292 rr
->wire_format_rdata_offset
= rds
;
1293 rr
->wire_format_canonical
= canonical
;
1295 packet
._data
= NULL
;
1296 dns_packet_unref(&packet
);
1301 int dns_resource_record_signer(DnsResourceRecord
*rr
, const char **ret
) {
1308 /* Returns the RRset's signer, if it is known. */
1310 if (rr
->n_skip_labels_signer
== (unsigned) -1)
1313 n
= dns_resource_key_name(rr
->key
);
1314 r
= dns_name_skip(n
, rr
->n_skip_labels_signer
, &n
);
1324 int dns_resource_record_source(DnsResourceRecord
*rr
, const char **ret
) {
1331 /* Returns the RRset's synthesizing source, if it is known. */
1333 if (rr
->n_skip_labels_source
== (unsigned) -1)
1336 n
= dns_resource_key_name(rr
->key
);
1337 r
= dns_name_skip(n
, rr
->n_skip_labels_source
, &n
);
1347 int dns_resource_record_is_signer(DnsResourceRecord
*rr
, const char *zone
) {
1353 r
= dns_resource_record_signer(rr
, &signer
);
1357 return dns_name_equal(zone
, signer
);
1360 int dns_resource_record_is_synthetic(DnsResourceRecord
*rr
) {
1365 /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
1367 if (rr
->n_skip_labels_source
== (unsigned) -1)
1370 if (rr
->n_skip_labels_source
== 0)
1373 if (rr
->n_skip_labels_source
> 1)
1376 r
= dns_name_startswith(dns_resource_key_name(rr
->key
), "*");
1383 void dns_resource_record_hash_func(const void *i
, struct siphash
*state
) {
1384 const DnsResourceRecord
*rr
= i
;
1388 dns_resource_key_hash_func(rr
->key
, state
);
1390 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1393 siphash24_compress(&rr
->srv
.priority
, sizeof(rr
->srv
.priority
), state
);
1394 siphash24_compress(&rr
->srv
.weight
, sizeof(rr
->srv
.weight
), state
);
1395 siphash24_compress(&rr
->srv
.port
, sizeof(rr
->srv
.port
), state
);
1396 dns_name_hash_func(rr
->srv
.name
, state
);
1401 case DNS_TYPE_CNAME
:
1402 case DNS_TYPE_DNAME
:
1403 dns_name_hash_func(rr
->ptr
.name
, state
);
1406 case DNS_TYPE_HINFO
:
1407 string_hash_func(rr
->hinfo
.cpu
, state
);
1408 string_hash_func(rr
->hinfo
.os
, state
);
1412 case DNS_TYPE_SPF
: {
1415 LIST_FOREACH(items
, j
, rr
->txt
.items
) {
1416 siphash24_compress(j
->data
, j
->length
, state
);
1418 /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
1419 * followed by "". */
1420 siphash24_compress_byte(0, state
);
1426 siphash24_compress(&rr
->a
.in_addr
, sizeof(rr
->a
.in_addr
), state
);
1430 siphash24_compress(&rr
->aaaa
.in6_addr
, sizeof(rr
->aaaa
.in6_addr
), state
);
1434 dns_name_hash_func(rr
->soa
.mname
, state
);
1435 dns_name_hash_func(rr
->soa
.rname
, state
);
1436 siphash24_compress(&rr
->soa
.serial
, sizeof(rr
->soa
.serial
), state
);
1437 siphash24_compress(&rr
->soa
.refresh
, sizeof(rr
->soa
.refresh
), state
);
1438 siphash24_compress(&rr
->soa
.retry
, sizeof(rr
->soa
.retry
), state
);
1439 siphash24_compress(&rr
->soa
.expire
, sizeof(rr
->soa
.expire
), state
);
1440 siphash24_compress(&rr
->soa
.minimum
, sizeof(rr
->soa
.minimum
), state
);
1444 siphash24_compress(&rr
->mx
.priority
, sizeof(rr
->mx
.priority
), state
);
1445 dns_name_hash_func(rr
->mx
.exchange
, state
);
1449 siphash24_compress(&rr
->loc
.version
, sizeof(rr
->loc
.version
), state
);
1450 siphash24_compress(&rr
->loc
.size
, sizeof(rr
->loc
.size
), state
);
1451 siphash24_compress(&rr
->loc
.horiz_pre
, sizeof(rr
->loc
.horiz_pre
), state
);
1452 siphash24_compress(&rr
->loc
.vert_pre
, sizeof(rr
->loc
.vert_pre
), state
);
1453 siphash24_compress(&rr
->loc
.latitude
, sizeof(rr
->loc
.latitude
), state
);
1454 siphash24_compress(&rr
->loc
.longitude
, sizeof(rr
->loc
.longitude
), state
);
1455 siphash24_compress(&rr
->loc
.altitude
, sizeof(rr
->loc
.altitude
), state
);
1458 case DNS_TYPE_SSHFP
:
1459 siphash24_compress(&rr
->sshfp
.algorithm
, sizeof(rr
->sshfp
.algorithm
), state
);
1460 siphash24_compress(&rr
->sshfp
.fptype
, sizeof(rr
->sshfp
.fptype
), state
);
1461 siphash24_compress(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
, state
);
1464 case DNS_TYPE_DNSKEY
:
1465 siphash24_compress(&rr
->dnskey
.flags
, sizeof(rr
->dnskey
.flags
), state
);
1466 siphash24_compress(&rr
->dnskey
.protocol
, sizeof(rr
->dnskey
.protocol
), state
);
1467 siphash24_compress(&rr
->dnskey
.algorithm
, sizeof(rr
->dnskey
.algorithm
), state
);
1468 siphash24_compress(rr
->dnskey
.key
, rr
->dnskey
.key_size
, state
);
1471 case DNS_TYPE_RRSIG
:
1472 siphash24_compress(&rr
->rrsig
.type_covered
, sizeof(rr
->rrsig
.type_covered
), state
);
1473 siphash24_compress(&rr
->rrsig
.algorithm
, sizeof(rr
->rrsig
.algorithm
), state
);
1474 siphash24_compress(&rr
->rrsig
.labels
, sizeof(rr
->rrsig
.labels
), state
);
1475 siphash24_compress(&rr
->rrsig
.original_ttl
, sizeof(rr
->rrsig
.original_ttl
), state
);
1476 siphash24_compress(&rr
->rrsig
.expiration
, sizeof(rr
->rrsig
.expiration
), state
);
1477 siphash24_compress(&rr
->rrsig
.inception
, sizeof(rr
->rrsig
.inception
), state
);
1478 siphash24_compress(&rr
->rrsig
.key_tag
, sizeof(rr
->rrsig
.key_tag
), state
);
1479 dns_name_hash_func(rr
->rrsig
.signer
, state
);
1480 siphash24_compress(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
, state
);
1484 dns_name_hash_func(rr
->nsec
.next_domain_name
, state
);
1485 /* FIXME: we leave out the type bitmap here. Hash
1486 * would be better if we'd take it into account
1491 siphash24_compress(&rr
->ds
.key_tag
, sizeof(rr
->ds
.key_tag
), state
);
1492 siphash24_compress(&rr
->ds
.algorithm
, sizeof(rr
->ds
.algorithm
), state
);
1493 siphash24_compress(&rr
->ds
.digest_type
, sizeof(rr
->ds
.digest_type
), state
);
1494 siphash24_compress(rr
->ds
.digest
, rr
->ds
.digest_size
, state
);
1497 case DNS_TYPE_NSEC3
:
1498 siphash24_compress(&rr
->nsec3
.algorithm
, sizeof(rr
->nsec3
.algorithm
), state
);
1499 siphash24_compress(&rr
->nsec3
.flags
, sizeof(rr
->nsec3
.flags
), state
);
1500 siphash24_compress(&rr
->nsec3
.iterations
, sizeof(rr
->nsec3
.iterations
), state
);
1501 siphash24_compress(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
, state
);
1502 siphash24_compress(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, state
);
1503 /* FIXME: We leave the bitmaps out */
1507 siphash24_compress(&rr
->tlsa
.cert_usage
, sizeof(rr
->tlsa
.cert_usage
), state
);
1508 siphash24_compress(&rr
->tlsa
.selector
, sizeof(rr
->tlsa
.selector
), state
);
1509 siphash24_compress(&rr
->tlsa
.matching_type
, sizeof(rr
->tlsa
.matching_type
), state
);
1510 siphash24_compress(rr
->tlsa
.data
, rr
->tlsa
.data_size
, state
);
1514 siphash24_compress(&rr
->caa
.flags
, sizeof(rr
->caa
.flags
), state
);
1515 string_hash_func(rr
->caa
.tag
, state
);
1516 siphash24_compress(rr
->caa
.value
, rr
->caa
.value_size
, state
);
1519 case DNS_TYPE_OPENPGPKEY
:
1521 siphash24_compress(rr
->generic
.data
, rr
->generic
.data_size
, state
);
1526 static int dns_resource_record_compare_func(const void *a
, const void *b
) {
1527 const DnsResourceRecord
*x
= a
, *y
= b
;
1530 ret
= dns_resource_key_compare_func(x
->key
, y
->key
);
1534 if (dns_resource_record_equal(x
, y
))
1537 /* This is a bit dirty, we don't implement proper ordering, but
1538 * the hashtable doesn't need ordering anyway, hence we don't
1540 return x
< y
? -1 : 1;
1543 const struct hash_ops dns_resource_record_hash_ops
= {
1544 .hash
= dns_resource_record_hash_func
,
1545 .compare
= dns_resource_record_compare_func
,
1548 DnsResourceRecord
*dns_resource_record_copy(DnsResourceRecord
*rr
) {
1549 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*copy
= NULL
;
1550 DnsResourceRecord
*t
;
1554 copy
= dns_resource_record_new(rr
->key
);
1558 copy
->ttl
= rr
->ttl
;
1559 copy
->expiry
= rr
->expiry
;
1560 copy
->n_skip_labels_signer
= rr
->n_skip_labels_signer
;
1561 copy
->n_skip_labels_source
= rr
->n_skip_labels_source
;
1562 copy
->unparseable
= rr
->unparseable
;
1564 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1567 copy
->srv
.priority
= rr
->srv
.priority
;
1568 copy
->srv
.weight
= rr
->srv
.weight
;
1569 copy
->srv
.port
= rr
->srv
.port
;
1570 copy
->srv
.name
= strdup(rr
->srv
.name
);
1571 if (!copy
->srv
.name
)
1577 case DNS_TYPE_CNAME
:
1578 case DNS_TYPE_DNAME
:
1579 copy
->ptr
.name
= strdup(rr
->ptr
.name
);
1580 if (!copy
->ptr
.name
)
1584 case DNS_TYPE_HINFO
:
1585 copy
->hinfo
.cpu
= strdup(rr
->hinfo
.cpu
);
1586 if (!copy
->hinfo
.cpu
)
1589 copy
->hinfo
.os
= strdup(rr
->hinfo
.os
);
1590 if (!copy
->hinfo
.os
)
1596 copy
->txt
.items
= dns_txt_item_copy(rr
->txt
.items
);
1597 if (!copy
->txt
.items
)
1606 copy
->aaaa
= rr
->aaaa
;
1610 copy
->soa
.mname
= strdup(rr
->soa
.mname
);
1611 if (!copy
->soa
.mname
)
1613 copy
->soa
.rname
= strdup(rr
->soa
.rname
);
1614 if (!copy
->soa
.rname
)
1616 copy
->soa
.serial
= rr
->soa
.serial
;
1617 copy
->soa
.refresh
= rr
->soa
.refresh
;
1618 copy
->soa
.retry
= rr
->soa
.retry
;
1619 copy
->soa
.expire
= rr
->soa
.expire
;
1620 copy
->soa
.minimum
= rr
->soa
.minimum
;
1624 copy
->mx
.priority
= rr
->mx
.priority
;
1625 copy
->mx
.exchange
= strdup(rr
->mx
.exchange
);
1626 if (!copy
->mx
.exchange
)
1631 copy
->loc
= rr
->loc
;
1634 case DNS_TYPE_SSHFP
:
1635 copy
->sshfp
.algorithm
= rr
->sshfp
.algorithm
;
1636 copy
->sshfp
.fptype
= rr
->sshfp
.fptype
;
1637 copy
->sshfp
.fingerprint
= memdup(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
1638 if (!copy
->sshfp
.fingerprint
)
1640 copy
->sshfp
.fingerprint_size
= rr
->sshfp
.fingerprint_size
;
1643 case DNS_TYPE_DNSKEY
:
1644 copy
->dnskey
.flags
= rr
->dnskey
.flags
;
1645 copy
->dnskey
.protocol
= rr
->dnskey
.protocol
;
1646 copy
->dnskey
.algorithm
= rr
->dnskey
.algorithm
;
1647 copy
->dnskey
.key
= memdup(rr
->dnskey
.key
, rr
->dnskey
.key_size
);
1648 if (!copy
->dnskey
.key
)
1650 copy
->dnskey
.key_size
= rr
->dnskey
.key_size
;
1653 case DNS_TYPE_RRSIG
:
1654 copy
->rrsig
.type_covered
= rr
->rrsig
.type_covered
;
1655 copy
->rrsig
.algorithm
= rr
->rrsig
.algorithm
;
1656 copy
->rrsig
.labels
= rr
->rrsig
.labels
;
1657 copy
->rrsig
.original_ttl
= rr
->rrsig
.original_ttl
;
1658 copy
->rrsig
.expiration
= rr
->rrsig
.expiration
;
1659 copy
->rrsig
.inception
= rr
->rrsig
.inception
;
1660 copy
->rrsig
.key_tag
= rr
->rrsig
.key_tag
;
1661 copy
->rrsig
.signer
= strdup(rr
->rrsig
.signer
);
1662 if (!copy
->rrsig
.signer
)
1664 copy
->rrsig
.signature
= memdup(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
);
1665 if (!copy
->rrsig
.signature
)
1667 copy
->rrsig
.signature_size
= rr
->rrsig
.signature_size
;
1671 copy
->nsec
.next_domain_name
= strdup(rr
->nsec
.next_domain_name
);
1672 if (!copy
->nsec
.next_domain_name
)
1674 copy
->nsec
.types
= bitmap_copy(rr
->nsec
.types
);
1675 if (!copy
->nsec
.types
)
1680 copy
->ds
.key_tag
= rr
->ds
.key_tag
;
1681 copy
->ds
.algorithm
= rr
->ds
.algorithm
;
1682 copy
->ds
.digest_type
= rr
->ds
.digest_type
;
1683 copy
->ds
.digest
= memdup(rr
->ds
.digest
, rr
->ds
.digest_size
);
1684 if (!copy
->ds
.digest
)
1686 copy
->ds
.digest_size
= rr
->ds
.digest_size
;
1689 case DNS_TYPE_NSEC3
:
1690 copy
->nsec3
.algorithm
= rr
->nsec3
.algorithm
;
1691 copy
->nsec3
.flags
= rr
->nsec3
.flags
;
1692 copy
->nsec3
.iterations
= rr
->nsec3
.iterations
;
1693 copy
->nsec3
.salt
= memdup(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
);
1694 if (!copy
->nsec3
.salt
)
1696 copy
->nsec3
.salt_size
= rr
->nsec3
.salt_size
;
1697 copy
->nsec3
.next_hashed_name
= memdup(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
);
1698 if (!copy
->nsec3
.next_hashed_name_size
)
1700 copy
->nsec3
.next_hashed_name_size
= rr
->nsec3
.next_hashed_name_size
;
1701 copy
->nsec3
.types
= bitmap_copy(rr
->nsec3
.types
);
1702 if (!copy
->nsec3
.types
)
1707 copy
->tlsa
.cert_usage
= rr
->tlsa
.cert_usage
;
1708 copy
->tlsa
.selector
= rr
->tlsa
.selector
;
1709 copy
->tlsa
.matching_type
= rr
->tlsa
.matching_type
;
1710 copy
->tlsa
.data
= memdup(rr
->tlsa
.data
, rr
->tlsa
.data_size
);
1711 if (!copy
->tlsa
.data
)
1713 copy
->tlsa
.data_size
= rr
->tlsa
.data_size
;
1717 copy
->caa
.flags
= rr
->caa
.flags
;
1718 copy
->caa
.tag
= strdup(rr
->caa
.tag
);
1721 copy
->caa
.value
= memdup(rr
->caa
.value
, rr
->caa
.value_size
);
1722 if (!copy
->caa
.value
)
1724 copy
->caa
.value_size
= rr
->caa
.value_size
;
1729 copy
->generic
.data
= memdup(rr
->generic
.data
, rr
->generic
.data_size
);
1730 if (!copy
->generic
.data
)
1732 copy
->generic
.data_size
= rr
->generic
.data_size
;
1741 int dns_resource_record_clamp_ttl(DnsResourceRecord
**rr
, uint32_t max_ttl
) {
1742 DnsResourceRecord
*old_rr
, *new_rr
;
1748 if (old_rr
->key
->type
== DNS_TYPE_OPT
)
1751 new_ttl
= MIN(old_rr
->ttl
, max_ttl
);
1752 if (new_ttl
== old_rr
->ttl
)
1755 if (old_rr
->n_ref
== 1) {
1756 /* Patch in place */
1757 old_rr
->ttl
= new_ttl
;
1761 new_rr
= dns_resource_record_copy(old_rr
);
1765 new_rr
->ttl
= new_ttl
;
1767 dns_resource_record_unref(*rr
);
1773 DnsTxtItem
*dns_txt_item_free_all(DnsTxtItem
*i
) {
1782 return dns_txt_item_free_all(n
);
1785 bool dns_txt_item_equal(DnsTxtItem
*a
, DnsTxtItem
*b
) {
1796 if (a
->length
!= b
->length
)
1799 if (memcmp(a
->data
, b
->data
, a
->length
) != 0)
1802 return dns_txt_item_equal(a
->items_next
, b
->items_next
);
1805 DnsTxtItem
*dns_txt_item_copy(DnsTxtItem
*first
) {
1806 DnsTxtItem
*i
, *copy
= NULL
, *end
= NULL
;
1808 LIST_FOREACH(items
, i
, first
) {
1811 j
= memdup(i
, offsetof(DnsTxtItem
, data
) + i
->length
+ 1);
1813 dns_txt_item_free_all(copy
);
1817 LIST_INSERT_AFTER(items
, copy
, end
, j
);
1824 int dns_txt_item_new_empty(DnsTxtItem
**ret
) {
1827 /* RFC 6763, section 6.1 suggests to treat
1828 * empty TXT RRs as equivalent to a TXT record
1829 * with a single empty string. */
1831 i
= malloc0(offsetof(DnsTxtItem
, data
) + 1); /* for safety reasons we add an extra NUL byte */
1840 static const char* const dnssec_algorithm_table
[_DNSSEC_ALGORITHM_MAX_DEFINED
] = {
1841 /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
1842 [DNSSEC_ALGORITHM_RSAMD5
] = "RSAMD5",
1843 [DNSSEC_ALGORITHM_DH
] = "DH",
1844 [DNSSEC_ALGORITHM_DSA
] = "DSA",
1845 [DNSSEC_ALGORITHM_ECC
] = "ECC",
1846 [DNSSEC_ALGORITHM_RSASHA1
] = "RSASHA1",
1847 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1
] = "DSA-NSEC3-SHA1",
1848 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1
] = "RSASHA1-NSEC3-SHA1",
1849 [DNSSEC_ALGORITHM_RSASHA256
] = "RSASHA256",
1850 [DNSSEC_ALGORITHM_RSASHA512
] = "RSASHA512",
1851 [DNSSEC_ALGORITHM_ECC_GOST
] = "ECC-GOST",
1852 [DNSSEC_ALGORITHM_ECDSAP256SHA256
] = "ECDSAP256SHA256",
1853 [DNSSEC_ALGORITHM_ECDSAP384SHA384
] = "ECDSAP384SHA384",
1854 [DNSSEC_ALGORITHM_ED25519
] = "ED25519",
1855 [DNSSEC_ALGORITHM_ED448
] = "ED448",
1856 [DNSSEC_ALGORITHM_INDIRECT
] = "INDIRECT",
1857 [DNSSEC_ALGORITHM_PRIVATEDNS
] = "PRIVATEDNS",
1858 [DNSSEC_ALGORITHM_PRIVATEOID
] = "PRIVATEOID",
1860 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm
, int, 255);
1862 static const char* const dnssec_digest_table
[_DNSSEC_DIGEST_MAX_DEFINED
] = {
1863 /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
1864 [DNSSEC_DIGEST_SHA1
] = "SHA-1",
1865 [DNSSEC_DIGEST_SHA256
] = "SHA-256",
1866 [DNSSEC_DIGEST_GOST_R_34_11_94
] = "GOST_R_34.11-94",
1867 [DNSSEC_DIGEST_SHA384
] = "SHA-384",
1869 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest
, int, 255);