1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "alloc-util.h"
6 #include "dns-domain.h"
10 #include "memory-util.h"
11 #include "resolved-dns-dnssec.h"
12 #include "resolved-dns-packet.h"
13 #include "resolved-dns-rr.h"
14 #include "string-table.h"
15 #include "string-util.h"
17 #include "terminal-util.h"
19 DnsResourceKey
* dns_resource_key_new(uint16_t class, uint16_t type
, const char *name
) {
26 k
= malloc0(sizeof(DnsResourceKey
) + l
+ 1);
34 strcpy((char*) k
+ sizeof(DnsResourceKey
), name
);
39 DnsResourceKey
* dns_resource_key_new_redirect(const DnsResourceKey
*key
, const DnsResourceRecord
*cname
) {
45 assert(IN_SET(cname
->key
->type
, DNS_TYPE_CNAME
, DNS_TYPE_DNAME
));
47 if (cname
->key
->type
== DNS_TYPE_CNAME
)
48 return dns_resource_key_new(key
->class, key
->type
, cname
->cname
.name
);
50 _cleanup_free_
char *destination
= NULL
;
53 r
= dns_name_change_suffix(dns_resource_key_name(key
), dns_resource_key_name(cname
->key
), cname
->dname
.name
, &destination
);
57 return dns_resource_key_ref((DnsResourceKey
*) key
);
59 k
= dns_resource_key_new_consume(key
->class, key
->type
, destination
);
63 TAKE_PTR(destination
);
68 int dns_resource_key_new_append_suffix(DnsResourceKey
**ret
, DnsResourceKey
*key
, char *name
) {
69 DnsResourceKey
*new_key
;
77 if (dns_name_is_root(name
)) {
78 *ret
= dns_resource_key_ref(key
);
82 r
= dns_name_concat(dns_resource_key_name(key
), name
, 0, &joined
);
86 new_key
= dns_resource_key_new_consume(key
->class, key
->type
, joined
);
96 DnsResourceKey
* dns_resource_key_new_consume(uint16_t class, uint16_t type
, char *name
) {
101 k
= new(DnsResourceKey
, 1);
105 *k
= (DnsResourceKey
) {
115 DnsResourceKey
* dns_resource_key_ref(DnsResourceKey
*k
) {
120 /* Static/const keys created with DNS_RESOURCE_KEY_CONST will
121 * set this to -1, they should not be reffed/unreffed */
122 assert(k
->n_ref
!= UINT_MAX
);
124 assert(k
->n_ref
> 0);
130 DnsResourceKey
* dns_resource_key_unref(DnsResourceKey
*k
) {
134 assert(k
->n_ref
!= UINT_MAX
);
135 assert(k
->n_ref
> 0);
146 const char* dns_resource_key_name(const DnsResourceKey
*key
) {
155 name
= (char*) key
+ sizeof(DnsResourceKey
);
157 if (dns_name_is_root(name
))
163 bool dns_resource_key_is_address(const DnsResourceKey
*key
) {
166 /* Check if this is an A or AAAA resource key */
168 return key
->class == DNS_CLASS_IN
&& IN_SET(key
->type
, DNS_TYPE_A
, DNS_TYPE_AAAA
);
171 bool dns_resource_key_is_dnssd_ptr(const DnsResourceKey
*key
) {
174 /* Check if this is a PTR resource key used in
175 Service Instance Enumeration as described in RFC6763 p4.1. */
177 if (key
->type
!= DNS_TYPE_PTR
)
180 return dns_name_endswith(dns_resource_key_name(key
), "_tcp.local") ||
181 dns_name_endswith(dns_resource_key_name(key
), "_udp.local");
184 int dns_resource_key_equal(const DnsResourceKey
*a
, const DnsResourceKey
*b
) {
190 r
= dns_name_equal(dns_resource_key_name(a
), dns_resource_key_name(b
));
194 if (a
->class != b
->class)
197 if (a
->type
!= b
->type
)
203 int dns_resource_key_match_rr(const DnsResourceKey
*key
, DnsResourceRecord
*rr
, const char *search_domain
) {
212 /* Checks if an rr matches the specified key. If a search
213 * domain is specified, it will also be checked if the key
214 * with the search domain suffixed might match the RR. */
216 if (rr
->key
->class != key
->class && key
->class != DNS_CLASS_ANY
)
219 if (rr
->key
->type
!= key
->type
&& key
->type
!= DNS_TYPE_ANY
)
222 r
= dns_name_equal(dns_resource_key_name(rr
->key
), dns_resource_key_name(key
));
227 _cleanup_free_
char *joined
= NULL
;
229 r
= dns_name_concat(dns_resource_key_name(key
), search_domain
, 0, &joined
);
233 return dns_name_equal(dns_resource_key_name(rr
->key
), joined
);
239 int dns_resource_key_match_cname_or_dname(const DnsResourceKey
*key
, const DnsResourceKey
*cname
, const char *search_domain
) {
245 if (cname
->class != key
->class && key
->class != DNS_CLASS_ANY
)
248 if (!dns_type_may_redirect(key
->type
))
251 if (cname
->type
== DNS_TYPE_CNAME
)
252 r
= dns_name_equal(dns_resource_key_name(key
), dns_resource_key_name(cname
));
253 else if (cname
->type
== DNS_TYPE_DNAME
)
254 r
= dns_name_endswith(dns_resource_key_name(key
), dns_resource_key_name(cname
));
262 _cleanup_free_
char *joined
= NULL
;
264 r
= dns_name_concat(dns_resource_key_name(key
), search_domain
, 0, &joined
);
268 if (cname
->type
== DNS_TYPE_CNAME
)
269 return dns_name_equal(joined
, dns_resource_key_name(cname
));
270 else if (cname
->type
== DNS_TYPE_DNAME
)
271 return dns_name_endswith(joined
, dns_resource_key_name(cname
));
277 int dns_resource_key_match_soa(const DnsResourceKey
*key
, const DnsResourceKey
*soa
) {
281 /* Checks whether 'soa' is a SOA record for the specified key. */
283 if (soa
->class != key
->class)
286 if (soa
->type
!= DNS_TYPE_SOA
)
289 return dns_name_endswith(dns_resource_key_name(key
), dns_resource_key_name(soa
));
292 static void dns_resource_key_hash_func(const DnsResourceKey
*k
, struct siphash
*state
) {
295 dns_name_hash_func(dns_resource_key_name(k
), state
);
296 siphash24_compress_typesafe(k
->class, state
);
297 siphash24_compress_typesafe(k
->type
, state
);
300 static int dns_resource_key_compare_func(const DnsResourceKey
*x
, const DnsResourceKey
*y
) {
303 r
= dns_name_compare_func(dns_resource_key_name(x
), dns_resource_key_name(y
));
307 r
= CMP(x
->type
, y
->type
);
311 return CMP(x
->class, y
->class);
314 DEFINE_HASH_OPS(dns_resource_key_hash_ops
, DnsResourceKey
, dns_resource_key_hash_func
, dns_resource_key_compare_func
);
316 char* dns_resource_key_to_string(const DnsResourceKey
*key
, char *buf
, size_t buf_size
) {
320 /* If we cannot convert the CLASS/TYPE into a known string,
321 use the format recommended by RFC 3597, Section 5. */
323 c
= dns_class_to_string(key
->class);
324 t
= dns_type_to_string(key
->type
);
326 (void) snprintf(buf
, buf_size
, "%s %s%s%.0u %s%s%.0u",
327 dns_resource_key_name(key
),
328 strempty(c
), c
? "" : "CLASS", c
? 0u : key
->class,
329 strempty(t
), t
? "" : "TYPE", t
? 0u : key
->type
);
334 bool dns_resource_key_reduce(DnsResourceKey
**a
, DnsResourceKey
**b
) {
338 /* Try to replace one RR key by another if they are identical, thus saving a bit of memory. Note that we do
339 * this only for RR keys, not for RRs themselves, as they carry a lot of additional metadata (where they come
340 * from, validity data, and suchlike), and cannot be replaced so easily by other RRs that have the same
341 * superficial data. */
348 /* We refuse merging const keys */
349 if ((*a
)->n_ref
== UINT_MAX
)
351 if ((*b
)->n_ref
== UINT_MAX
)
354 /* Already the same? */
358 /* Are they really identical? */
359 if (dns_resource_key_equal(*a
, *b
) <= 0)
362 /* Keep the one which already has more references. */
363 if ((*a
)->n_ref
> (*b
)->n_ref
)
364 DNS_RESOURCE_KEY_REPLACE(*b
, dns_resource_key_ref(*a
));
366 DNS_RESOURCE_KEY_REPLACE(*a
, dns_resource_key_ref(*b
));
371 DnsResourceRecord
* dns_resource_record_new(DnsResourceKey
*key
) {
372 DnsResourceRecord
*rr
;
374 rr
= new(DnsResourceRecord
, 1);
378 *rr
= (DnsResourceRecord
) {
380 .key
= dns_resource_key_ref(key
),
381 .expiry
= USEC_INFINITY
,
382 .n_skip_labels_signer
= UINT8_MAX
,
383 .n_skip_labels_source
= UINT8_MAX
,
389 DnsResourceRecord
* dns_resource_record_new_full(uint16_t class, uint16_t type
, const char *name
) {
390 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
392 key
= dns_resource_key_new(class, type
, name
);
396 return dns_resource_record_new(key
);
399 static DnsResourceRecord
* dns_resource_record_free(DnsResourceRecord
*rr
) {
403 switch (rr
->key
->type
) {
423 dns_txt_item_free_all(rr
->txt
.items
);
432 free(rr
->mx
.exchange
);
440 free(rr
->sshfp
.fingerprint
);
443 case DNS_TYPE_DNSKEY
:
444 free(rr
->dnskey
.key
);
448 free(rr
->rrsig
.signer
);
449 free(rr
->rrsig
.signature
);
453 free(rr
->nsec
.next_domain_name
);
454 bitmap_free(rr
->nsec
.types
);
458 free(rr
->nsec3
.next_hashed_name
);
459 free(rr
->nsec3
.salt
);
460 bitmap_free(rr
->nsec3
.types
);
474 free(rr
->svcb
.target_name
);
475 dns_svc_param_free_all(rr
->svcb
.params
);
483 case DNS_TYPE_OPENPGPKEY
:
486 free(rr
->generic
.data
);
490 free(rr
->generic
.data
);
492 free(rr
->wire_format
);
493 dns_resource_key_unref(rr
->key
);
500 DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsResourceRecord
, dns_resource_record
, dns_resource_record_free
);
502 int dns_resource_record_new_reverse(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *hostname
) {
503 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
504 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
505 _cleanup_free_
char *ptr
= NULL
;
512 r
= dns_name_reverse(family
, address
, &ptr
);
516 key
= dns_resource_key_new_consume(DNS_CLASS_IN
, DNS_TYPE_PTR
, ptr
);
522 rr
= dns_resource_record_new(key
);
526 rr
->ptr
.name
= strdup(hostname
);
535 int dns_resource_record_new_address(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *name
) {
536 DnsResourceRecord
*rr
;
542 if (family
== AF_INET
) {
544 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, name
);
548 rr
->a
.in_addr
= address
->in
;
550 } else if (family
== AF_INET6
) {
552 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_AAAA
, name
);
556 rr
->aaaa
.in6_addr
= address
->in6
;
558 return -EAFNOSUPPORT
;
565 #define FIELD_EQUAL(a, b, field) \
566 ((a).field ## _size == (b).field ## _size && \
567 memcmp_safe((a).field, (b).field, (a).field ## _size) == 0)
569 int dns_resource_record_payload_equal(const DnsResourceRecord
*a
, const DnsResourceRecord
*b
) {
572 /* Check if a and b are the same, but don't look at their keys */
574 if (a
->unparsable
!= b
->unparsable
)
577 switch (a
->unparsable
? _DNS_TYPE_INVALID
: a
->key
->type
) {
580 r
= dns_name_equal(a
->srv
.name
, b
->srv
.name
);
584 return a
->srv
.priority
== b
->srv
.priority
&&
585 a
->srv
.weight
== b
->srv
.weight
&&
586 a
->srv
.port
== b
->srv
.port
;
592 return dns_name_equal(a
->ptr
.name
, b
->ptr
.name
);
595 return strcaseeq(a
->hinfo
.cpu
, b
->hinfo
.cpu
) &&
596 strcaseeq(a
->hinfo
.os
, b
->hinfo
.os
);
598 case DNS_TYPE_SPF
: /* exactly the same as TXT */
600 return dns_txt_item_equal(a
->txt
.items
, b
->txt
.items
);
603 return memcmp(&a
->a
.in_addr
, &b
->a
.in_addr
, sizeof(struct in_addr
)) == 0;
606 return memcmp(&a
->aaaa
.in6_addr
, &b
->aaaa
.in6_addr
, sizeof(struct in6_addr
)) == 0;
609 r
= dns_name_equal(a
->soa
.mname
, b
->soa
.mname
);
612 r
= dns_name_equal(a
->soa
.rname
, b
->soa
.rname
);
616 return a
->soa
.serial
== b
->soa
.serial
&&
617 a
->soa
.refresh
== b
->soa
.refresh
&&
618 a
->soa
.retry
== b
->soa
.retry
&&
619 a
->soa
.expire
== b
->soa
.expire
&&
620 a
->soa
.minimum
== b
->soa
.minimum
;
623 if (a
->mx
.priority
!= b
->mx
.priority
)
626 return dns_name_equal(a
->mx
.exchange
, b
->mx
.exchange
);
629 assert(a
->loc
.version
== b
->loc
.version
);
631 return a
->loc
.size
== b
->loc
.size
&&
632 a
->loc
.horiz_pre
== b
->loc
.horiz_pre
&&
633 a
->loc
.vert_pre
== b
->loc
.vert_pre
&&
634 a
->loc
.latitude
== b
->loc
.latitude
&&
635 a
->loc
.longitude
== b
->loc
.longitude
&&
636 a
->loc
.altitude
== b
->loc
.altitude
;
639 return a
->ds
.key_tag
== b
->ds
.key_tag
&&
640 a
->ds
.algorithm
== b
->ds
.algorithm
&&
641 a
->ds
.digest_type
== b
->ds
.digest_type
&&
642 FIELD_EQUAL(a
->ds
, b
->ds
, digest
);
645 return a
->sshfp
.algorithm
== b
->sshfp
.algorithm
&&
646 a
->sshfp
.fptype
== b
->sshfp
.fptype
&&
647 FIELD_EQUAL(a
->sshfp
, b
->sshfp
, fingerprint
);
649 case DNS_TYPE_DNSKEY
:
650 return a
->dnskey
.flags
== b
->dnskey
.flags
&&
651 a
->dnskey
.protocol
== b
->dnskey
.protocol
&&
652 a
->dnskey
.algorithm
== b
->dnskey
.algorithm
&&
653 FIELD_EQUAL(a
->dnskey
, b
->dnskey
, key
);
656 /* do the fast comparisons first */
657 return a
->rrsig
.type_covered
== b
->rrsig
.type_covered
&&
658 a
->rrsig
.algorithm
== b
->rrsig
.algorithm
&&
659 a
->rrsig
.labels
== b
->rrsig
.labels
&&
660 a
->rrsig
.original_ttl
== b
->rrsig
.original_ttl
&&
661 a
->rrsig
.expiration
== b
->rrsig
.expiration
&&
662 a
->rrsig
.inception
== b
->rrsig
.inception
&&
663 a
->rrsig
.key_tag
== b
->rrsig
.key_tag
&&
664 FIELD_EQUAL(a
->rrsig
, b
->rrsig
, signature
) &&
665 dns_name_equal(a
->rrsig
.signer
, b
->rrsig
.signer
);
668 return dns_name_equal(a
->nsec
.next_domain_name
, b
->nsec
.next_domain_name
) &&
669 bitmap_equal(a
->nsec
.types
, b
->nsec
.types
);
672 return a
->nsec3
.algorithm
== b
->nsec3
.algorithm
&&
673 a
->nsec3
.flags
== b
->nsec3
.flags
&&
674 a
->nsec3
.iterations
== b
->nsec3
.iterations
&&
675 FIELD_EQUAL(a
->nsec3
, b
->nsec3
, salt
) &&
676 FIELD_EQUAL(a
->nsec3
, b
->nsec3
, next_hashed_name
) &&
677 bitmap_equal(a
->nsec3
.types
, b
->nsec3
.types
);
680 return a
->tlsa
.cert_usage
== b
->tlsa
.cert_usage
&&
681 a
->tlsa
.selector
== b
->tlsa
.selector
&&
682 a
->tlsa
.matching_type
== b
->tlsa
.matching_type
&&
683 FIELD_EQUAL(a
->tlsa
, b
->tlsa
, data
);
687 return a
->svcb
.priority
== b
->svcb
.priority
&&
688 dns_name_equal(a
->svcb
.target_name
, b
->svcb
.target_name
) &&
689 dns_svc_params_equal(a
->svcb
.params
, b
->svcb
.params
);
692 return a
->caa
.flags
== b
->caa
.flags
&&
693 streq(a
->caa
.tag
, b
->caa
.tag
) &&
694 FIELD_EQUAL(a
->caa
, b
->caa
, value
);
696 case DNS_TYPE_OPENPGPKEY
:
698 return FIELD_EQUAL(a
->generic
, b
->generic
, data
);
702 int dns_resource_record_equal(const DnsResourceRecord
*a
, const DnsResourceRecord
*b
) {
711 r
= dns_resource_key_equal(a
->key
, b
->key
);
715 return dns_resource_record_payload_equal(a
, b
);
718 static char* format_location(uint32_t latitude
, uint32_t longitude
, uint32_t altitude
,
719 uint8_t size
, uint8_t horiz_pre
, uint8_t vert_pre
) {
721 char NS
= latitude
>= 1U<<31 ? 'N' : 'S';
722 char EW
= longitude
>= 1U<<31 ? 'E' : 'W';
724 int lat
= latitude
>= 1U<<31 ? (int) (latitude
- (1U<<31)) : (int) ((1U<<31) - latitude
);
725 int lon
= longitude
>= 1U<<31 ? (int) (longitude
- (1U<<31)) : (int) ((1U<<31) - longitude
);
726 double alt
= altitude
>= 10000000u ? altitude
- 10000000u : -(double)(10000000u - altitude
);
727 double siz
= (size
>> 4) * exp10((double) (size
& 0xF));
728 double hor
= (horiz_pre
>> 4) * exp10((double) (horiz_pre
& 0xF));
729 double ver
= (vert_pre
>> 4) * exp10((double) (vert_pre
& 0xF));
731 if (asprintf(&s
, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
734 (lat
% 60000) / 1000.,
738 (lon
% 60000) / 1000.,
749 static int format_timestamp_dns(char *buf
, size_t l
, time_t sec
) {
753 assert(l
> STRLEN("YYYYMMDDHHmmSS"));
755 if (!gmtime_r(&sec
, &tm
))
758 if (strftime(buf
, l
, "%Y%m%d%H%M%S", &tm
) <= 0)
764 static char *format_types(Bitmap
*types
) {
765 _cleanup_strv_free_
char **strv
= NULL
;
766 _cleanup_free_
char *str
= NULL
;
770 BITMAP_FOREACH(type
, types
) {
771 if (dns_type_to_string(type
)) {
772 r
= strv_extend(&strv
, dns_type_to_string(type
));
778 r
= asprintf(&t
, "TYPE%u", type
);
782 r
= strv_consume(&strv
, t
);
788 str
= strv_join(strv
, " ");
792 return strjoin("( ", str
, " )");
795 static char *format_txt(DnsTxtItem
*first
) {
799 LIST_FOREACH(items
, i
, first
)
800 c
+= i
->length
* 4 + 3;
802 p
= s
= new(char, c
);
806 LIST_FOREACH(items
, i
, first
) {
812 for (size_t j
= 0; j
< i
->length
; j
++) {
813 if (i
->data
[j
] < ' ' || i
->data
[j
] == '"' || i
->data
[j
] >= 127) {
815 *(p
++) = '0' + (i
->data
[j
] / 100);
816 *(p
++) = '0' + ((i
->data
[j
] / 10) % 10);
817 *(p
++) = '0' + (i
->data
[j
] % 10);
829 const char *dns_resource_record_to_string(DnsResourceRecord
*rr
) {
830 _cleanup_free_
char *s
= NULL
, *t
= NULL
;
831 char k
[DNS_RESOURCE_KEY_STRING_MAX
];
837 return rr
->to_string
;
839 dns_resource_key_to_string(rr
->key
, k
, sizeof(k
));
841 switch (rr
->unparsable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
844 r
= asprintf(&s
, "%s %u %u %u %s",
849 strna(rr
->srv
.name
));
858 s
= strjoin(k
, " ", rr
->ptr
.name
);
865 s
= strjoin(k
, " ", rr
->hinfo
.cpu
, " ", rr
->hinfo
.os
);
870 case DNS_TYPE_SPF
: /* exactly the same as TXT */
872 t
= format_txt(rr
->txt
.items
);
876 s
= strjoin(k
, " ", t
);
882 r
= in_addr_to_string(AF_INET
, (const union in_addr_union
*) &rr
->a
.in_addr
, &t
);
886 s
= strjoin(k
, " ", t
);
892 r
= in_addr_to_string(AF_INET6
, (const union in_addr_union
*) &rr
->aaaa
.in6_addr
, &t
);
896 s
= strjoin(k
, " ", t
);
902 r
= asprintf(&s
, "%s %s %s %u %u %u %u %u",
904 strna(rr
->soa
.mname
),
905 strna(rr
->soa
.rname
),
916 r
= asprintf(&s
, "%s %u %s",
925 assert(rr
->loc
.version
== 0);
927 t
= format_location(rr
->loc
.latitude
,
936 s
= strjoin(k
, " ", t
);
942 t
= hexmem(rr
->ds
.digest
, rr
->ds
.digest_size
);
946 r
= asprintf(&s
, "%s %u %u %u %s",
957 t
= hexmem(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
961 r
= asprintf(&s
, "%s %u %u %s",
970 case DNS_TYPE_DNSKEY
: {
971 _cleanup_free_
char *alg
= NULL
;
974 key_tag
= dnssec_keytag(rr
, true);
976 r
= dnssec_algorithm_to_string_alloc(rr
->dnskey
.algorithm
, &alg
);
980 r
= asprintf(&t
, "%s %u %u %s",
988 r
= base64_append(&t
, r
,
989 rr
->dnskey
.key
, rr
->dnskey
.key_size
,
994 r
= asprintf(&s
, "%s\n"
998 rr
->dnskey
.flags
& DNSKEY_FLAG_SEP
? " SEP" : "",
999 rr
->dnskey
.flags
& DNSKEY_FLAG_REVOKE
? " REVOKE" : "",
1000 rr
->dnskey
.flags
& DNSKEY_FLAG_ZONE_KEY
? " ZONE_KEY" : "",
1008 case DNS_TYPE_RRSIG
: {
1009 _cleanup_free_
char *alg
= NULL
;
1010 char expiration
[STRLEN("YYYYMMDDHHmmSS") + 1], inception
[STRLEN("YYYYMMDDHHmmSS") + 1];
1013 type
= dns_type_to_string(rr
->rrsig
.type_covered
);
1015 r
= dnssec_algorithm_to_string_alloc(rr
->rrsig
.algorithm
, &alg
);
1019 r
= format_timestamp_dns(expiration
, sizeof(expiration
), rr
->rrsig
.expiration
);
1023 r
= format_timestamp_dns(inception
, sizeof(inception
), rr
->rrsig
.inception
);
1028 * http://tools.ietf.org/html/rfc3597#section-5 */
1030 r
= asprintf(&s
, "%s %s%.*u %s %u %u %s %s %u %s",
1033 type
? 0 : 1, type
? 0u : (unsigned) rr
->rrsig
.type_covered
,
1036 rr
->rrsig
.original_ttl
,
1044 r
= base64_append(&s
, r
,
1045 rr
->rrsig
.signature
, rr
->rrsig
.signature_size
,
1054 t
= format_types(rr
->nsec
.types
);
1058 r
= asprintf(&s
, "%s %s %s",
1060 rr
->nsec
.next_domain_name
,
1066 case DNS_TYPE_NSEC3
: {
1067 _cleanup_free_
char *salt
= NULL
, *hash
= NULL
;
1069 if (rr
->nsec3
.salt_size
> 0) {
1070 salt
= hexmem(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
);
1075 hash
= base32hexmem(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, false);
1079 t
= format_types(rr
->nsec3
.types
);
1083 r
= asprintf(&s
, "%s %"PRIu8
" %"PRIu8
" %"PRIu16
" %s %s %s",
1085 rr
->nsec3
.algorithm
,
1087 rr
->nsec3
.iterations
,
1088 rr
->nsec3
.salt_size
> 0 ? salt
: "-",
1098 t
= hexmem(rr
->tlsa
.data
, rr
->tlsa
.data_size
);
1104 " -- Cert. usage: %s\n"
1105 " -- Selector: %s\n"
1106 " -- Matching type: %s",
1108 rr
->tlsa
.cert_usage
,
1110 rr
->tlsa
.matching_type
,
1112 tlsa_cert_usage_to_string(rr
->tlsa
.cert_usage
),
1113 tlsa_selector_to_string(rr
->tlsa
.selector
),
1114 tlsa_matching_type_to_string(rr
->tlsa
.matching_type
));
1121 t
= octescape(rr
->caa
.value
, rr
->caa
.value_size
);
1125 r
= asprintf(&s
, "%s %u %s \"%s\"%s%s%s%.0u",
1130 rr
->caa
.flags
? "\n -- Flags:" : "",
1131 rr
->caa
.flags
& CAA_FLAG_CRITICAL
? " critical" : "",
1132 rr
->caa
.flags
& ~CAA_FLAG_CRITICAL
? " " : "",
1133 rr
->caa
.flags
& ~CAA_FLAG_CRITICAL
);
1139 case DNS_TYPE_OPENPGPKEY
:
1140 r
= asprintf(&s
, "%s", k
);
1144 r
= base64_append(&s
, r
,
1145 rr
->generic
.data
, rr
->generic
.data_size
,
1152 /* Format as documented in RFC 3597, Section 5 */
1153 if (rr
->generic
.data_size
== 0)
1154 r
= asprintf(&s
, "%s \\# 0", k
);
1156 t
= hexmem(rr
->generic
.data
, rr
->generic
.data_size
);
1159 r
= asprintf(&s
, "%s \\# %zu %s", k
, rr
->generic
.data_size
, t
);
1170 ssize_t
dns_resource_record_payload(DnsResourceRecord
*rr
, void **out
) {
1174 switch (rr
->unparsable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1178 case DNS_TYPE_CNAME
:
1179 case DNS_TYPE_DNAME
:
1180 case DNS_TYPE_HINFO
:
1189 case DNS_TYPE_DNSKEY
:
1190 case DNS_TYPE_RRSIG
:
1192 case DNS_TYPE_NSEC3
:
1195 case DNS_TYPE_SSHFP
:
1196 *out
= rr
->sshfp
.fingerprint
;
1197 return rr
->sshfp
.fingerprint_size
;
1200 *out
= rr
->tlsa
.data
;
1201 return rr
->tlsa
.data_size
;
1203 case DNS_TYPE_OPENPGPKEY
:
1205 *out
= rr
->generic
.data
;
1206 return rr
->generic
.data_size
;
1210 int dns_resource_record_to_wire_format(DnsResourceRecord
*rr
, bool canonical
) {
1212 _cleanup_(dns_packet_unref
) DnsPacket packet
= {
1214 .protocol
= DNS_PROTOCOL_DNS
,
1216 .refuse_compression
= true,
1217 .canonical_form
= canonical
,
1225 /* Generates the RR in wire-format, optionally in the
1226 * canonical form as discussed in the DNSSEC RFC 4034, Section
1227 * 6.2. We allocate a throw-away DnsPacket object on the stack
1228 * here, because we need some book-keeping for memory
1229 * management, and can reuse the DnsPacket serializer, that
1230 * can generate the canonical form, too, but also knows label
1231 * compression and suchlike. */
1233 if (rr
->wire_format
&& rr
->wire_format_canonical
== canonical
)
1236 r
= dns_packet_append_rr(&packet
, rr
, 0, &start
, &rds
);
1241 assert(packet
._data
);
1243 free(rr
->wire_format
);
1244 rr
->wire_format
= TAKE_PTR(packet
._data
);
1245 rr
->wire_format_size
= packet
.size
;
1246 rr
->wire_format_rdata_offset
= rds
;
1247 rr
->wire_format_canonical
= canonical
;
1252 int dns_resource_record_signer(DnsResourceRecord
*rr
, const char **ret
) {
1259 /* Returns the RRset's signer, if it is known. */
1261 if (rr
->n_skip_labels_signer
== UINT8_MAX
)
1264 n
= dns_resource_key_name(rr
->key
);
1265 r
= dns_name_skip(n
, rr
->n_skip_labels_signer
, &n
);
1275 int dns_resource_record_source(DnsResourceRecord
*rr
, const char **ret
) {
1282 /* Returns the RRset's synthesizing source, if it is known. */
1284 if (rr
->n_skip_labels_source
== UINT8_MAX
)
1287 n
= dns_resource_key_name(rr
->key
);
1288 r
= dns_name_skip(n
, rr
->n_skip_labels_source
, &n
);
1298 int dns_resource_record_is_signer(DnsResourceRecord
*rr
, const char *zone
) {
1304 r
= dns_resource_record_signer(rr
, &signer
);
1308 return dns_name_equal(zone
, signer
);
1311 int dns_resource_record_is_synthetic(DnsResourceRecord
*rr
) {
1316 /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
1318 if (rr
->n_skip_labels_source
== UINT8_MAX
)
1321 if (rr
->n_skip_labels_source
== 0)
1324 if (rr
->n_skip_labels_source
> 1)
1327 r
= dns_name_startswith(dns_resource_key_name(rr
->key
), "*");
1334 void dns_resource_record_hash_func(const DnsResourceRecord
*rr
, struct siphash
*state
) {
1337 dns_resource_key_hash_func(rr
->key
, state
);
1339 switch (rr
->unparsable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1342 siphash24_compress_typesafe(rr
->srv
.priority
, state
);
1343 siphash24_compress_typesafe(rr
->srv
.weight
, state
);
1344 siphash24_compress_typesafe(rr
->srv
.port
, state
);
1345 dns_name_hash_func(rr
->srv
.name
, state
);
1350 case DNS_TYPE_CNAME
:
1351 case DNS_TYPE_DNAME
:
1352 dns_name_hash_func(rr
->ptr
.name
, state
);
1355 case DNS_TYPE_HINFO
:
1356 string_hash_func(rr
->hinfo
.cpu
, state
);
1357 string_hash_func(rr
->hinfo
.os
, state
);
1361 case DNS_TYPE_SPF
: {
1362 LIST_FOREACH(items
, j
, rr
->txt
.items
) {
1363 siphash24_compress_safe(j
->data
, j
->length
, state
);
1365 /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
1366 * followed by "". */
1367 siphash24_compress_byte(0, state
);
1373 siphash24_compress_typesafe(rr
->a
.in_addr
, state
);
1377 siphash24_compress_typesafe(rr
->aaaa
.in6_addr
, state
);
1381 dns_name_hash_func(rr
->soa
.mname
, state
);
1382 dns_name_hash_func(rr
->soa
.rname
, state
);
1383 siphash24_compress_typesafe(rr
->soa
.serial
, state
);
1384 siphash24_compress_typesafe(rr
->soa
.refresh
, state
);
1385 siphash24_compress_typesafe(rr
->soa
.retry
, state
);
1386 siphash24_compress_typesafe(rr
->soa
.expire
, state
);
1387 siphash24_compress_typesafe(rr
->soa
.minimum
, state
);
1391 siphash24_compress_typesafe(rr
->mx
.priority
, state
);
1392 dns_name_hash_func(rr
->mx
.exchange
, state
);
1396 siphash24_compress_typesafe(rr
->loc
.version
, state
);
1397 siphash24_compress_typesafe(rr
->loc
.size
, state
);
1398 siphash24_compress_typesafe(rr
->loc
.horiz_pre
, state
);
1399 siphash24_compress_typesafe(rr
->loc
.vert_pre
, state
);
1400 siphash24_compress_typesafe(rr
->loc
.latitude
, state
);
1401 siphash24_compress_typesafe(rr
->loc
.longitude
, state
);
1402 siphash24_compress_typesafe(rr
->loc
.altitude
, state
);
1405 case DNS_TYPE_SSHFP
:
1406 siphash24_compress_typesafe(rr
->sshfp
.algorithm
, state
);
1407 siphash24_compress_typesafe(rr
->sshfp
.fptype
, state
);
1408 siphash24_compress_safe(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
, state
);
1411 case DNS_TYPE_DNSKEY
:
1412 siphash24_compress_typesafe(rr
->dnskey
.flags
, state
);
1413 siphash24_compress_typesafe(rr
->dnskey
.protocol
, state
);
1414 siphash24_compress_typesafe(rr
->dnskey
.algorithm
, state
);
1415 siphash24_compress_safe(rr
->dnskey
.key
, rr
->dnskey
.key_size
, state
);
1418 case DNS_TYPE_RRSIG
:
1419 siphash24_compress_typesafe(rr
->rrsig
.type_covered
, state
);
1420 siphash24_compress_typesafe(rr
->rrsig
.algorithm
, state
);
1421 siphash24_compress_typesafe(rr
->rrsig
.labels
, state
);
1422 siphash24_compress_typesafe(rr
->rrsig
.original_ttl
, state
);
1423 siphash24_compress_typesafe(rr
->rrsig
.expiration
, state
);
1424 siphash24_compress_typesafe(rr
->rrsig
.inception
, state
);
1425 siphash24_compress_typesafe(rr
->rrsig
.key_tag
, state
);
1426 dns_name_hash_func(rr
->rrsig
.signer
, state
);
1427 siphash24_compress_safe(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
, state
);
1431 dns_name_hash_func(rr
->nsec
.next_domain_name
, state
);
1432 /* FIXME: we leave out the type bitmap here. Hash
1433 * would be better if we'd take it into account
1438 siphash24_compress_typesafe(rr
->ds
.key_tag
, state
);
1439 siphash24_compress_typesafe(rr
->ds
.algorithm
, state
);
1440 siphash24_compress_typesafe(rr
->ds
.digest_type
, state
);
1441 siphash24_compress_safe(rr
->ds
.digest
, rr
->ds
.digest_size
, state
);
1444 case DNS_TYPE_NSEC3
:
1445 siphash24_compress_typesafe(rr
->nsec3
.algorithm
, state
);
1446 siphash24_compress_typesafe(rr
->nsec3
.flags
, state
);
1447 siphash24_compress_typesafe(rr
->nsec3
.iterations
, state
);
1448 siphash24_compress_safe(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
, state
);
1449 siphash24_compress_safe(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, state
);
1450 /* FIXME: We leave the bitmaps out */
1454 siphash24_compress_typesafe(rr
->tlsa
.cert_usage
, state
);
1455 siphash24_compress_typesafe(rr
->tlsa
.selector
, state
);
1456 siphash24_compress_typesafe(rr
->tlsa
.matching_type
, state
);
1457 siphash24_compress_safe(rr
->tlsa
.data
, rr
->tlsa
.data_size
, state
);
1461 case DNS_TYPE_HTTPS
:
1462 dns_name_hash_func(rr
->svcb
.target_name
, state
);
1463 siphash24_compress_typesafe(rr
->svcb
.priority
, state
);
1464 LIST_FOREACH(params
, j
, rr
->svcb
.params
) {
1465 siphash24_compress_typesafe(j
->key
, state
);
1466 siphash24_compress_safe(j
->value
, j
->length
, state
);
1471 siphash24_compress_typesafe(rr
->caa
.flags
, state
);
1472 string_hash_func(rr
->caa
.tag
, state
);
1473 siphash24_compress_safe(rr
->caa
.value
, rr
->caa
.value_size
, state
);
1476 case DNS_TYPE_OPENPGPKEY
:
1478 siphash24_compress_safe(rr
->generic
.data
, rr
->generic
.data_size
, state
);
1483 int dns_resource_record_compare_func(const DnsResourceRecord
*x
, const DnsResourceRecord
*y
) {
1486 r
= dns_resource_key_compare_func(x
->key
, y
->key
);
1490 if (dns_resource_record_payload_equal(x
, y
) > 0)
1493 /* We still use CMP() here, even though don't implement proper
1494 * ordering, since the hashtable doesn't need ordering anyway. */
1498 DEFINE_HASH_OPS(dns_resource_record_hash_ops
, DnsResourceRecord
, dns_resource_record_hash_func
, dns_resource_record_compare_func
);
1500 DnsResourceRecord
*dns_resource_record_copy(DnsResourceRecord
*rr
) {
1501 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*copy
= NULL
;
1502 DnsResourceRecord
*t
;
1506 copy
= dns_resource_record_new(rr
->key
);
1510 copy
->ttl
= rr
->ttl
;
1511 copy
->expiry
= rr
->expiry
;
1512 copy
->n_skip_labels_signer
= rr
->n_skip_labels_signer
;
1513 copy
->n_skip_labels_source
= rr
->n_skip_labels_source
;
1514 copy
->unparsable
= rr
->unparsable
;
1516 switch (rr
->unparsable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1519 copy
->srv
.priority
= rr
->srv
.priority
;
1520 copy
->srv
.weight
= rr
->srv
.weight
;
1521 copy
->srv
.port
= rr
->srv
.port
;
1522 copy
->srv
.name
= strdup(rr
->srv
.name
);
1523 if (!copy
->srv
.name
)
1529 case DNS_TYPE_CNAME
:
1530 case DNS_TYPE_DNAME
:
1531 copy
->ptr
.name
= strdup(rr
->ptr
.name
);
1532 if (!copy
->ptr
.name
)
1536 case DNS_TYPE_HINFO
:
1537 copy
->hinfo
.cpu
= strdup(rr
->hinfo
.cpu
);
1538 if (!copy
->hinfo
.cpu
)
1541 copy
->hinfo
.os
= strdup(rr
->hinfo
.os
);
1542 if (!copy
->hinfo
.os
)
1548 copy
->txt
.items
= dns_txt_item_copy(rr
->txt
.items
);
1549 if (!copy
->txt
.items
)
1558 copy
->aaaa
= rr
->aaaa
;
1562 copy
->soa
.mname
= strdup(rr
->soa
.mname
);
1563 if (!copy
->soa
.mname
)
1565 copy
->soa
.rname
= strdup(rr
->soa
.rname
);
1566 if (!copy
->soa
.rname
)
1568 copy
->soa
.serial
= rr
->soa
.serial
;
1569 copy
->soa
.refresh
= rr
->soa
.refresh
;
1570 copy
->soa
.retry
= rr
->soa
.retry
;
1571 copy
->soa
.expire
= rr
->soa
.expire
;
1572 copy
->soa
.minimum
= rr
->soa
.minimum
;
1576 copy
->mx
.priority
= rr
->mx
.priority
;
1577 copy
->mx
.exchange
= strdup(rr
->mx
.exchange
);
1578 if (!copy
->mx
.exchange
)
1583 copy
->loc
= rr
->loc
;
1586 case DNS_TYPE_SSHFP
:
1587 copy
->sshfp
.algorithm
= rr
->sshfp
.algorithm
;
1588 copy
->sshfp
.fptype
= rr
->sshfp
.fptype
;
1589 copy
->sshfp
.fingerprint
= memdup(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
1590 if (!copy
->sshfp
.fingerprint
)
1592 copy
->sshfp
.fingerprint_size
= rr
->sshfp
.fingerprint_size
;
1595 case DNS_TYPE_DNSKEY
:
1596 copy
->dnskey
.flags
= rr
->dnskey
.flags
;
1597 copy
->dnskey
.protocol
= rr
->dnskey
.protocol
;
1598 copy
->dnskey
.algorithm
= rr
->dnskey
.algorithm
;
1599 copy
->dnskey
.key
= memdup(rr
->dnskey
.key
, rr
->dnskey
.key_size
);
1600 if (!copy
->dnskey
.key
)
1602 copy
->dnskey
.key_size
= rr
->dnskey
.key_size
;
1605 case DNS_TYPE_RRSIG
:
1606 copy
->rrsig
.type_covered
= rr
->rrsig
.type_covered
;
1607 copy
->rrsig
.algorithm
= rr
->rrsig
.algorithm
;
1608 copy
->rrsig
.labels
= rr
->rrsig
.labels
;
1609 copy
->rrsig
.original_ttl
= rr
->rrsig
.original_ttl
;
1610 copy
->rrsig
.expiration
= rr
->rrsig
.expiration
;
1611 copy
->rrsig
.inception
= rr
->rrsig
.inception
;
1612 copy
->rrsig
.key_tag
= rr
->rrsig
.key_tag
;
1613 copy
->rrsig
.signer
= strdup(rr
->rrsig
.signer
);
1614 if (!copy
->rrsig
.signer
)
1616 copy
->rrsig
.signature
= memdup(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
);
1617 if (!copy
->rrsig
.signature
)
1619 copy
->rrsig
.signature_size
= rr
->rrsig
.signature_size
;
1623 copy
->nsec
.next_domain_name
= strdup(rr
->nsec
.next_domain_name
);
1624 if (!copy
->nsec
.next_domain_name
)
1626 if (rr
->nsec
.types
) {
1627 copy
->nsec
.types
= bitmap_copy(rr
->nsec
.types
);
1628 if (!copy
->nsec
.types
)
1634 copy
->ds
.key_tag
= rr
->ds
.key_tag
;
1635 copy
->ds
.algorithm
= rr
->ds
.algorithm
;
1636 copy
->ds
.digest_type
= rr
->ds
.digest_type
;
1637 copy
->ds
.digest
= memdup(rr
->ds
.digest
, rr
->ds
.digest_size
);
1638 if (!copy
->ds
.digest
)
1640 copy
->ds
.digest_size
= rr
->ds
.digest_size
;
1643 case DNS_TYPE_NSEC3
:
1644 copy
->nsec3
.algorithm
= rr
->nsec3
.algorithm
;
1645 copy
->nsec3
.flags
= rr
->nsec3
.flags
;
1646 copy
->nsec3
.iterations
= rr
->nsec3
.iterations
;
1647 copy
->nsec3
.salt
= memdup(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
);
1648 if (!copy
->nsec3
.salt
)
1650 copy
->nsec3
.salt_size
= rr
->nsec3
.salt_size
;
1651 copy
->nsec3
.next_hashed_name
= memdup(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
);
1652 if (!copy
->nsec3
.next_hashed_name
)
1654 copy
->nsec3
.next_hashed_name_size
= rr
->nsec3
.next_hashed_name_size
;
1655 if (rr
->nsec3
.types
) {
1656 copy
->nsec3
.types
= bitmap_copy(rr
->nsec3
.types
);
1657 if (!copy
->nsec3
.types
)
1663 copy
->tlsa
.cert_usage
= rr
->tlsa
.cert_usage
;
1664 copy
->tlsa
.selector
= rr
->tlsa
.selector
;
1665 copy
->tlsa
.matching_type
= rr
->tlsa
.matching_type
;
1666 copy
->tlsa
.data
= memdup(rr
->tlsa
.data
, rr
->tlsa
.data_size
);
1667 if (!copy
->tlsa
.data
)
1669 copy
->tlsa
.data_size
= rr
->tlsa
.data_size
;
1673 copy
->caa
.flags
= rr
->caa
.flags
;
1674 copy
->caa
.tag
= strdup(rr
->caa
.tag
);
1677 copy
->caa
.value
= memdup(rr
->caa
.value
, rr
->caa
.value_size
);
1678 if (!copy
->caa
.value
)
1680 copy
->caa
.value_size
= rr
->caa
.value_size
;
1684 case DNS_TYPE_HTTPS
:
1685 copy
->svcb
.priority
= rr
->svcb
.priority
;
1686 copy
->svcb
.target_name
= strdup(rr
->svcb
.target_name
);
1687 if (!copy
->svcb
.target_name
)
1689 copy
->svcb
.params
= dns_svc_params_copy(rr
->svcb
.params
);
1690 if (rr
->svcb
.params
&& !copy
->svcb
.params
)
1696 copy
->generic
.data
= memdup(rr
->generic
.data
, rr
->generic
.data_size
);
1697 if (!copy
->generic
.data
)
1699 copy
->generic
.data_size
= rr
->generic
.data_size
;
1708 int dns_resource_record_clamp_ttl(DnsResourceRecord
**rr
, uint32_t max_ttl
) {
1709 DnsResourceRecord
*old_rr
, *new_rr
;
1715 if (old_rr
->key
->type
== DNS_TYPE_OPT
)
1718 new_ttl
= MIN(old_rr
->ttl
, max_ttl
);
1719 if (new_ttl
== old_rr
->ttl
)
1722 if (old_rr
->n_ref
== 1) {
1723 /* Patch in place */
1724 old_rr
->ttl
= new_ttl
;
1728 new_rr
= dns_resource_record_copy(old_rr
);
1732 new_rr
->ttl
= new_ttl
;
1734 DNS_RR_REPLACE(*rr
, new_rr
);
1738 bool dns_resource_record_is_link_local_address(DnsResourceRecord
*rr
) {
1741 if (rr
->key
->class != DNS_CLASS_IN
)
1744 if (rr
->key
->type
== DNS_TYPE_A
)
1745 return in4_addr_is_link_local(&rr
->a
.in_addr
);
1747 if (rr
->key
->type
== DNS_TYPE_AAAA
)
1748 return in6_addr_is_link_local(&rr
->aaaa
.in6_addr
);
1753 int dns_resource_record_get_cname_target(DnsResourceKey
*key
, DnsResourceRecord
*cname
, char **ret
) {
1754 _cleanup_free_
char *d
= NULL
;
1760 /* Checks if the RR `cname` is a CNAME/DNAME RR that matches the specified `key`. If so, returns the
1761 * target domain. If not, returns -EUNATCH */
1763 if (key
->class != cname
->key
->class && key
->class != DNS_CLASS_ANY
)
1766 if (!dns_type_may_redirect(key
->type
)) /* This key type is not subject to CNAME/DNAME redirection?
1767 * Then let's refuse right-away */
1770 if (cname
->key
->type
== DNS_TYPE_CNAME
) {
1771 r
= dns_name_equal(dns_resource_key_name(key
),
1772 dns_resource_key_name(cname
->key
));
1776 return -EUNATCH
; /* CNAME RR key doesn't actually match the original key */
1778 d
= strdup(cname
->cname
.name
);
1782 } else if (cname
->key
->type
== DNS_TYPE_DNAME
) {
1784 r
= dns_name_change_suffix(
1785 dns_resource_key_name(key
),
1786 dns_resource_key_name(cname
->key
),
1792 return -EUNATCH
; /* DNAME RR key doesn't actually match the original key */
1795 return -EUNATCH
; /* Not a CNAME/DNAME RR, hence doesn't match the proposition either */
1801 DnsTxtItem
*dns_txt_item_free_all(DnsTxtItem
*first
) {
1802 LIST_FOREACH(items
, i
, first
)
1808 DnsSvcParam
*dns_svc_param_free_all(DnsSvcParam
*first
) {
1809 LIST_FOREACH(params
, i
, first
)
1815 bool dns_txt_item_equal(DnsTxtItem
*a
, DnsTxtItem
*b
) {
1821 LIST_FOREACH(items
, aa
, a
) {
1825 if (memcmp_nn(aa
->data
, aa
->length
, bb
->data
, bb
->length
) != 0)
1828 bb
= bb
->items_next
;
1834 DnsTxtItem
*dns_txt_item_copy(DnsTxtItem
*first
) {
1835 DnsTxtItem
*copy
= NULL
, *end
= NULL
;
1837 LIST_FOREACH(items
, i
, first
) {
1840 j
= memdup(i
, offsetof(DnsTxtItem
, data
) + i
->length
+ 1);
1842 return dns_txt_item_free_all(copy
);
1844 LIST_INSERT_AFTER(items
, copy
, end
, j
);
1851 bool dns_svc_params_equal(DnsSvcParam
*a
, DnsSvcParam
*b
) {
1852 DnsSvcParam
*bb
= b
;
1857 LIST_FOREACH(params
, aa
, a
) {
1861 if (aa
->key
!= bb
->key
)
1864 if (memcmp_nn(aa
->value
, aa
->length
, bb
->value
, bb
->length
) != 0)
1867 bb
= bb
->params_next
;
1873 DnsSvcParam
*dns_svc_params_copy(DnsSvcParam
*first
) {
1874 DnsSvcParam
*copy
= NULL
, *end
= NULL
;
1876 LIST_FOREACH(params
, i
, first
) {
1879 j
= memdup(i
, offsetof(DnsSvcParam
, value
) + i
->length
);
1881 return dns_svc_param_free_all(copy
);
1883 LIST_INSERT_AFTER(params
, copy
, end
, j
);
1890 int dns_txt_item_new_empty(DnsTxtItem
**ret
) {
1895 /* RFC 6763, section 6.1 suggests to treat
1896 * empty TXT RRs as equivalent to a TXT record
1897 * with a single empty string. */
1899 i
= malloc0(offsetof(DnsTxtItem
, data
) + 1); /* for safety reasons we add an extra NUL byte */
1907 int dns_resource_record_new_from_raw(DnsResourceRecord
**ret
, const void *data
, size_t size
) {
1908 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
1911 r
= dns_packet_new(&p
, DNS_PROTOCOL_DNS
, 0, DNS_PACKET_SIZE_MAX
);
1915 p
->refuse_compression
= true;
1917 r
= dns_packet_append_blob(p
, data
, size
, NULL
);
1921 return dns_packet_read_rr(p
, ret
, NULL
, NULL
);
1924 int dns_resource_key_to_json(DnsResourceKey
*key
, JsonVariant
**ret
) {
1928 return json_build(ret
,
1930 JSON_BUILD_PAIR("class", JSON_BUILD_INTEGER(key
->class)),
1931 JSON_BUILD_PAIR("type", JSON_BUILD_INTEGER(key
->type
)),
1932 JSON_BUILD_PAIR("name", JSON_BUILD_STRING(dns_resource_key_name(key
)))));
1935 int dns_resource_key_from_json(JsonVariant
*v
, DnsResourceKey
**ret
) {
1936 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
1937 uint16_t type
= 0, class = 0;
1938 const char *name
= NULL
;
1941 JsonDispatch dispatch_table
[] = {
1942 { "class", _JSON_VARIANT_TYPE_INVALID
, json_dispatch_uint16
, PTR_TO_SIZE(&class), JSON_MANDATORY
},
1943 { "type", _JSON_VARIANT_TYPE_INVALID
, json_dispatch_uint16
, PTR_TO_SIZE(&type
), JSON_MANDATORY
},
1944 { "name", JSON_VARIANT_STRING
, json_dispatch_const_string
, PTR_TO_SIZE(&name
), JSON_MANDATORY
},
1951 r
= json_dispatch(v
, dispatch_table
, 0, NULL
);
1955 key
= dns_resource_key_new(class, type
, name
);
1959 *ret
= TAKE_PTR(key
);
1963 static int type_bitmap_to_json(Bitmap
*b
, JsonVariant
**ret
) {
1964 _cleanup_(json_variant_unrefp
) JsonVariant
*l
= NULL
;
1970 BITMAP_FOREACH(t
, b
) {
1971 _cleanup_(json_variant_unrefp
) JsonVariant
*v
= NULL
;
1973 r
= json_variant_new_unsigned(&v
, t
);
1977 r
= json_variant_append_array(&l
, v
);
1983 return json_variant_new_array(ret
, NULL
, 0);
1989 static int txt_to_json(DnsTxtItem
*items
, JsonVariant
**ret
) {
1990 JsonVariant
**elements
= NULL
;
1996 LIST_FOREACH(items
, i
, items
) {
1997 if (!GREEDY_REALLOC(elements
, n
+ 1)) {
2002 r
= json_variant_new_octescape(elements
+ n
, i
->data
, i
->length
);
2009 r
= json_variant_new_array(ret
, elements
, n
);
2012 for (size_t i
= 0; i
< n
; i
++)
2013 json_variant_unref(elements
[i
]);
2019 int dns_resource_record_to_json(DnsResourceRecord
*rr
, JsonVariant
**ret
) {
2020 _cleanup_(json_variant_unrefp
) JsonVariant
*k
= NULL
;
2026 r
= dns_resource_key_to_json(rr
->key
, &k
);
2030 switch (rr
->unparsable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
2033 return json_build(ret
,
2035 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2036 JSON_BUILD_PAIR("priority", JSON_BUILD_UNSIGNED(rr
->srv
.priority
)),
2037 JSON_BUILD_PAIR("weight", JSON_BUILD_UNSIGNED(rr
->srv
.weight
)),
2038 JSON_BUILD_PAIR("port", JSON_BUILD_UNSIGNED(rr
->srv
.port
)),
2039 JSON_BUILD_PAIR("name", JSON_BUILD_STRING(rr
->srv
.name
))));
2043 case DNS_TYPE_CNAME
:
2044 case DNS_TYPE_DNAME
:
2045 return json_build(ret
,
2047 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2048 JSON_BUILD_PAIR("name", JSON_BUILD_STRING(rr
->ptr
.name
))));
2050 case DNS_TYPE_HINFO
:
2051 return json_build(ret
,
2053 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2054 JSON_BUILD_PAIR("cpu", JSON_BUILD_STRING(rr
->hinfo
.cpu
)),
2055 JSON_BUILD_PAIR("os", JSON_BUILD_STRING(rr
->hinfo
.os
))));
2058 case DNS_TYPE_TXT
: {
2059 _cleanup_(json_variant_unrefp
) JsonVariant
*l
= NULL
;
2061 r
= txt_to_json(rr
->txt
.items
, &l
);
2065 return json_build(ret
,
2067 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2068 JSON_BUILD_PAIR("items", JSON_BUILD_VARIANT(l
))));
2072 return json_build(ret
,
2074 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2075 JSON_BUILD_PAIR("address", JSON_BUILD_IN4_ADDR(&rr
->a
.in_addr
))));
2078 return json_build(ret
,
2080 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2081 JSON_BUILD_PAIR("address", JSON_BUILD_IN6_ADDR(&rr
->aaaa
.in6_addr
))));
2084 return json_build(ret
,
2086 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2087 JSON_BUILD_PAIR("mname", JSON_BUILD_STRING(rr
->soa
.mname
)),
2088 JSON_BUILD_PAIR("rname", JSON_BUILD_STRING(rr
->soa
.rname
)),
2089 JSON_BUILD_PAIR("serial", JSON_BUILD_UNSIGNED(rr
->soa
.serial
)),
2090 JSON_BUILD_PAIR("refresh", JSON_BUILD_UNSIGNED(rr
->soa
.refresh
)),
2091 JSON_BUILD_PAIR("expire", JSON_BUILD_UNSIGNED(rr
->soa
.retry
)),
2092 JSON_BUILD_PAIR("minimum", JSON_BUILD_UNSIGNED(rr
->soa
.minimum
))));
2095 return json_build(ret
,
2097 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2098 JSON_BUILD_PAIR("priority", JSON_BUILD_UNSIGNED(rr
->mx
.priority
)),
2099 JSON_BUILD_PAIR("exchange", JSON_BUILD_STRING(rr
->mx
.exchange
))));
2101 return json_build(ret
,
2103 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2104 JSON_BUILD_PAIR("version", JSON_BUILD_UNSIGNED(rr
->loc
.version
)),
2105 JSON_BUILD_PAIR("size", JSON_BUILD_UNSIGNED(rr
->loc
.size
)),
2106 JSON_BUILD_PAIR("horiz_pre", JSON_BUILD_UNSIGNED(rr
->loc
.horiz_pre
)),
2107 JSON_BUILD_PAIR("vert_pre", JSON_BUILD_UNSIGNED(rr
->loc
.vert_pre
)),
2108 JSON_BUILD_PAIR("latitude", JSON_BUILD_UNSIGNED(rr
->loc
.latitude
)),
2109 JSON_BUILD_PAIR("longitude", JSON_BUILD_UNSIGNED(rr
->loc
.longitude
)),
2110 JSON_BUILD_PAIR("altitude", JSON_BUILD_UNSIGNED(rr
->loc
.altitude
))));
2113 return json_build(ret
,
2115 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2116 JSON_BUILD_PAIR("keyTag", JSON_BUILD_UNSIGNED(rr
->ds
.key_tag
)),
2117 JSON_BUILD_PAIR("algorithm", JSON_BUILD_UNSIGNED(rr
->ds
.algorithm
)),
2118 JSON_BUILD_PAIR("digestType", JSON_BUILD_UNSIGNED(rr
->ds
.digest_type
)),
2119 JSON_BUILD_PAIR("digest", JSON_BUILD_HEX(rr
->ds
.digest
, rr
->ds
.digest_size
))));
2121 case DNS_TYPE_SSHFP
:
2122 return json_build(ret
,
2124 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2125 JSON_BUILD_PAIR("algorithm", JSON_BUILD_UNSIGNED(rr
->sshfp
.algorithm
)),
2126 JSON_BUILD_PAIR("fptype", JSON_BUILD_UNSIGNED(rr
->sshfp
.fptype
)),
2127 JSON_BUILD_PAIR("fingerprint", JSON_BUILD_HEX(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
))));
2129 case DNS_TYPE_DNSKEY
:
2130 return json_build(ret
,
2132 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2133 JSON_BUILD_PAIR("flags", JSON_BUILD_UNSIGNED(rr
->dnskey
.flags
)),
2134 JSON_BUILD_PAIR("protocol", JSON_BUILD_UNSIGNED(rr
->dnskey
.protocol
)),
2135 JSON_BUILD_PAIR("algorithm", JSON_BUILD_UNSIGNED(rr
->dnskey
.algorithm
)),
2136 JSON_BUILD_PAIR("dnskey", JSON_BUILD_BASE64(rr
->dnskey
.key
, rr
->dnskey
.key_size
))));
2139 case DNS_TYPE_RRSIG
:
2140 return json_build(ret
,
2142 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2143 JSON_BUILD_PAIR("signer", JSON_BUILD_STRING(rr
->rrsig
.signer
)),
2144 JSON_BUILD_PAIR("typeCovered", JSON_BUILD_UNSIGNED(rr
->rrsig
.type_covered
)),
2145 JSON_BUILD_PAIR("algorithm", JSON_BUILD_UNSIGNED(rr
->rrsig
.algorithm
)),
2146 JSON_BUILD_PAIR("labels", JSON_BUILD_UNSIGNED(rr
->rrsig
.labels
)),
2147 JSON_BUILD_PAIR("originalTtl", JSON_BUILD_UNSIGNED(rr
->rrsig
.original_ttl
)),
2148 JSON_BUILD_PAIR("expiration", JSON_BUILD_UNSIGNED(rr
->rrsig
.expiration
)),
2149 JSON_BUILD_PAIR("inception", JSON_BUILD_UNSIGNED(rr
->rrsig
.inception
)),
2150 JSON_BUILD_PAIR("keyTag", JSON_BUILD_UNSIGNED(rr
->rrsig
.key_tag
)),
2151 JSON_BUILD_PAIR("signature", JSON_BUILD_BASE64(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
))));
2153 case DNS_TYPE_NSEC
: {
2154 _cleanup_(json_variant_unrefp
) JsonVariant
*bm
= NULL
;
2156 r
= type_bitmap_to_json(rr
->nsec
.types
, &bm
);
2160 return json_build(ret
,
2162 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2163 JSON_BUILD_PAIR("nextDomain", JSON_BUILD_STRING(rr
->nsec
.next_domain_name
)),
2164 JSON_BUILD_PAIR("types", JSON_BUILD_VARIANT(bm
))));
2167 case DNS_TYPE_NSEC3
: {
2168 _cleanup_(json_variant_unrefp
) JsonVariant
*bm
= NULL
;
2170 r
= type_bitmap_to_json(rr
->nsec3
.types
, &bm
);
2174 return json_build(ret
,
2176 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2177 JSON_BUILD_PAIR("algorithm", JSON_BUILD_UNSIGNED(rr
->nsec3
.algorithm
)),
2178 JSON_BUILD_PAIR("flags", JSON_BUILD_UNSIGNED(rr
->nsec3
.flags
)),
2179 JSON_BUILD_PAIR("iterations", JSON_BUILD_UNSIGNED(rr
->nsec3
.iterations
)),
2180 JSON_BUILD_PAIR("salt", JSON_BUILD_HEX(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
)),
2181 JSON_BUILD_PAIR("hash", JSON_BUILD_BASE32HEX(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
)),
2182 JSON_BUILD_PAIR("types", JSON_BUILD_VARIANT(bm
))));
2186 return json_build(ret
,
2188 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2189 JSON_BUILD_PAIR("certUsage", JSON_BUILD_UNSIGNED(rr
->tlsa
.cert_usage
)),
2190 JSON_BUILD_PAIR("selector", JSON_BUILD_UNSIGNED(rr
->tlsa
.selector
)),
2191 JSON_BUILD_PAIR("matchingType", JSON_BUILD_UNSIGNED(rr
->tlsa
.matching_type
)),
2192 JSON_BUILD_PAIR("data", JSON_BUILD_HEX(rr
->tlsa
.data
, rr
->tlsa
.data_size
))));
2195 return json_build(ret
,
2197 JSON_BUILD_PAIR("key", JSON_BUILD_VARIANT(k
)),
2198 JSON_BUILD_PAIR("flags", JSON_BUILD_UNSIGNED(rr
->caa
.flags
)),
2199 JSON_BUILD_PAIR("tag", JSON_BUILD_STRING(rr
->caa
.tag
)),
2200 JSON_BUILD_PAIR("value", JSON_BUILD_OCTESCAPE(rr
->caa
.value
, rr
->caa
.value_size
))));
2203 /* Can't provide broken-down format */
2209 static const char* const dnssec_algorithm_table
[_DNSSEC_ALGORITHM_MAX_DEFINED
] = {
2210 /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
2211 [DNSSEC_ALGORITHM_RSAMD5
] = "RSAMD5",
2212 [DNSSEC_ALGORITHM_DH
] = "DH",
2213 [DNSSEC_ALGORITHM_DSA
] = "DSA",
2214 [DNSSEC_ALGORITHM_ECC
] = "ECC",
2215 [DNSSEC_ALGORITHM_RSASHA1
] = "RSASHA1",
2216 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1
] = "DSA-NSEC3-SHA1",
2217 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1
] = "RSASHA1-NSEC3-SHA1",
2218 [DNSSEC_ALGORITHM_RSASHA256
] = "RSASHA256",
2219 [DNSSEC_ALGORITHM_RSASHA512
] = "RSASHA512",
2220 [DNSSEC_ALGORITHM_ECC_GOST
] = "ECC-GOST",
2221 [DNSSEC_ALGORITHM_ECDSAP256SHA256
] = "ECDSAP256SHA256",
2222 [DNSSEC_ALGORITHM_ECDSAP384SHA384
] = "ECDSAP384SHA384",
2223 [DNSSEC_ALGORITHM_ED25519
] = "ED25519",
2224 [DNSSEC_ALGORITHM_ED448
] = "ED448",
2225 [DNSSEC_ALGORITHM_INDIRECT
] = "INDIRECT",
2226 [DNSSEC_ALGORITHM_PRIVATEDNS
] = "PRIVATEDNS",
2227 [DNSSEC_ALGORITHM_PRIVATEOID
] = "PRIVATEOID",
2229 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm
, int, 255);
2231 static const char* const dnssec_digest_table
[_DNSSEC_DIGEST_MAX_DEFINED
] = {
2232 /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
2233 [DNSSEC_DIGEST_SHA1
] = "SHA-1",
2234 [DNSSEC_DIGEST_SHA256
] = "SHA-256",
2235 [DNSSEC_DIGEST_GOST_R_34_11_94
] = "GOST_R_34.11-94",
2236 [DNSSEC_DIGEST_SHA384
] = "SHA-384",
2238 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest
, int, 255);