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 int dns_resource_key_equal(const DnsResourceKey
*a
, const DnsResourceKey
*b
) {
191 r
= dns_name_equal(dns_resource_key_name(a
), dns_resource_key_name(b
));
195 if (a
->class != b
->class)
198 if (a
->type
!= b
->type
)
204 int dns_resource_key_match_rr(const DnsResourceKey
*key
, DnsResourceRecord
*rr
, const char *search_domain
) {
213 /* Checks if an rr matches the specified key. If a search
214 * domain is specified, it will also be checked if the key
215 * with the search domain suffixed might match the RR. */
217 if (rr
->key
->class != key
->class && key
->class != DNS_CLASS_ANY
)
220 if (rr
->key
->type
!= key
->type
&& key
->type
!= DNS_TYPE_ANY
)
223 r
= dns_name_equal(dns_resource_key_name(rr
->key
), dns_resource_key_name(key
));
228 _cleanup_free_
char *joined
= NULL
;
230 r
= dns_name_concat(dns_resource_key_name(key
), search_domain
, &joined
);
234 return dns_name_equal(dns_resource_key_name(rr
->key
), joined
);
240 int dns_resource_key_match_cname_or_dname(const DnsResourceKey
*key
, const DnsResourceKey
*cname
, const char *search_domain
) {
246 if (cname
->class != key
->class && key
->class != DNS_CLASS_ANY
)
249 if (cname
->type
== DNS_TYPE_CNAME
)
250 r
= dns_name_equal(dns_resource_key_name(key
), dns_resource_key_name(cname
));
251 else if (cname
->type
== DNS_TYPE_DNAME
)
252 r
= dns_name_endswith(dns_resource_key_name(key
), dns_resource_key_name(cname
));
260 _cleanup_free_
char *joined
= NULL
;
262 r
= dns_name_concat(dns_resource_key_name(key
), search_domain
, &joined
);
266 if (cname
->type
== DNS_TYPE_CNAME
)
267 return dns_name_equal(joined
, dns_resource_key_name(cname
));
268 else if (cname
->type
== DNS_TYPE_DNAME
)
269 return dns_name_endswith(joined
, dns_resource_key_name(cname
));
275 int dns_resource_key_match_soa(const DnsResourceKey
*key
, const DnsResourceKey
*soa
) {
279 /* Checks whether 'soa' is a SOA record for the specified key. */
281 if (soa
->class != key
->class)
284 if (soa
->type
!= DNS_TYPE_SOA
)
287 return dns_name_endswith(dns_resource_key_name(key
), dns_resource_key_name(soa
));
290 static void dns_resource_key_hash_func(const void *i
, struct siphash
*state
) {
291 const DnsResourceKey
*k
= i
;
295 dns_name_hash_func(dns_resource_key_name(k
), state
);
296 siphash24_compress(&k
->class, sizeof(k
->class), state
);
297 siphash24_compress(&k
->type
, sizeof(k
->type
), state
);
300 static int dns_resource_key_compare_func(const void *a
, const void *b
) {
301 const DnsResourceKey
*x
= a
, *y
= b
;
304 ret
= dns_name_compare_func(dns_resource_key_name(x
), dns_resource_key_name(y
));
308 if (x
->type
< y
->type
)
310 if (x
->type
> y
->type
)
313 if (x
->class < y
->class)
315 if (x
->class > y
->class)
321 const struct hash_ops dns_resource_key_hash_ops
= {
322 .hash
= dns_resource_key_hash_func
,
323 .compare
= dns_resource_key_compare_func
326 char* dns_resource_key_to_string(const DnsResourceKey
*key
, char *buf
, size_t buf_size
) {
330 /* If we cannot convert the CLASS/TYPE into a known string,
331 use the format recommended by RFC 3597, Section 5. */
333 c
= dns_class_to_string(key
->class);
334 t
= dns_type_to_string(key
->type
);
336 snprintf(buf
, buf_size
, "%s %s%s%.0u %s%s%.0u",
337 dns_resource_key_name(key
),
338 strempty(c
), c
? "" : "CLASS", c
? 0 : key
->class,
339 strempty(t
), t
? "" : "TYPE", t
? 0 : key
->class);
344 bool dns_resource_key_reduce(DnsResourceKey
**a
, DnsResourceKey
**b
) {
348 /* Try to replace one RR key by another if they are identical, thus saving a bit of memory. Note that we do
349 * this only for RR keys, not for RRs themselves, as they carry a lot of additional metadata (where they come
350 * from, validity data, and suchlike), and cannot be replaced so easily by other RRs that have the same
351 * superficial data. */
358 /* We refuse merging const keys */
359 if ((*a
)->n_ref
== (unsigned) -1)
361 if ((*b
)->n_ref
== (unsigned) -1)
364 /* Already the same? */
368 /* Are they really identical? */
369 if (dns_resource_key_equal(*a
, *b
) <= 0)
372 /* Keep the one which already has more references. */
373 if ((*a
)->n_ref
> (*b
)->n_ref
) {
374 dns_resource_key_unref(*b
);
375 *b
= dns_resource_key_ref(*a
);
377 dns_resource_key_unref(*a
);
378 *a
= dns_resource_key_ref(*b
);
384 DnsResourceRecord
* dns_resource_record_new(DnsResourceKey
*key
) {
385 DnsResourceRecord
*rr
;
387 rr
= new0(DnsResourceRecord
, 1);
392 rr
->key
= dns_resource_key_ref(key
);
393 rr
->expiry
= USEC_INFINITY
;
394 rr
->n_skip_labels_signer
= rr
->n_skip_labels_source
= (unsigned) -1;
399 DnsResourceRecord
* dns_resource_record_new_full(uint16_t class, uint16_t type
, const char *name
) {
400 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
402 key
= dns_resource_key_new(class, type
, name
);
406 return dns_resource_record_new(key
);
409 DnsResourceRecord
* dns_resource_record_ref(DnsResourceRecord
*rr
) {
413 assert(rr
->n_ref
> 0);
419 DnsResourceRecord
* dns_resource_record_unref(DnsResourceRecord
*rr
) {
423 assert(rr
->n_ref
> 0);
431 switch(rr
->key
->type
) {
451 dns_txt_item_free_all(rr
->txt
.items
);
460 free(rr
->mx
.exchange
);
468 free(rr
->sshfp
.fingerprint
);
471 case DNS_TYPE_DNSKEY
:
472 free(rr
->dnskey
.key
);
476 free(rr
->rrsig
.signer
);
477 free(rr
->rrsig
.signature
);
481 free(rr
->nsec
.next_domain_name
);
482 bitmap_free(rr
->nsec
.types
);
486 free(rr
->nsec3
.next_hashed_name
);
487 free(rr
->nsec3
.salt
);
488 bitmap_free(rr
->nsec3
.types
);
505 case DNS_TYPE_OPENPGPKEY
:
507 free(rr
->generic
.data
);
510 free(rr
->wire_format
);
511 dns_resource_key_unref(rr
->key
);
518 int dns_resource_record_new_reverse(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *hostname
) {
519 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
520 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
521 _cleanup_free_
char *ptr
= NULL
;
528 r
= dns_name_reverse(family
, address
, &ptr
);
532 key
= dns_resource_key_new_consume(DNS_CLASS_IN
, DNS_TYPE_PTR
, ptr
);
538 rr
= dns_resource_record_new(key
);
542 rr
->ptr
.name
= strdup(hostname
);
552 int dns_resource_record_new_address(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *name
) {
553 DnsResourceRecord
*rr
;
559 if (family
== AF_INET
) {
561 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, name
);
565 rr
->a
.in_addr
= address
->in
;
567 } else if (family
== AF_INET6
) {
569 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_AAAA
, name
);
573 rr
->aaaa
.in6_addr
= address
->in6
;
575 return -EAFNOSUPPORT
;
582 #define FIELD_EQUAL(a, b, field) \
583 ((a).field ## _size == (b).field ## _size && \
584 memcmp((a).field, (b).field, (a).field ## _size) == 0)
586 int dns_resource_record_equal(const DnsResourceRecord
*a
, const DnsResourceRecord
*b
) {
595 r
= dns_resource_key_equal(a
->key
, b
->key
);
599 if (a
->unparseable
!= b
->unparseable
)
602 switch (a
->unparseable
? _DNS_TYPE_INVALID
: a
->key
->type
) {
605 r
= dns_name_equal(a
->srv
.name
, b
->srv
.name
);
609 return a
->srv
.priority
== b
->srv
.priority
&&
610 a
->srv
.weight
== b
->srv
.weight
&&
611 a
->srv
.port
== b
->srv
.port
;
617 return dns_name_equal(a
->ptr
.name
, b
->ptr
.name
);
620 return strcaseeq(a
->hinfo
.cpu
, b
->hinfo
.cpu
) &&
621 strcaseeq(a
->hinfo
.os
, b
->hinfo
.os
);
623 case DNS_TYPE_SPF
: /* exactly the same as TXT */
625 return dns_txt_item_equal(a
->txt
.items
, b
->txt
.items
);
628 return memcmp(&a
->a
.in_addr
, &b
->a
.in_addr
, sizeof(struct in_addr
)) == 0;
631 return memcmp(&a
->aaaa
.in6_addr
, &b
->aaaa
.in6_addr
, sizeof(struct in6_addr
)) == 0;
634 r
= dns_name_equal(a
->soa
.mname
, b
->soa
.mname
);
637 r
= dns_name_equal(a
->soa
.rname
, b
->soa
.rname
);
641 return a
->soa
.serial
== b
->soa
.serial
&&
642 a
->soa
.refresh
== b
->soa
.refresh
&&
643 a
->soa
.retry
== b
->soa
.retry
&&
644 a
->soa
.expire
== b
->soa
.expire
&&
645 a
->soa
.minimum
== b
->soa
.minimum
;
648 if (a
->mx
.priority
!= b
->mx
.priority
)
651 return dns_name_equal(a
->mx
.exchange
, b
->mx
.exchange
);
654 assert(a
->loc
.version
== b
->loc
.version
);
656 return a
->loc
.size
== b
->loc
.size
&&
657 a
->loc
.horiz_pre
== b
->loc
.horiz_pre
&&
658 a
->loc
.vert_pre
== b
->loc
.vert_pre
&&
659 a
->loc
.latitude
== b
->loc
.latitude
&&
660 a
->loc
.longitude
== b
->loc
.longitude
&&
661 a
->loc
.altitude
== b
->loc
.altitude
;
664 return a
->ds
.key_tag
== b
->ds
.key_tag
&&
665 a
->ds
.algorithm
== b
->ds
.algorithm
&&
666 a
->ds
.digest_type
== b
->ds
.digest_type
&&
667 FIELD_EQUAL(a
->ds
, b
->ds
, digest
);
670 return a
->sshfp
.algorithm
== b
->sshfp
.algorithm
&&
671 a
->sshfp
.fptype
== b
->sshfp
.fptype
&&
672 FIELD_EQUAL(a
->sshfp
, b
->sshfp
, fingerprint
);
674 case DNS_TYPE_DNSKEY
:
675 return a
->dnskey
.flags
== b
->dnskey
.flags
&&
676 a
->dnskey
.protocol
== b
->dnskey
.protocol
&&
677 a
->dnskey
.algorithm
== b
->dnskey
.algorithm
&&
678 FIELD_EQUAL(a
->dnskey
, b
->dnskey
, key
);
681 /* do the fast comparisons first */
682 return a
->rrsig
.type_covered
== b
->rrsig
.type_covered
&&
683 a
->rrsig
.algorithm
== b
->rrsig
.algorithm
&&
684 a
->rrsig
.labels
== b
->rrsig
.labels
&&
685 a
->rrsig
.original_ttl
== b
->rrsig
.original_ttl
&&
686 a
->rrsig
.expiration
== b
->rrsig
.expiration
&&
687 a
->rrsig
.inception
== b
->rrsig
.inception
&&
688 a
->rrsig
.key_tag
== b
->rrsig
.key_tag
&&
689 FIELD_EQUAL(a
->rrsig
, b
->rrsig
, signature
) &&
690 dns_name_equal(a
->rrsig
.signer
, b
->rrsig
.signer
);
693 return dns_name_equal(a
->nsec
.next_domain_name
, b
->nsec
.next_domain_name
) &&
694 bitmap_equal(a
->nsec
.types
, b
->nsec
.types
);
697 return a
->nsec3
.algorithm
== b
->nsec3
.algorithm
&&
698 a
->nsec3
.flags
== b
->nsec3
.flags
&&
699 a
->nsec3
.iterations
== b
->nsec3
.iterations
&&
700 FIELD_EQUAL(a
->nsec3
, b
->nsec3
, salt
) &&
701 FIELD_EQUAL(a
->nsec3
, b
->nsec3
, next_hashed_name
) &&
702 bitmap_equal(a
->nsec3
.types
, b
->nsec3
.types
);
705 return a
->tlsa
.cert_usage
== b
->tlsa
.cert_usage
&&
706 a
->tlsa
.selector
== b
->tlsa
.selector
&&
707 a
->tlsa
.matching_type
== b
->tlsa
.matching_type
&&
708 FIELD_EQUAL(a
->tlsa
, b
->tlsa
, data
);
711 return a
->caa
.flags
== b
->caa
.flags
&&
712 streq(a
->caa
.tag
, b
->caa
.tag
) &&
713 FIELD_EQUAL(a
->caa
, b
->caa
, value
);
715 case DNS_TYPE_OPENPGPKEY
:
717 return FIELD_EQUAL(a
->generic
, b
->generic
, data
);
721 static char* format_location(uint32_t latitude
, uint32_t longitude
, uint32_t altitude
,
722 uint8_t size
, uint8_t horiz_pre
, uint8_t vert_pre
) {
724 char NS
= latitude
>= 1U<<31 ? 'N' : 'S';
725 char EW
= longitude
>= 1U<<31 ? 'E' : 'W';
727 int lat
= latitude
>= 1U<<31 ? (int) (latitude
- (1U<<31)) : (int) ((1U<<31) - latitude
);
728 int lon
= longitude
>= 1U<<31 ? (int) (longitude
- (1U<<31)) : (int) ((1U<<31) - longitude
);
729 double alt
= altitude
>= 10000000u ? altitude
- 10000000u : -(double)(10000000u - altitude
);
730 double siz
= (size
>> 4) * exp10((double) (size
& 0xF));
731 double hor
= (horiz_pre
>> 4) * exp10((double) (horiz_pre
& 0xF));
732 double ver
= (vert_pre
>> 4) * exp10((double) (vert_pre
& 0xF));
734 if (asprintf(&s
, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
737 (lat
% 60000) / 1000.,
741 (lon
% 60000) / 1000.,
752 static int format_timestamp_dns(char *buf
, size_t l
, time_t sec
) {
756 assert(l
> strlen("YYYYMMDDHHmmSS"));
758 if (!gmtime_r(&sec
, &tm
))
761 if (strftime(buf
, l
, "%Y%m%d%H%M%S", &tm
) <= 0)
767 static char *format_types(Bitmap
*types
) {
768 _cleanup_strv_free_
char **strv
= NULL
;
769 _cleanup_free_
char *str
= NULL
;
774 BITMAP_FOREACH(type
, types
, i
) {
775 if (dns_type_to_string(type
)) {
776 r
= strv_extend(&strv
, dns_type_to_string(type
));
782 r
= asprintf(&t
, "TYPE%u", type
);
786 r
= strv_consume(&strv
, t
);
792 str
= strv_join(strv
, " ");
796 return strjoin("( ", str
, " )");
799 static char *format_txt(DnsTxtItem
*first
) {
804 LIST_FOREACH(items
, i
, first
)
805 c
+= i
->length
* 4 + 3;
807 p
= s
= new(char, c
);
811 LIST_FOREACH(items
, i
, first
) {
819 for (j
= 0; j
< i
->length
; j
++) {
820 if (i
->data
[j
] < ' ' || i
->data
[j
] == '"' || i
->data
[j
] >= 127) {
822 *(p
++) = '0' + (i
->data
[j
] / 100);
823 *(p
++) = '0' + ((i
->data
[j
] / 10) % 10);
824 *(p
++) = '0' + (i
->data
[j
] % 10);
836 const char *dns_resource_record_to_string(DnsResourceRecord
*rr
) {
837 _cleanup_free_
char *t
= NULL
;
838 char *s
, k
[DNS_RESOURCE_KEY_STRING_MAX
];
844 return rr
->to_string
;
846 dns_resource_key_to_string(rr
->key
, k
, sizeof(k
));
848 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
851 r
= asprintf(&s
, "%s %u %u %u %s",
856 strna(rr
->srv
.name
));
865 s
= strjoin(k
, " ", rr
->ptr
.name
);
872 s
= strjoin(k
, " ", rr
->hinfo
.cpu
, " ", rr
->hinfo
.os
);
877 case DNS_TYPE_SPF
: /* exactly the same as TXT */
879 t
= format_txt(rr
->txt
.items
);
883 s
= strjoin(k
, " ", t
);
889 _cleanup_free_
char *x
= NULL
;
891 r
= in_addr_to_string(AF_INET
, (const union in_addr_union
*) &rr
->a
.in_addr
, &x
);
895 s
= strjoin(k
, " ", x
);
902 r
= in_addr_to_string(AF_INET6
, (const union in_addr_union
*) &rr
->aaaa
.in6_addr
, &t
);
906 s
= strjoin(k
, " ", t
);
912 r
= asprintf(&s
, "%s %s %s %u %u %u %u %u",
914 strna(rr
->soa
.mname
),
915 strna(rr
->soa
.rname
),
926 r
= asprintf(&s
, "%s %u %s",
935 assert(rr
->loc
.version
== 0);
937 t
= format_location(rr
->loc
.latitude
,
946 s
= strjoin(k
, " ", t
);
952 t
= hexmem(rr
->ds
.digest
, rr
->ds
.digest_size
);
956 r
= asprintf(&s
, "%s %u %u %u %s",
967 t
= hexmem(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
971 r
= asprintf(&s
, "%s %u %u %s",
980 case DNS_TYPE_DNSKEY
: {
981 _cleanup_free_
char *alg
= NULL
;
986 key_tag
= dnssec_keytag(rr
, true);
988 r
= dnssec_algorithm_to_string_alloc(rr
->dnskey
.algorithm
, &alg
);
992 r
= asprintf(&s
, "%s %u %u %s %n",
1001 r
= base64_append(&s
, n
,
1002 rr
->dnskey
.key
, rr
->dnskey
.key_size
,
1007 r
= asprintf(&ss
, "%s\n"
1008 " -- Flags:%s%s%s\n"
1011 rr
->dnskey
.flags
& DNSKEY_FLAG_SEP
? " SEP" : "",
1012 rr
->dnskey
.flags
& DNSKEY_FLAG_REVOKE
? " REVOKE" : "",
1013 rr
->dnskey
.flags
& DNSKEY_FLAG_ZONE_KEY
? " ZONE_KEY" : "",
1023 case DNS_TYPE_RRSIG
: {
1024 _cleanup_free_
char *alg
= NULL
;
1025 char expiration
[strlen("YYYYMMDDHHmmSS") + 1], inception
[strlen("YYYYMMDDHHmmSS") + 1];
1029 type
= dns_type_to_string(rr
->rrsig
.type_covered
);
1031 r
= dnssec_algorithm_to_string_alloc(rr
->rrsig
.algorithm
, &alg
);
1035 r
= format_timestamp_dns(expiration
, sizeof(expiration
), rr
->rrsig
.expiration
);
1039 r
= format_timestamp_dns(inception
, sizeof(inception
), rr
->rrsig
.inception
);
1044 * http://tools.ietf.org/html/rfc3597#section-5 */
1046 r
= asprintf(&s
, "%s %s%.*u %s %u %u %s %s %u %s %n",
1049 type
? 0 : 1, type
? 0u : (unsigned) rr
->rrsig
.type_covered
,
1052 rr
->rrsig
.original_ttl
,
1061 r
= base64_append(&s
, n
,
1062 rr
->rrsig
.signature
, rr
->rrsig
.signature_size
,
1071 t
= format_types(rr
->nsec
.types
);
1075 r
= asprintf(&s
, "%s %s %s",
1077 rr
->nsec
.next_domain_name
,
1083 case DNS_TYPE_NSEC3
: {
1084 _cleanup_free_
char *salt
= NULL
, *hash
= NULL
;
1086 if (rr
->nsec3
.salt_size
> 0) {
1087 salt
= hexmem(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
);
1092 hash
= base32hexmem(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, false);
1096 t
= format_types(rr
->nsec3
.types
);
1100 r
= asprintf(&s
, "%s %"PRIu8
" %"PRIu8
" %"PRIu16
" %s %s %s",
1102 rr
->nsec3
.algorithm
,
1104 rr
->nsec3
.iterations
,
1105 rr
->nsec3
.salt_size
> 0 ? salt
: "-",
1114 case DNS_TYPE_TLSA
: {
1115 const char *cert_usage
, *selector
, *matching_type
;
1117 cert_usage
= tlsa_cert_usage_to_string(rr
->tlsa
.cert_usage
);
1118 selector
= tlsa_selector_to_string(rr
->tlsa
.selector
);
1119 matching_type
= tlsa_matching_type_to_string(rr
->tlsa
.matching_type
);
1121 t
= hexmem(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
1127 " -- Cert. usage: %s\n"
1128 " -- Selector: %s\n"
1129 " -- Matching type: %s",
1131 rr
->tlsa
.cert_usage
,
1133 rr
->tlsa
.matching_type
,
1144 case DNS_TYPE_CAA
: {
1145 _cleanup_free_
char *value
;
1147 value
= octescape(rr
->caa
.value
, rr
->caa
.value_size
);
1151 r
= asprintf(&s
, "%s %u %s \"%s\"%s%s%s%.0u",
1156 rr
->caa
.flags
? "\n -- Flags:" : "",
1157 rr
->caa
.flags
& CAA_FLAG_CRITICAL
? " critical" : "",
1158 rr
->caa
.flags
& ~CAA_FLAG_CRITICAL
? " " : "",
1159 rr
->caa
.flags
& ~CAA_FLAG_CRITICAL
);
1166 case DNS_TYPE_OPENPGPKEY
: {
1169 r
= asprintf(&s
, "%s %n",
1175 r
= base64_append(&s
, n
,
1176 rr
->generic
.data
, rr
->generic
.data_size
,
1184 t
= hexmem(rr
->generic
.data
, rr
->generic
.data_size
);
1188 /* Format as documented in RFC 3597, Section 5 */
1189 r
= asprintf(&s
, "%s \\# %zu %s", k
, rr
->generic
.data_size
, t
);
1199 ssize_t
dns_resource_record_payload(DnsResourceRecord
*rr
, void **out
) {
1203 switch(rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1207 case DNS_TYPE_CNAME
:
1208 case DNS_TYPE_DNAME
:
1209 case DNS_TYPE_HINFO
:
1218 case DNS_TYPE_DNSKEY
:
1219 case DNS_TYPE_RRSIG
:
1221 case DNS_TYPE_NSEC3
:
1224 case DNS_TYPE_SSHFP
:
1225 *out
= rr
->sshfp
.fingerprint
;
1226 return rr
->sshfp
.fingerprint_size
;
1229 *out
= rr
->tlsa
.data
;
1230 return rr
->tlsa
.data_size
;
1233 case DNS_TYPE_OPENPGPKEY
:
1235 *out
= rr
->generic
.data
;
1236 return rr
->generic
.data_size
;
1240 int dns_resource_record_to_wire_format(DnsResourceRecord
*rr
, bool canonical
) {
1242 DnsPacket packet
= {
1244 .protocol
= DNS_PROTOCOL_DNS
,
1246 .refuse_compression
= true,
1247 .canonical_form
= canonical
,
1255 /* Generates the RR in wire-format, optionally in the
1256 * canonical form as discussed in the DNSSEC RFC 4034, Section
1257 * 6.2. We allocate a throw-away DnsPacket object on the stack
1258 * here, because we need some book-keeping for memory
1259 * management, and can reuse the DnsPacket serializer, that
1260 * can generate the canonical form, too, but also knows label
1261 * compression and suchlike. */
1263 if (rr
->wire_format
&& rr
->wire_format_canonical
== canonical
)
1266 r
= dns_packet_append_rr(&packet
, rr
, 0, &start
, &rds
);
1271 assert(packet
._data
);
1273 free(rr
->wire_format
);
1274 rr
->wire_format
= packet
._data
;
1275 rr
->wire_format_size
= packet
.size
;
1276 rr
->wire_format_rdata_offset
= rds
;
1277 rr
->wire_format_canonical
= canonical
;
1279 packet
._data
= NULL
;
1280 dns_packet_unref(&packet
);
1285 int dns_resource_record_signer(DnsResourceRecord
*rr
, const char **ret
) {
1292 /* Returns the RRset's signer, if it is known. */
1294 if (rr
->n_skip_labels_signer
== (unsigned) -1)
1297 n
= dns_resource_key_name(rr
->key
);
1298 r
= dns_name_skip(n
, rr
->n_skip_labels_signer
, &n
);
1308 int dns_resource_record_source(DnsResourceRecord
*rr
, const char **ret
) {
1315 /* Returns the RRset's synthesizing source, if it is known. */
1317 if (rr
->n_skip_labels_source
== (unsigned) -1)
1320 n
= dns_resource_key_name(rr
->key
);
1321 r
= dns_name_skip(n
, rr
->n_skip_labels_source
, &n
);
1331 int dns_resource_record_is_signer(DnsResourceRecord
*rr
, const char *zone
) {
1337 r
= dns_resource_record_signer(rr
, &signer
);
1341 return dns_name_equal(zone
, signer
);
1344 int dns_resource_record_is_synthetic(DnsResourceRecord
*rr
) {
1349 /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
1351 if (rr
->n_skip_labels_source
== (unsigned) -1)
1354 if (rr
->n_skip_labels_source
== 0)
1357 if (rr
->n_skip_labels_source
> 1)
1360 r
= dns_name_startswith(dns_resource_key_name(rr
->key
), "*");
1367 void dns_resource_record_hash_func(const void *i
, struct siphash
*state
) {
1368 const DnsResourceRecord
*rr
= i
;
1372 dns_resource_key_hash_func(rr
->key
, state
);
1374 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1377 siphash24_compress(&rr
->srv
.priority
, sizeof(rr
->srv
.priority
), state
);
1378 siphash24_compress(&rr
->srv
.weight
, sizeof(rr
->srv
.weight
), state
);
1379 siphash24_compress(&rr
->srv
.port
, sizeof(rr
->srv
.port
), state
);
1380 dns_name_hash_func(rr
->srv
.name
, state
);
1385 case DNS_TYPE_CNAME
:
1386 case DNS_TYPE_DNAME
:
1387 dns_name_hash_func(rr
->ptr
.name
, state
);
1390 case DNS_TYPE_HINFO
:
1391 string_hash_func(rr
->hinfo
.cpu
, state
);
1392 string_hash_func(rr
->hinfo
.os
, state
);
1396 case DNS_TYPE_SPF
: {
1399 LIST_FOREACH(items
, j
, rr
->txt
.items
) {
1400 siphash24_compress(j
->data
, j
->length
, state
);
1402 /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
1403 * followed by "". */
1404 siphash24_compress_byte(0, state
);
1410 siphash24_compress(&rr
->a
.in_addr
, sizeof(rr
->a
.in_addr
), state
);
1414 siphash24_compress(&rr
->aaaa
.in6_addr
, sizeof(rr
->aaaa
.in6_addr
), state
);
1418 dns_name_hash_func(rr
->soa
.mname
, state
);
1419 dns_name_hash_func(rr
->soa
.rname
, state
);
1420 siphash24_compress(&rr
->soa
.serial
, sizeof(rr
->soa
.serial
), state
);
1421 siphash24_compress(&rr
->soa
.refresh
, sizeof(rr
->soa
.refresh
), state
);
1422 siphash24_compress(&rr
->soa
.retry
, sizeof(rr
->soa
.retry
), state
);
1423 siphash24_compress(&rr
->soa
.expire
, sizeof(rr
->soa
.expire
), state
);
1424 siphash24_compress(&rr
->soa
.minimum
, sizeof(rr
->soa
.minimum
), state
);
1428 siphash24_compress(&rr
->mx
.priority
, sizeof(rr
->mx
.priority
), state
);
1429 dns_name_hash_func(rr
->mx
.exchange
, state
);
1433 siphash24_compress(&rr
->loc
.version
, sizeof(rr
->loc
.version
), state
);
1434 siphash24_compress(&rr
->loc
.size
, sizeof(rr
->loc
.size
), state
);
1435 siphash24_compress(&rr
->loc
.horiz_pre
, sizeof(rr
->loc
.horiz_pre
), state
);
1436 siphash24_compress(&rr
->loc
.vert_pre
, sizeof(rr
->loc
.vert_pre
), state
);
1437 siphash24_compress(&rr
->loc
.latitude
, sizeof(rr
->loc
.latitude
), state
);
1438 siphash24_compress(&rr
->loc
.longitude
, sizeof(rr
->loc
.longitude
), state
);
1439 siphash24_compress(&rr
->loc
.altitude
, sizeof(rr
->loc
.altitude
), state
);
1442 case DNS_TYPE_SSHFP
:
1443 siphash24_compress(&rr
->sshfp
.algorithm
, sizeof(rr
->sshfp
.algorithm
), state
);
1444 siphash24_compress(&rr
->sshfp
.fptype
, sizeof(rr
->sshfp
.fptype
), state
);
1445 siphash24_compress(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
, state
);
1448 case DNS_TYPE_DNSKEY
:
1449 siphash24_compress(&rr
->dnskey
.flags
, sizeof(rr
->dnskey
.flags
), state
);
1450 siphash24_compress(&rr
->dnskey
.protocol
, sizeof(rr
->dnskey
.protocol
), state
);
1451 siphash24_compress(&rr
->dnskey
.algorithm
, sizeof(rr
->dnskey
.algorithm
), state
);
1452 siphash24_compress(rr
->dnskey
.key
, rr
->dnskey
.key_size
, state
);
1455 case DNS_TYPE_RRSIG
:
1456 siphash24_compress(&rr
->rrsig
.type_covered
, sizeof(rr
->rrsig
.type_covered
), state
);
1457 siphash24_compress(&rr
->rrsig
.algorithm
, sizeof(rr
->rrsig
.algorithm
), state
);
1458 siphash24_compress(&rr
->rrsig
.labels
, sizeof(rr
->rrsig
.labels
), state
);
1459 siphash24_compress(&rr
->rrsig
.original_ttl
, sizeof(rr
->rrsig
.original_ttl
), state
);
1460 siphash24_compress(&rr
->rrsig
.expiration
, sizeof(rr
->rrsig
.expiration
), state
);
1461 siphash24_compress(&rr
->rrsig
.inception
, sizeof(rr
->rrsig
.inception
), state
);
1462 siphash24_compress(&rr
->rrsig
.key_tag
, sizeof(rr
->rrsig
.key_tag
), state
);
1463 dns_name_hash_func(rr
->rrsig
.signer
, state
);
1464 siphash24_compress(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
, state
);
1468 dns_name_hash_func(rr
->nsec
.next_domain_name
, state
);
1469 /* FIXME: we leave out the type bitmap here. Hash
1470 * would be better if we'd take it into account
1475 siphash24_compress(&rr
->ds
.key_tag
, sizeof(rr
->ds
.key_tag
), state
);
1476 siphash24_compress(&rr
->ds
.algorithm
, sizeof(rr
->ds
.algorithm
), state
);
1477 siphash24_compress(&rr
->ds
.digest_type
, sizeof(rr
->ds
.digest_type
), state
);
1478 siphash24_compress(rr
->ds
.digest
, rr
->ds
.digest_size
, state
);
1481 case DNS_TYPE_NSEC3
:
1482 siphash24_compress(&rr
->nsec3
.algorithm
, sizeof(rr
->nsec3
.algorithm
), state
);
1483 siphash24_compress(&rr
->nsec3
.flags
, sizeof(rr
->nsec3
.flags
), state
);
1484 siphash24_compress(&rr
->nsec3
.iterations
, sizeof(rr
->nsec3
.iterations
), state
);
1485 siphash24_compress(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
, state
);
1486 siphash24_compress(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, state
);
1487 /* FIXME: We leave the bitmaps out */
1491 siphash24_compress(&rr
->tlsa
.cert_usage
, sizeof(rr
->tlsa
.cert_usage
), state
);
1492 siphash24_compress(&rr
->tlsa
.selector
, sizeof(rr
->tlsa
.selector
), state
);
1493 siphash24_compress(&rr
->tlsa
.matching_type
, sizeof(rr
->tlsa
.matching_type
), state
);
1494 siphash24_compress(rr
->tlsa
.data
, rr
->tlsa
.data_size
, state
);
1498 siphash24_compress(&rr
->caa
.flags
, sizeof(rr
->caa
.flags
), state
);
1499 string_hash_func(rr
->caa
.tag
, state
);
1500 siphash24_compress(rr
->caa
.value
, rr
->caa
.value_size
, state
);
1503 case DNS_TYPE_OPENPGPKEY
:
1505 siphash24_compress(rr
->generic
.data
, rr
->generic
.data_size
, state
);
1510 static int dns_resource_record_compare_func(const void *a
, const void *b
) {
1511 const DnsResourceRecord
*x
= a
, *y
= b
;
1514 ret
= dns_resource_key_compare_func(x
->key
, y
->key
);
1518 if (dns_resource_record_equal(x
, y
))
1521 /* This is a bit dirty, we don't implement proper ordering, but
1522 * the hashtable doesn't need ordering anyway, hence we don't
1524 return x
< y
? -1 : 1;
1527 const struct hash_ops dns_resource_record_hash_ops
= {
1528 .hash
= dns_resource_record_hash_func
,
1529 .compare
= dns_resource_record_compare_func
,
1532 DnsResourceRecord
*dns_resource_record_copy(DnsResourceRecord
*rr
) {
1533 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*copy
= NULL
;
1534 DnsResourceRecord
*t
;
1538 copy
= dns_resource_record_new(rr
->key
);
1542 copy
->ttl
= rr
->ttl
;
1543 copy
->expiry
= rr
->expiry
;
1544 copy
->n_skip_labels_signer
= rr
->n_skip_labels_signer
;
1545 copy
->n_skip_labels_source
= rr
->n_skip_labels_source
;
1546 copy
->unparseable
= rr
->unparseable
;
1548 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1551 copy
->srv
.priority
= rr
->srv
.priority
;
1552 copy
->srv
.weight
= rr
->srv
.weight
;
1553 copy
->srv
.port
= rr
->srv
.port
;
1554 copy
->srv
.name
= strdup(rr
->srv
.name
);
1555 if (!copy
->srv
.name
)
1561 case DNS_TYPE_CNAME
:
1562 case DNS_TYPE_DNAME
:
1563 copy
->ptr
.name
= strdup(rr
->ptr
.name
);
1564 if (!copy
->ptr
.name
)
1568 case DNS_TYPE_HINFO
:
1569 copy
->hinfo
.cpu
= strdup(rr
->hinfo
.cpu
);
1570 if (!copy
->hinfo
.cpu
)
1573 copy
->hinfo
.os
= strdup(rr
->hinfo
.os
);
1574 if (!copy
->hinfo
.os
)
1580 copy
->txt
.items
= dns_txt_item_copy(rr
->txt
.items
);
1581 if (!copy
->txt
.items
)
1590 copy
->aaaa
= rr
->aaaa
;
1594 copy
->soa
.mname
= strdup(rr
->soa
.mname
);
1595 if (!copy
->soa
.mname
)
1597 copy
->soa
.rname
= strdup(rr
->soa
.rname
);
1598 if (!copy
->soa
.rname
)
1600 copy
->soa
.serial
= rr
->soa
.serial
;
1601 copy
->soa
.refresh
= rr
->soa
.refresh
;
1602 copy
->soa
.retry
= rr
->soa
.retry
;
1603 copy
->soa
.expire
= rr
->soa
.expire
;
1604 copy
->soa
.minimum
= rr
->soa
.minimum
;
1608 copy
->mx
.priority
= rr
->mx
.priority
;
1609 copy
->mx
.exchange
= strdup(rr
->mx
.exchange
);
1610 if (!copy
->mx
.exchange
)
1615 copy
->loc
= rr
->loc
;
1618 case DNS_TYPE_SSHFP
:
1619 copy
->sshfp
.algorithm
= rr
->sshfp
.algorithm
;
1620 copy
->sshfp
.fptype
= rr
->sshfp
.fptype
;
1621 copy
->sshfp
.fingerprint
= memdup(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
1622 if (!copy
->sshfp
.fingerprint
)
1624 copy
->sshfp
.fingerprint_size
= rr
->sshfp
.fingerprint_size
;
1627 case DNS_TYPE_DNSKEY
:
1628 copy
->dnskey
.flags
= rr
->dnskey
.flags
;
1629 copy
->dnskey
.protocol
= rr
->dnskey
.protocol
;
1630 copy
->dnskey
.algorithm
= rr
->dnskey
.algorithm
;
1631 copy
->dnskey
.key
= memdup(rr
->dnskey
.key
, rr
->dnskey
.key_size
);
1632 if (!copy
->dnskey
.key
)
1634 copy
->dnskey
.key_size
= rr
->dnskey
.key_size
;
1637 case DNS_TYPE_RRSIG
:
1638 copy
->rrsig
.type_covered
= rr
->rrsig
.type_covered
;
1639 copy
->rrsig
.algorithm
= rr
->rrsig
.algorithm
;
1640 copy
->rrsig
.labels
= rr
->rrsig
.labels
;
1641 copy
->rrsig
.original_ttl
= rr
->rrsig
.original_ttl
;
1642 copy
->rrsig
.expiration
= rr
->rrsig
.expiration
;
1643 copy
->rrsig
.inception
= rr
->rrsig
.inception
;
1644 copy
->rrsig
.key_tag
= rr
->rrsig
.key_tag
;
1645 copy
->rrsig
.signer
= strdup(rr
->rrsig
.signer
);
1646 if (!copy
->rrsig
.signer
)
1648 copy
->rrsig
.signature
= memdup(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
);
1649 if (!copy
->rrsig
.signature
)
1651 copy
->rrsig
.signature_size
= rr
->rrsig
.signature_size
;
1655 copy
->nsec
.next_domain_name
= strdup(rr
->nsec
.next_domain_name
);
1656 if (!copy
->nsec
.next_domain_name
)
1658 copy
->nsec
.types
= bitmap_copy(rr
->nsec
.types
);
1659 if (!copy
->nsec
.types
)
1664 copy
->ds
.key_tag
= rr
->ds
.key_tag
;
1665 copy
->ds
.algorithm
= rr
->ds
.algorithm
;
1666 copy
->ds
.digest_type
= rr
->ds
.digest_type
;
1667 copy
->ds
.digest
= memdup(rr
->ds
.digest
, rr
->ds
.digest_size
);
1668 if (!copy
->ds
.digest
)
1670 copy
->ds
.digest_size
= rr
->ds
.digest_size
;
1673 case DNS_TYPE_NSEC3
:
1674 copy
->nsec3
.algorithm
= rr
->nsec3
.algorithm
;
1675 copy
->nsec3
.flags
= rr
->nsec3
.flags
;
1676 copy
->nsec3
.iterations
= rr
->nsec3
.iterations
;
1677 copy
->nsec3
.salt
= memdup(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
);
1678 if (!copy
->nsec3
.salt
)
1680 copy
->nsec3
.salt_size
= rr
->nsec3
.salt_size
;
1681 copy
->nsec3
.next_hashed_name
= memdup(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
);
1682 if (!copy
->nsec3
.next_hashed_name_size
)
1684 copy
->nsec3
.next_hashed_name_size
= rr
->nsec3
.next_hashed_name_size
;
1685 copy
->nsec3
.types
= bitmap_copy(rr
->nsec3
.types
);
1686 if (!copy
->nsec3
.types
)
1691 copy
->tlsa
.cert_usage
= rr
->tlsa
.cert_usage
;
1692 copy
->tlsa
.selector
= rr
->tlsa
.selector
;
1693 copy
->tlsa
.matching_type
= rr
->tlsa
.matching_type
;
1694 copy
->tlsa
.data
= memdup(rr
->tlsa
.data
, rr
->tlsa
.data_size
);
1695 if (!copy
->tlsa
.data
)
1697 copy
->tlsa
.data_size
= rr
->tlsa
.data_size
;
1701 copy
->caa
.flags
= rr
->caa
.flags
;
1702 copy
->caa
.tag
= strdup(rr
->caa
.tag
);
1705 copy
->caa
.value
= memdup(rr
->caa
.value
, rr
->caa
.value_size
);
1706 if (!copy
->caa
.value
)
1708 copy
->caa
.value_size
= rr
->caa
.value_size
;
1713 copy
->generic
.data
= memdup(rr
->generic
.data
, rr
->generic
.data_size
);
1714 if (!copy
->generic
.data
)
1716 copy
->generic
.data_size
= rr
->generic
.data_size
;
1726 int dns_resource_record_clamp_ttl(DnsResourceRecord
**rr
, uint32_t max_ttl
) {
1727 DnsResourceRecord
*old_rr
, *new_rr
;
1733 if (old_rr
->key
->type
== DNS_TYPE_OPT
)
1736 new_ttl
= MIN(old_rr
->ttl
, max_ttl
);
1737 if (new_ttl
== old_rr
->ttl
)
1740 if (old_rr
->n_ref
== 1) {
1741 /* Patch in place */
1742 old_rr
->ttl
= new_ttl
;
1746 new_rr
= dns_resource_record_copy(old_rr
);
1750 new_rr
->ttl
= new_ttl
;
1752 dns_resource_record_unref(*rr
);
1758 DnsTxtItem
*dns_txt_item_free_all(DnsTxtItem
*i
) {
1767 return dns_txt_item_free_all(n
);
1770 bool dns_txt_item_equal(DnsTxtItem
*a
, DnsTxtItem
*b
) {
1781 if (a
->length
!= b
->length
)
1784 if (memcmp(a
->data
, b
->data
, a
->length
) != 0)
1787 return dns_txt_item_equal(a
->items_next
, b
->items_next
);
1790 DnsTxtItem
*dns_txt_item_copy(DnsTxtItem
*first
) {
1791 DnsTxtItem
*i
, *copy
= NULL
, *end
= NULL
;
1793 LIST_FOREACH(items
, i
, first
) {
1796 j
= memdup(i
, offsetof(DnsTxtItem
, data
) + i
->length
+ 1);
1798 dns_txt_item_free_all(copy
);
1802 LIST_INSERT_AFTER(items
, copy
, end
, j
);
1809 static const char* const dnssec_algorithm_table
[_DNSSEC_ALGORITHM_MAX_DEFINED
] = {
1810 /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
1811 [DNSSEC_ALGORITHM_RSAMD5
] = "RSAMD5",
1812 [DNSSEC_ALGORITHM_DH
] = "DH",
1813 [DNSSEC_ALGORITHM_DSA
] = "DSA",
1814 [DNSSEC_ALGORITHM_ECC
] = "ECC",
1815 [DNSSEC_ALGORITHM_RSASHA1
] = "RSASHA1",
1816 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1
] = "DSA-NSEC3-SHA1",
1817 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1
] = "RSASHA1-NSEC3-SHA1",
1818 [DNSSEC_ALGORITHM_RSASHA256
] = "RSASHA256",
1819 [DNSSEC_ALGORITHM_RSASHA512
] = "RSASHA512",
1820 [DNSSEC_ALGORITHM_ECC_GOST
] = "ECC-GOST",
1821 [DNSSEC_ALGORITHM_ECDSAP256SHA256
] = "ECDSAP256SHA256",
1822 [DNSSEC_ALGORITHM_ECDSAP384SHA384
] = "ECDSAP384SHA384",
1823 [DNSSEC_ALGORITHM_INDIRECT
] = "INDIRECT",
1824 [DNSSEC_ALGORITHM_PRIVATEDNS
] = "PRIVATEDNS",
1825 [DNSSEC_ALGORITHM_PRIVATEOID
] = "PRIVATEOID",
1827 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm
, int, 255);
1829 static const char* const dnssec_digest_table
[_DNSSEC_DIGEST_MAX_DEFINED
] = {
1830 /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
1831 [DNSSEC_DIGEST_SHA1
] = "SHA-1",
1832 [DNSSEC_DIGEST_SHA256
] = "SHA-256",
1833 [DNSSEC_DIGEST_GOST_R_34_11_94
] = "GOST_R_34.11-94",
1834 [DNSSEC_DIGEST_SHA384
] = "SHA-384",
1836 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest
, int, 255);