1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
5 #include "alloc-util.h"
7 #include "dns-domain.h"
10 #include "hash-funcs.h"
11 #include "hexdecoct.h"
12 #include "json-util.h"
13 #include "memory-util.h"
14 #include "resolved-dns-answer.h"
15 #include "resolved-dns-dnssec.h"
16 #include "resolved-dns-packet.h"
17 #include "resolved-dns-rr.h"
18 #include "siphash24.h"
19 #include "string-table.h"
20 #include "string-util.h"
22 #include "terminal-util.h"
23 #include "time-util.h"
24 #include "unaligned.h"
26 DnsResourceKey
* dns_resource_key_new(uint16_t class, uint16_t type
, const char *name
) {
33 k
= malloc0(sizeof(DnsResourceKey
) + l
+ 1);
41 strcpy((char*) k
+ sizeof(DnsResourceKey
), name
);
46 DnsResourceKey
* dns_resource_key_new_redirect(const DnsResourceKey
*key
, const DnsResourceRecord
*cname
) {
52 assert(IN_SET(cname
->key
->type
, DNS_TYPE_CNAME
, DNS_TYPE_DNAME
));
54 if (cname
->key
->type
== DNS_TYPE_CNAME
)
55 return dns_resource_key_new(key
->class, key
->type
, cname
->cname
.name
);
57 _cleanup_free_
char *destination
= NULL
;
60 r
= dns_name_change_suffix(dns_resource_key_name(key
), dns_resource_key_name(cname
->key
), cname
->dname
.name
, &destination
);
64 return dns_resource_key_ref((DnsResourceKey
*) key
);
66 k
= dns_resource_key_new_consume(key
->class, key
->type
, destination
);
70 TAKE_PTR(destination
);
75 int dns_resource_key_new_append_suffix(DnsResourceKey
**ret
, DnsResourceKey
*key
, char *name
) {
76 DnsResourceKey
*new_key
;
84 if (dns_name_is_root(name
)) {
85 *ret
= dns_resource_key_ref(key
);
89 r
= dns_name_concat(dns_resource_key_name(key
), name
, 0, &joined
);
93 new_key
= dns_resource_key_new_consume(key
->class, key
->type
, joined
);
103 DnsResourceKey
* dns_resource_key_new_consume(uint16_t class, uint16_t type
, char *name
) {
108 k
= new(DnsResourceKey
, 1);
112 *k
= (DnsResourceKey
) {
122 DnsResourceKey
* dns_resource_key_ref(DnsResourceKey
*k
) {
127 /* Static/const keys created with DNS_RESOURCE_KEY_CONST will
128 * set this to -1, they should not be reffed/unreffed */
129 assert(k
->n_ref
!= UINT_MAX
);
131 assert(k
->n_ref
> 0);
137 DnsResourceKey
* dns_resource_key_unref(DnsResourceKey
*k
) {
141 assert(k
->n_ref
!= UINT_MAX
);
142 assert(k
->n_ref
> 0);
153 const char* dns_resource_key_name(const DnsResourceKey
*key
) {
162 name
= (char*) key
+ sizeof(DnsResourceKey
);
164 if (dns_name_is_root(name
))
170 bool dns_resource_key_is_address(const DnsResourceKey
*key
) {
173 /* Check if this is an A or AAAA resource key */
175 return key
->class == DNS_CLASS_IN
&& IN_SET(key
->type
, DNS_TYPE_A
, DNS_TYPE_AAAA
);
178 bool dns_resource_key_is_dnssd_ptr(const DnsResourceKey
*key
) {
181 /* Check if this is a PTR resource key used in
182 Service Instance Enumeration as described in RFC6763 p4.1. */
184 if (key
->type
!= DNS_TYPE_PTR
)
187 return dns_name_endswith(dns_resource_key_name(key
), "_tcp.local") ||
188 dns_name_endswith(dns_resource_key_name(key
), "_udp.local");
191 bool dns_resource_key_is_dnssd_two_label_ptr(const DnsResourceKey
*key
) {
194 /* Check if this is a PTR resource key used in Service Instance
195 * Enumeration as described in RFC6763 § 4.1, excluding selective
196 * service names described in RFC6763 § 7.1. */
198 if (key
->type
!= DNS_TYPE_PTR
)
201 const char *name
= dns_resource_key_name(key
);
202 if (dns_name_parent(&name
) <= 0)
205 return dns_name_equal(name
, "_tcp.local") > 0 || dns_name_equal(name
, "_udp.local") > 0;
208 int dns_resource_key_equal(const DnsResourceKey
*a
, const DnsResourceKey
*b
) {
214 r
= dns_name_equal(dns_resource_key_name(a
), dns_resource_key_name(b
));
218 if (a
->class != b
->class)
221 if (a
->type
!= b
->type
)
227 int dns_resource_key_match_rr(const DnsResourceKey
*key
, DnsResourceRecord
*rr
, const char *search_domain
) {
236 /* Checks if an rr matches the specified key. If a search
237 * domain is specified, it will also be checked if the key
238 * with the search domain suffixed might match the RR. */
240 if (rr
->key
->class != key
->class && key
->class != DNS_CLASS_ANY
)
243 if (rr
->key
->type
!= key
->type
&& key
->type
!= DNS_TYPE_ANY
)
246 r
= dns_name_equal(dns_resource_key_name(rr
->key
), dns_resource_key_name(key
));
251 _cleanup_free_
char *joined
= NULL
;
253 r
= dns_name_concat(dns_resource_key_name(key
), search_domain
, 0, &joined
);
257 return dns_name_equal(dns_resource_key_name(rr
->key
), joined
);
263 int dns_resource_key_match_cname_or_dname(const DnsResourceKey
*key
, const DnsResourceKey
*cname
, const char *search_domain
) {
269 if (cname
->class != key
->class && key
->class != DNS_CLASS_ANY
)
272 if (!dns_type_may_redirect(key
->type
))
275 if (cname
->type
== DNS_TYPE_CNAME
)
276 r
= dns_name_equal(dns_resource_key_name(key
), dns_resource_key_name(cname
));
277 else if (cname
->type
== DNS_TYPE_DNAME
)
278 r
= dns_name_endswith(dns_resource_key_name(key
), dns_resource_key_name(cname
));
286 _cleanup_free_
char *joined
= NULL
;
288 r
= dns_name_concat(dns_resource_key_name(key
), search_domain
, 0, &joined
);
292 if (cname
->type
== DNS_TYPE_CNAME
)
293 return dns_name_equal(joined
, dns_resource_key_name(cname
));
294 else if (cname
->type
== DNS_TYPE_DNAME
)
295 return dns_name_endswith(joined
, dns_resource_key_name(cname
));
301 int dns_resource_key_match_soa(const DnsResourceKey
*key
, const DnsResourceKey
*soa
) {
305 /* Checks whether 'soa' is a SOA record for the specified key. */
307 if (soa
->class != key
->class)
310 if (soa
->type
!= DNS_TYPE_SOA
)
313 return dns_name_endswith(dns_resource_key_name(key
), dns_resource_key_name(soa
));
316 void dns_resource_key_hash_func(const DnsResourceKey
*k
, struct siphash
*state
) {
319 dns_name_hash_func(dns_resource_key_name(k
), state
);
320 siphash24_compress_typesafe(k
->class, state
);
321 siphash24_compress_typesafe(k
->type
, state
);
324 int dns_resource_key_compare_func(const DnsResourceKey
*x
, const DnsResourceKey
*y
) {
327 r
= dns_name_compare_func(dns_resource_key_name(x
), dns_resource_key_name(y
));
331 r
= CMP(x
->type
, y
->type
);
335 return CMP(x
->class, y
->class);
338 DEFINE_HASH_OPS(dns_resource_key_hash_ops
, DnsResourceKey
, dns_resource_key_hash_func
, dns_resource_key_compare_func
);
340 char* dns_resource_key_to_string(const DnsResourceKey
*key
, char *buf
, size_t buf_size
) {
344 /* If we cannot convert the CLASS/TYPE into a known string,
345 use the format recommended by RFC 3597, Section 5. */
347 c
= dns_class_to_string(key
->class);
348 t
= dns_type_to_string(key
->type
);
350 (void) snprintf(buf
, buf_size
, "%s %s%s%.0u %s%s%.0u",
351 dns_resource_key_name(key
),
352 strempty(c
), c
? "" : "CLASS", c
? 0u : key
->class,
353 strempty(t
), t
? "" : "TYPE", t
? 0u : key
->type
);
358 bool dns_resource_key_reduce(DnsResourceKey
**a
, DnsResourceKey
**b
) {
362 /* Try to replace one RR key by another if they are identical, thus saving a bit of memory. Note that we do
363 * this only for RR keys, not for RRs themselves, as they carry a lot of additional metadata (where they come
364 * from, validity data, and suchlike), and cannot be replaced so easily by other RRs that have the same
365 * superficial data. */
372 /* We refuse merging const keys */
373 if ((*a
)->n_ref
== UINT_MAX
)
375 if ((*b
)->n_ref
== UINT_MAX
)
378 /* Already the same? */
382 /* Are they really identical? */
383 if (dns_resource_key_equal(*a
, *b
) <= 0)
386 /* Keep the one which already has more references. */
387 if ((*a
)->n_ref
> (*b
)->n_ref
)
388 DNS_RESOURCE_KEY_REPLACE(*b
, dns_resource_key_ref(*a
));
390 DNS_RESOURCE_KEY_REPLACE(*a
, dns_resource_key_ref(*b
));
395 DnsResourceRecord
* dns_resource_record_new(DnsResourceKey
*key
) {
396 DnsResourceRecord
*rr
;
398 rr
= new(DnsResourceRecord
, 1);
402 *rr
= (DnsResourceRecord
) {
404 .key
= dns_resource_key_ref(key
),
405 .expiry
= USEC_INFINITY
,
406 .n_skip_labels_signer
= UINT8_MAX
,
407 .n_skip_labels_source
= UINT8_MAX
,
413 DnsResourceRecord
* dns_resource_record_new_full(uint16_t class, uint16_t type
, const char *name
) {
414 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
416 key
= dns_resource_key_new(class, type
, name
);
420 return dns_resource_record_new(key
);
423 static DnsResourceRecord
* dns_resource_record_free(DnsResourceRecord
*rr
) {
427 switch (rr
->key
->type
) {
447 dns_txt_item_free_all(rr
->txt
.items
);
456 free(rr
->mx
.exchange
);
464 free(rr
->sshfp
.fingerprint
);
467 case DNS_TYPE_DNSKEY
:
468 free(rr
->dnskey
.key
);
472 free(rr
->rrsig
.signer
);
473 free(rr
->rrsig
.signature
);
477 free(rr
->nsec
.next_domain_name
);
478 bitmap_free(rr
->nsec
.types
);
482 free(rr
->nsec3
.next_hashed_name
);
483 free(rr
->nsec3
.salt
);
484 bitmap_free(rr
->nsec3
.types
);
498 free(rr
->svcb
.target_name
);
499 dns_svc_param_free_all(rr
->svcb
.params
);
508 free(rr
->naptr
.flags
);
509 free(rr
->naptr
.services
);
510 free(rr
->naptr
.regexp
);
511 free(rr
->naptr
.replacement
);
514 case DNS_TYPE_OPENPGPKEY
:
517 free(rr
->generic
.data
);
521 free(rr
->generic
.data
);
523 free(rr
->wire_format
);
524 dns_resource_key_unref(rr
->key
);
531 DEFINE_TRIVIAL_REF_UNREF_FUNC(DnsResourceRecord
, dns_resource_record
, dns_resource_record_free
);
533 int dns_resource_record_new_reverse(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *hostname
) {
534 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
535 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
536 _cleanup_free_
char *ptr
= NULL
;
543 r
= dns_name_reverse(family
, address
, &ptr
);
547 key
= dns_resource_key_new_consume(DNS_CLASS_IN
, DNS_TYPE_PTR
, ptr
);
553 rr
= dns_resource_record_new(key
);
557 rr
->ptr
.name
= strdup(hostname
);
566 int dns_resource_record_new_address(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *name
) {
567 DnsResourceRecord
*rr
;
573 if (family
== AF_INET
) {
575 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, name
);
579 rr
->a
.in_addr
= address
->in
;
581 } else if (family
== AF_INET6
) {
583 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_AAAA
, name
);
587 rr
->aaaa
.in6_addr
= address
->in6
;
589 return -EAFNOSUPPORT
;
596 #define FIELD_EQUAL(a, b, field) \
597 ((a).field ## _size == (b).field ## _size && \
598 memcmp_safe((a).field, (b).field, (a).field ## _size) == 0)
600 int dns_resource_record_payload_equal(const DnsResourceRecord
*a
, const DnsResourceRecord
*b
) {
603 /* Check if a and b are the same, but don't look at their keys */
605 if (a
->unparsable
!= b
->unparsable
)
608 switch (a
->unparsable
? _DNS_TYPE_INVALID
: a
->key
->type
) {
611 r
= dns_name_equal(a
->srv
.name
, b
->srv
.name
);
615 return a
->srv
.priority
== b
->srv
.priority
&&
616 a
->srv
.weight
== b
->srv
.weight
&&
617 a
->srv
.port
== b
->srv
.port
;
623 return dns_name_equal(a
->ptr
.name
, b
->ptr
.name
);
626 return strcaseeq(a
->hinfo
.cpu
, b
->hinfo
.cpu
) &&
627 strcaseeq(a
->hinfo
.os
, b
->hinfo
.os
);
629 case DNS_TYPE_SPF
: /* exactly the same as TXT */
631 return dns_txt_item_equal(a
->txt
.items
, b
->txt
.items
);
634 return memcmp(&a
->a
.in_addr
, &b
->a
.in_addr
, sizeof(struct in_addr
)) == 0;
637 return memcmp(&a
->aaaa
.in6_addr
, &b
->aaaa
.in6_addr
, sizeof(struct in6_addr
)) == 0;
640 r
= dns_name_equal(a
->soa
.mname
, b
->soa
.mname
);
643 r
= dns_name_equal(a
->soa
.rname
, b
->soa
.rname
);
647 return a
->soa
.serial
== b
->soa
.serial
&&
648 a
->soa
.refresh
== b
->soa
.refresh
&&
649 a
->soa
.retry
== b
->soa
.retry
&&
650 a
->soa
.expire
== b
->soa
.expire
&&
651 a
->soa
.minimum
== b
->soa
.minimum
;
654 if (a
->mx
.priority
!= b
->mx
.priority
)
657 return dns_name_equal(a
->mx
.exchange
, b
->mx
.exchange
);
660 assert(a
->loc
.version
== b
->loc
.version
);
662 return a
->loc
.size
== b
->loc
.size
&&
663 a
->loc
.horiz_pre
== b
->loc
.horiz_pre
&&
664 a
->loc
.vert_pre
== b
->loc
.vert_pre
&&
665 a
->loc
.latitude
== b
->loc
.latitude
&&
666 a
->loc
.longitude
== b
->loc
.longitude
&&
667 a
->loc
.altitude
== b
->loc
.altitude
;
670 return a
->ds
.key_tag
== b
->ds
.key_tag
&&
671 a
->ds
.algorithm
== b
->ds
.algorithm
&&
672 a
->ds
.digest_type
== b
->ds
.digest_type
&&
673 FIELD_EQUAL(a
->ds
, b
->ds
, digest
);
676 return a
->sshfp
.algorithm
== b
->sshfp
.algorithm
&&
677 a
->sshfp
.fptype
== b
->sshfp
.fptype
&&
678 FIELD_EQUAL(a
->sshfp
, b
->sshfp
, fingerprint
);
680 case DNS_TYPE_DNSKEY
:
681 return a
->dnskey
.flags
== b
->dnskey
.flags
&&
682 a
->dnskey
.protocol
== b
->dnskey
.protocol
&&
683 a
->dnskey
.algorithm
== b
->dnskey
.algorithm
&&
684 FIELD_EQUAL(a
->dnskey
, b
->dnskey
, key
);
687 /* do the fast comparisons first */
688 if (!(a
->rrsig
.type_covered
== b
->rrsig
.type_covered
&&
689 a
->rrsig
.algorithm
== b
->rrsig
.algorithm
&&
690 a
->rrsig
.labels
== b
->rrsig
.labels
&&
691 a
->rrsig
.original_ttl
== b
->rrsig
.original_ttl
&&
692 a
->rrsig
.expiration
== b
->rrsig
.expiration
&&
693 a
->rrsig
.inception
== b
->rrsig
.inception
&&
694 a
->rrsig
.key_tag
== b
->rrsig
.key_tag
&&
695 FIELD_EQUAL(a
->rrsig
, b
->rrsig
, signature
)))
698 return dns_name_equal(a
->rrsig
.signer
, b
->rrsig
.signer
);
701 r
= dns_name_equal(a
->nsec
.next_domain_name
, b
->nsec
.next_domain_name
);
705 return bitmap_equal(a
->nsec
.types
, b
->nsec
.types
);
708 return a
->nsec3
.algorithm
== b
->nsec3
.algorithm
&&
709 a
->nsec3
.flags
== b
->nsec3
.flags
&&
710 a
->nsec3
.iterations
== b
->nsec3
.iterations
&&
711 FIELD_EQUAL(a
->nsec3
, b
->nsec3
, salt
) &&
712 FIELD_EQUAL(a
->nsec3
, b
->nsec3
, next_hashed_name
) &&
713 bitmap_equal(a
->nsec3
.types
, b
->nsec3
.types
);
716 return a
->tlsa
.cert_usage
== b
->tlsa
.cert_usage
&&
717 a
->tlsa
.selector
== b
->tlsa
.selector
&&
718 a
->tlsa
.matching_type
== b
->tlsa
.matching_type
&&
719 FIELD_EQUAL(a
->tlsa
, b
->tlsa
, data
);
724 if (!(a
->svcb
.priority
== b
->svcb
.priority
&&
725 dns_svc_params_equal(a
->svcb
.params
, b
->svcb
.params
)))
728 return dns_name_equal(a
->svcb
.target_name
, b
->svcb
.target_name
);
731 return a
->caa
.flags
== b
->caa
.flags
&&
732 streq(a
->caa
.tag
, b
->caa
.tag
) &&
733 FIELD_EQUAL(a
->caa
, b
->caa
, value
);
736 r
= dns_name_equal(a
->naptr
.replacement
, b
->naptr
.replacement
);
740 return a
->naptr
.order
== b
->naptr
.order
&&
741 a
->naptr
.preference
== b
->naptr
.preference
&&
742 streq(a
->naptr
.flags
, b
->naptr
.flags
) &&
743 streq(a
->naptr
.services
, b
->naptr
.services
) &&
744 streq(a
->naptr
.regexp
, b
->naptr
.regexp
);
746 case DNS_TYPE_OPENPGPKEY
:
748 return FIELD_EQUAL(a
->generic
, b
->generic
, data
);
752 int dns_resource_record_equal(const DnsResourceRecord
*a
, const DnsResourceRecord
*b
) {
761 r
= dns_resource_key_equal(a
->key
, b
->key
);
765 return dns_resource_record_payload_equal(a
, b
);
768 static char* format_location(uint32_t latitude
, uint32_t longitude
, uint32_t altitude
,
769 uint8_t size
, uint8_t horiz_pre
, uint8_t vert_pre
) {
771 char NS
= latitude
>= 1U<<31 ? 'N' : 'S';
772 char EW
= longitude
>= 1U<<31 ? 'E' : 'W';
774 int lat
= latitude
>= 1U<<31 ? (int) (latitude
- (1U<<31)) : (int) ((1U<<31) - latitude
);
775 int lon
= longitude
>= 1U<<31 ? (int) (longitude
- (1U<<31)) : (int) ((1U<<31) - longitude
);
776 double alt
= altitude
>= 10000000u ? altitude
- 10000000u : -(double)(10000000u - altitude
);
777 double siz
= (size
>> 4) * exp10((double) (size
& 0xF));
778 double hor
= (horiz_pre
>> 4) * exp10((double) (horiz_pre
& 0xF));
779 double ver
= (vert_pre
>> 4) * exp10((double) (vert_pre
& 0xF));
781 if (asprintf(&s
, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
784 (lat
% 60000) / 1000.,
788 (lon
% 60000) / 1000.,
799 static int format_timestamp_dns(char *buf
, size_t l
, time_t sec
) {
804 assert(l
> STRLEN("YYYYMMDDHHmmSS"));
806 r
= localtime_or_gmtime_usec(sec
* USEC_PER_SEC
, /* utc= */ true, &tm
);
810 if (strftime(buf
, l
, "%Y%m%d%H%M%S", &tm
) <= 0)
816 static char *format_types(Bitmap
*types
) {
817 _cleanup_strv_free_
char **strv
= NULL
;
818 _cleanup_free_
char *str
= NULL
;
822 BITMAP_FOREACH(type
, types
) {
823 if (dns_type_to_string(type
)) {
824 r
= strv_extend(&strv
, dns_type_to_string(type
));
830 r
= asprintf(&t
, "TYPE%u", type
);
834 r
= strv_consume(&strv
, t
);
840 str
= strv_join(strv
, " ");
844 return strjoin("( ", str
, " )");
847 static char *format_txt(DnsTxtItem
*first
) {
851 LIST_FOREACH(items
, i
, first
)
852 c
+= i
->length
* 4 + 3;
854 p
= s
= new(char, c
);
858 LIST_FOREACH(items
, i
, first
) {
864 for (size_t j
= 0; j
< i
->length
; j
++) {
865 if (i
->data
[j
] < ' ' || i
->data
[j
] == '"' || i
->data
[j
] >= 127) {
867 *(p
++) = '0' + (i
->data
[j
] / 100);
868 *(p
++) = '0' + ((i
->data
[j
] / 10) % 10);
869 *(p
++) = '0' + (i
->data
[j
] % 10);
881 static char *format_svc_param_value(DnsSvcParam
*i
) {
882 _cleanup_free_
char *value
= NULL
;
887 case DNS_SVC_PARAM_KEY_ALPN
: {
889 _cleanup_strv_free_
char **values_strv
= NULL
;
890 while (offset
< i
->length
) {
891 size_t sz
= (uint8_t) i
->value
[offset
++];
893 char *alpn
= cescape_length((char *)&i
->value
[offset
], sz
);
897 if (strv_push(&values_strv
, alpn
) < 0)
902 value
= strv_join(values_strv
, ",");
908 case DNS_SVC_PARAM_KEY_PORT
: {
909 uint16_t port
= unaligned_read_be16(i
->value
);
910 if (asprintf(&value
, "%" PRIu16
, port
) < 0)
912 return TAKE_PTR(value
);
914 case DNS_SVC_PARAM_KEY_IPV4HINT
: {
915 const struct in_addr
*addrs
= i
->value_in_addr
;
916 _cleanup_strv_free_
char **values_strv
= NULL
;
917 for (size_t n
= 0; n
< i
->length
/ sizeof (struct in_addr
); n
++) {
919 if (in_addr_to_string(AF_INET
, (const union in_addr_union
*) &addrs
[n
], &addr
) < 0)
921 if (strv_push(&values_strv
, addr
) < 0)
924 return strv_join(values_strv
, ",");
926 case DNS_SVC_PARAM_KEY_IPV6HINT
: {
927 const struct in6_addr
*addrs
= i
->value_in6_addr
;
928 _cleanup_strv_free_
char **values_strv
= NULL
;
929 for (size_t n
= 0; n
< i
->length
/ sizeof (struct in6_addr
); n
++) {
931 if (in_addr_to_string(AF_INET6
, (const union in_addr_union
*) &addrs
[n
], &addr
) < 0)
933 if (strv_push(&values_strv
, addr
) < 0)
936 return strv_join(values_strv
, ",");
939 value
= decescape((char*) &i
->value
, i
->length
, " ,");
945 if (asprintf(&qvalue
, "\"%s\"", value
) < 0)
950 static char *format_svc_param(DnsSvcParam
*i
) {
951 const char *key
= FORMAT_DNS_SVC_PARAM_KEY(i
->key
);
952 _cleanup_free_
char *value
= NULL
;
959 value
= format_svc_param_value(i
);
963 return strjoin(key
, "=", value
);
966 static char *format_svc_params(DnsSvcParam
*first
) {
967 _cleanup_strv_free_
char **params
= NULL
;
969 LIST_FOREACH(params
, i
, first
) {
970 char *param
= format_svc_param(i
);
973 if (strv_push(¶ms
, param
) < 0)
977 return strv_join(params
, " ");
980 const char* dns_resource_record_to_string(DnsResourceRecord
*rr
) {
981 _cleanup_free_
char *s
= NULL
, *t
= NULL
;
982 char k
[DNS_RESOURCE_KEY_STRING_MAX
];
988 return rr
->to_string
;
990 dns_resource_key_to_string(rr
->key
, k
, sizeof(k
));
992 switch (rr
->unparsable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
995 r
= asprintf(&s
, "%s %u %u %u %s",
1000 strna(rr
->srv
.name
));
1007 case DNS_TYPE_CNAME
:
1008 case DNS_TYPE_DNAME
:
1009 s
= strjoin(k
, " ", rr
->ptr
.name
);
1015 case DNS_TYPE_HINFO
:
1016 s
= strjoin(k
, " ", rr
->hinfo
.cpu
, " ", rr
->hinfo
.os
);
1021 case DNS_TYPE_SPF
: /* exactly the same as TXT */
1023 t
= format_txt(rr
->txt
.items
);
1027 s
= strjoin(k
, " ", t
);
1033 r
= in_addr_to_string(AF_INET
, (const union in_addr_union
*) &rr
->a
.in_addr
, &t
);
1037 s
= strjoin(k
, " ", t
);
1043 r
= in_addr_to_string(AF_INET6
, (const union in_addr_union
*) &rr
->aaaa
.in6_addr
, &t
);
1047 s
= strjoin(k
, " ", t
);
1053 r
= asprintf(&s
, "%s %s %s %u %u %u %u %u",
1055 strna(rr
->soa
.mname
),
1056 strna(rr
->soa
.rname
),
1067 r
= asprintf(&s
, "%s %u %s",
1076 assert(rr
->loc
.version
== 0);
1078 t
= format_location(rr
->loc
.latitude
,
1087 s
= strjoin(k
, " ", t
);
1093 t
= hexmem(rr
->ds
.digest
, rr
->ds
.digest_size
);
1097 r
= asprintf(&s
, "%s %u %u %u %s",
1107 case DNS_TYPE_SSHFP
: {
1108 _cleanup_free_
char *alg
= NULL
, *key_type
= NULL
;
1110 t
= hexmem(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
1114 r
= sshfp_algorithm_to_string_alloc(rr
->sshfp
.algorithm
, &alg
);
1118 r
= sshfp_key_type_to_string_alloc(rr
->sshfp
.fptype
, &key_type
);
1122 r
= asprintf(&s
, "%s "SSHFP_ALGORITHM_FMT
" "SSHFP_KEY_TYPE_FMT
" %s",
1123 k
, alg
, key_type
, t
);
1129 case DNS_TYPE_DNSKEY
: {
1130 _cleanup_free_
char *alg
= NULL
;
1133 key_tag
= dnssec_keytag(rr
, true);
1135 r
= dnssec_algorithm_to_string_alloc(rr
->dnskey
.algorithm
, &alg
);
1139 r
= asprintf(&t
, "%s %u %u %s",
1142 rr
->dnskey
.protocol
,
1147 r
= base64_append(&t
, r
,
1148 rr
->dnskey
.key
, rr
->dnskey
.key_size
,
1153 r
= asprintf(&s
, "%s\n"
1154 " -- Flags:%s%s%s\n"
1157 rr
->dnskey
.flags
& DNSKEY_FLAG_SEP
? " SEP" : "",
1158 rr
->dnskey
.flags
& DNSKEY_FLAG_REVOKE
? " REVOKE" : "",
1159 rr
->dnskey
.flags
& DNSKEY_FLAG_ZONE_KEY
? " ZONE_KEY" : "",
1167 case DNS_TYPE_RRSIG
: {
1168 _cleanup_free_
char *alg
= NULL
;
1169 char expiration
[STRLEN("YYYYMMDDHHmmSS") + 1], inception
[STRLEN("YYYYMMDDHHmmSS") + 1];
1172 type
= dns_type_to_string(rr
->rrsig
.type_covered
);
1174 r
= dnssec_algorithm_to_string_alloc(rr
->rrsig
.algorithm
, &alg
);
1178 r
= format_timestamp_dns(expiration
, sizeof(expiration
), rr
->rrsig
.expiration
);
1182 r
= format_timestamp_dns(inception
, sizeof(inception
), rr
->rrsig
.inception
);
1187 * http://tools.ietf.org/html/rfc3597#section-5 */
1189 r
= asprintf(&s
, "%s %s%.*u %s %u %u %s %s %u %s",
1192 type
? 0 : 1, type
? 0u : (unsigned) rr
->rrsig
.type_covered
,
1195 rr
->rrsig
.original_ttl
,
1203 r
= base64_append(&s
, r
,
1204 rr
->rrsig
.signature
, rr
->rrsig
.signature_size
,
1213 t
= format_types(rr
->nsec
.types
);
1217 r
= asprintf(&s
, "%s %s %s",
1219 rr
->nsec
.next_domain_name
,
1225 case DNS_TYPE_NSEC3
: {
1226 _cleanup_free_
char *salt
= NULL
, *hash
= NULL
;
1228 if (rr
->nsec3
.salt_size
> 0) {
1229 salt
= hexmem(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
);
1234 hash
= base32hexmem(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, false);
1238 t
= format_types(rr
->nsec3
.types
);
1242 r
= asprintf(&s
, "%s %"PRIu8
" %"PRIu8
" %"PRIu16
" %s %s %s",
1244 rr
->nsec3
.algorithm
,
1246 rr
->nsec3
.iterations
,
1247 rr
->nsec3
.salt_size
> 0 ? salt
: "-",
1257 t
= hexmem(rr
->tlsa
.data
, rr
->tlsa
.data_size
);
1263 " -- Cert. usage: %s\n"
1264 " -- Selector: %s\n"
1265 " -- Matching type: %s",
1267 rr
->tlsa
.cert_usage
,
1269 rr
->tlsa
.matching_type
,
1271 tlsa_cert_usage_to_string(rr
->tlsa
.cert_usage
),
1272 tlsa_selector_to_string(rr
->tlsa
.selector
),
1273 tlsa_matching_type_to_string(rr
->tlsa
.matching_type
));
1280 t
= octescape(rr
->caa
.value
, rr
->caa
.value_size
);
1284 r
= asprintf(&s
, "%s %u %s \"%s\"%s%s%s%.0u",
1289 rr
->caa
.flags
? "\n -- Flags:" : "",
1290 rr
->caa
.flags
& CAA_FLAG_CRITICAL
? " critical" : "",
1291 rr
->caa
.flags
& ~CAA_FLAG_CRITICAL
? " " : "",
1292 rr
->caa
.flags
& ~CAA_FLAG_CRITICAL
);
1299 case DNS_TYPE_HTTPS
:
1300 t
= format_svc_params(rr
->svcb
.params
);
1303 r
= asprintf(&s
, "%s %d %s %s", k
, rr
->svcb
.priority
,
1304 isempty(rr
->svcb
.target_name
) ? "." : rr
->svcb
.target_name
,
1311 case DNS_TYPE_OPENPGPKEY
:
1312 r
= asprintf(&s
, "%s", k
);
1316 r
= base64_append(&s
, r
,
1317 rr
->generic
.data
, rr
->generic
.data_size
,
1323 case DNS_TYPE_NAPTR
: {
1324 _cleanup_free_
char *tt
= NULL
, *ttt
= NULL
;
1326 t
= octescape(rr
->naptr
.flags
, SIZE_MAX
);
1330 tt
= octescape(rr
->naptr
.services
, SIZE_MAX
);
1334 ttt
= octescape(rr
->naptr
.regexp
, SIZE_MAX
);
1338 if (asprintf(&s
, "%" PRIu16
" %" PRIu16
" \"%s\" \"%s\" \"%s\" %s.",
1340 rr
->naptr
.preference
,
1344 rr
->naptr
.replacement
) < 0)
1349 /* Format as documented in RFC 3597, Section 5 */
1350 if (rr
->generic
.data_size
== 0)
1351 r
= asprintf(&s
, "%s \\# 0", k
);
1353 t
= hexmem(rr
->generic
.data
, rr
->generic
.data_size
);
1356 r
= asprintf(&s
, "%s \\# %zu %s", k
, rr
->generic
.data_size
, t
);
1366 ssize_t
dns_resource_record_payload(DnsResourceRecord
*rr
, const void **ret
) {
1370 switch (rr
->unparsable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1374 case DNS_TYPE_CNAME
:
1375 case DNS_TYPE_DNAME
:
1376 case DNS_TYPE_HINFO
:
1383 case DNS_TYPE_DNSKEY
:
1384 case DNS_TYPE_RRSIG
:
1386 case DNS_TYPE_NSEC3
:
1390 *ret
= &rr
->a
.in_addr
;
1391 return sizeof(rr
->a
.in_addr
);
1394 *ret
= &rr
->aaaa
.in6_addr
;
1395 return sizeof(rr
->aaaa
.in6_addr
);
1397 case DNS_TYPE_SSHFP
:
1398 *ret
= rr
->sshfp
.fingerprint
;
1399 return rr
->sshfp
.fingerprint_size
;
1402 *ret
= rr
->tlsa
.data
;
1403 return rr
->tlsa
.data_size
;
1405 case DNS_TYPE_OPENPGPKEY
:
1407 *ret
= rr
->generic
.data
;
1408 return rr
->generic
.data_size
;
1412 int dns_resource_record_to_wire_format(DnsResourceRecord
*rr
, bool canonical
) {
1414 _cleanup_(dns_packet_unref
) DnsPacket packet
= {
1416 .protocol
= DNS_PROTOCOL_DNS
,
1418 .refuse_compression
= true,
1419 .canonical_form
= canonical
,
1427 /* Generates the RR in wire-format, optionally in the
1428 * canonical form as discussed in the DNSSEC RFC 4034, Section
1429 * 6.2. We allocate a throw-away DnsPacket object on the stack
1430 * here, because we need some book-keeping for memory
1431 * management, and can reuse the DnsPacket serializer, that
1432 * can generate the canonical form, too, but also knows label
1433 * compression and suchlike. */
1435 if (rr
->wire_format
&& rr
->wire_format_canonical
== canonical
)
1438 r
= dns_packet_append_rr(&packet
, rr
, 0, &start
, &rds
);
1443 assert(packet
._data
);
1445 free(rr
->wire_format
);
1446 rr
->wire_format
= TAKE_PTR(packet
._data
);
1447 rr
->wire_format_size
= packet
.size
;
1448 rr
->wire_format_rdata_offset
= rds
;
1449 rr
->wire_format_canonical
= canonical
;
1454 int dns_resource_record_signer(DnsResourceRecord
*rr
, const char **ret
) {
1461 /* Returns the RRset's signer, if it is known. */
1463 if (rr
->n_skip_labels_signer
== UINT8_MAX
)
1466 n
= dns_resource_key_name(rr
->key
);
1467 r
= dns_name_skip(n
, rr
->n_skip_labels_signer
, &n
);
1477 int dns_resource_record_source(DnsResourceRecord
*rr
, const char **ret
) {
1484 /* Returns the RRset's synthesizing source, if it is known. */
1486 if (rr
->n_skip_labels_source
== UINT8_MAX
)
1489 n
= dns_resource_key_name(rr
->key
);
1490 r
= dns_name_skip(n
, rr
->n_skip_labels_source
, &n
);
1500 int dns_resource_record_is_signer(DnsResourceRecord
*rr
, const char *zone
) {
1506 r
= dns_resource_record_signer(rr
, &signer
);
1510 return dns_name_equal(zone
, signer
);
1513 int dns_resource_record_is_synthetic(DnsResourceRecord
*rr
) {
1518 /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
1520 if (rr
->n_skip_labels_source
== UINT8_MAX
)
1523 if (rr
->n_skip_labels_source
== 0)
1526 if (rr
->n_skip_labels_source
> 1)
1529 r
= dns_name_startswith(dns_resource_key_name(rr
->key
), "*");
1536 void dns_resource_record_hash_func(const DnsResourceRecord
*rr
, struct siphash
*state
) {
1539 dns_resource_key_hash_func(rr
->key
, state
);
1541 switch (rr
->unparsable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1544 siphash24_compress_typesafe(rr
->srv
.priority
, state
);
1545 siphash24_compress_typesafe(rr
->srv
.weight
, state
);
1546 siphash24_compress_typesafe(rr
->srv
.port
, state
);
1547 dns_name_hash_func(rr
->srv
.name
, state
);
1552 case DNS_TYPE_CNAME
:
1553 case DNS_TYPE_DNAME
:
1554 dns_name_hash_func(rr
->ptr
.name
, state
);
1557 case DNS_TYPE_HINFO
:
1558 string_hash_func(rr
->hinfo
.cpu
, state
);
1559 string_hash_func(rr
->hinfo
.os
, state
);
1563 case DNS_TYPE_SPF
: {
1564 LIST_FOREACH(items
, j
, rr
->txt
.items
) {
1565 siphash24_compress_safe(j
->data
, j
->length
, state
);
1567 /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
1568 * followed by "". */
1569 siphash24_compress_byte(0, state
);
1575 siphash24_compress_typesafe(rr
->a
.in_addr
, state
);
1579 siphash24_compress_typesafe(rr
->aaaa
.in6_addr
, state
);
1583 dns_name_hash_func(rr
->soa
.mname
, state
);
1584 dns_name_hash_func(rr
->soa
.rname
, state
);
1585 siphash24_compress_typesafe(rr
->soa
.serial
, state
);
1586 siphash24_compress_typesafe(rr
->soa
.refresh
, state
);
1587 siphash24_compress_typesafe(rr
->soa
.retry
, state
);
1588 siphash24_compress_typesafe(rr
->soa
.expire
, state
);
1589 siphash24_compress_typesafe(rr
->soa
.minimum
, state
);
1593 siphash24_compress_typesafe(rr
->mx
.priority
, state
);
1594 dns_name_hash_func(rr
->mx
.exchange
, state
);
1598 siphash24_compress_typesafe(rr
->loc
.version
, state
);
1599 siphash24_compress_typesafe(rr
->loc
.size
, state
);
1600 siphash24_compress_typesafe(rr
->loc
.horiz_pre
, state
);
1601 siphash24_compress_typesafe(rr
->loc
.vert_pre
, state
);
1602 siphash24_compress_typesafe(rr
->loc
.latitude
, state
);
1603 siphash24_compress_typesafe(rr
->loc
.longitude
, state
);
1604 siphash24_compress_typesafe(rr
->loc
.altitude
, state
);
1607 case DNS_TYPE_SSHFP
:
1608 siphash24_compress_typesafe(rr
->sshfp
.algorithm
, state
);
1609 siphash24_compress_typesafe(rr
->sshfp
.fptype
, state
);
1610 siphash24_compress_safe(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
, state
);
1613 case DNS_TYPE_DNSKEY
:
1614 siphash24_compress_typesafe(rr
->dnskey
.flags
, state
);
1615 siphash24_compress_typesafe(rr
->dnskey
.protocol
, state
);
1616 siphash24_compress_typesafe(rr
->dnskey
.algorithm
, state
);
1617 siphash24_compress_safe(rr
->dnskey
.key
, rr
->dnskey
.key_size
, state
);
1620 case DNS_TYPE_RRSIG
:
1621 siphash24_compress_typesafe(rr
->rrsig
.type_covered
, state
);
1622 siphash24_compress_typesafe(rr
->rrsig
.algorithm
, state
);
1623 siphash24_compress_typesafe(rr
->rrsig
.labels
, state
);
1624 siphash24_compress_typesafe(rr
->rrsig
.original_ttl
, state
);
1625 siphash24_compress_typesafe(rr
->rrsig
.expiration
, state
);
1626 siphash24_compress_typesafe(rr
->rrsig
.inception
, state
);
1627 siphash24_compress_typesafe(rr
->rrsig
.key_tag
, state
);
1628 dns_name_hash_func(rr
->rrsig
.signer
, state
);
1629 siphash24_compress_safe(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
, state
);
1633 dns_name_hash_func(rr
->nsec
.next_domain_name
, state
);
1634 /* FIXME: we leave out the type bitmap here. Hash
1635 * would be better if we'd take it into account
1640 siphash24_compress_typesafe(rr
->ds
.key_tag
, state
);
1641 siphash24_compress_typesafe(rr
->ds
.algorithm
, state
);
1642 siphash24_compress_typesafe(rr
->ds
.digest_type
, state
);
1643 siphash24_compress_safe(rr
->ds
.digest
, rr
->ds
.digest_size
, state
);
1646 case DNS_TYPE_NSEC3
:
1647 siphash24_compress_typesafe(rr
->nsec3
.algorithm
, state
);
1648 siphash24_compress_typesafe(rr
->nsec3
.flags
, state
);
1649 siphash24_compress_typesafe(rr
->nsec3
.iterations
, state
);
1650 siphash24_compress_safe(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
, state
);
1651 siphash24_compress_safe(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, state
);
1652 /* FIXME: We leave the bitmaps out */
1656 siphash24_compress_typesafe(rr
->tlsa
.cert_usage
, state
);
1657 siphash24_compress_typesafe(rr
->tlsa
.selector
, state
);
1658 siphash24_compress_typesafe(rr
->tlsa
.matching_type
, state
);
1659 siphash24_compress_safe(rr
->tlsa
.data
, rr
->tlsa
.data_size
, state
);
1663 case DNS_TYPE_HTTPS
:
1664 dns_name_hash_func(rr
->svcb
.target_name
, state
);
1665 siphash24_compress_typesafe(rr
->svcb
.priority
, state
);
1666 LIST_FOREACH(params
, j
, rr
->svcb
.params
) {
1667 siphash24_compress_typesafe(j
->key
, state
);
1668 siphash24_compress_safe(j
->value
, j
->length
, state
);
1673 siphash24_compress_typesafe(rr
->caa
.flags
, state
);
1674 string_hash_func(rr
->caa
.tag
, state
);
1675 siphash24_compress_safe(rr
->caa
.value
, rr
->caa
.value_size
, state
);
1678 case DNS_TYPE_NAPTR
:
1679 siphash24_compress_typesafe(rr
->naptr
.order
, state
);
1680 siphash24_compress_typesafe(rr
->naptr
.preference
, state
);
1681 string_hash_func(rr
->naptr
.flags
, state
);
1682 string_hash_func(rr
->naptr
.services
, state
);
1683 string_hash_func(rr
->naptr
.regexp
, state
);
1684 dns_name_hash_func(rr
->naptr
.replacement
, state
);
1687 case DNS_TYPE_OPENPGPKEY
:
1689 siphash24_compress_safe(rr
->generic
.data
, rr
->generic
.data_size
, state
);
1693 int dns_resource_record_compare_func(const DnsResourceRecord
*x
, const DnsResourceRecord
*y
) {
1696 r
= dns_resource_key_compare_func(x
->key
, y
->key
);
1700 if (dns_resource_record_payload_equal(x
, y
) > 0)
1703 /* We still use CMP() here, even though don't implement proper
1704 * ordering, since the hashtable doesn't need ordering anyway. */
1708 DEFINE_HASH_OPS_WITH_KEY_DESTRUCTOR(
1709 dns_resource_record_hash_ops
,
1711 dns_resource_record_hash_func
,
1712 dns_resource_record_compare_func
,
1713 dns_resource_record_unref
);
1715 DEFINE_HASH_OPS_FULL(
1716 dns_resource_record_hash_ops_by_key
,
1718 dns_resource_key_hash_func
,
1719 dns_resource_key_compare_func
,
1720 dns_resource_key_unref
,
1722 dns_resource_record_unref
);
1724 DnsResourceRecord
*dns_resource_record_copy(DnsResourceRecord
*rr
) {
1725 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*copy
= NULL
;
1726 DnsResourceRecord
*t
;
1730 copy
= dns_resource_record_new(rr
->key
);
1734 copy
->ttl
= rr
->ttl
;
1735 copy
->expiry
= rr
->expiry
;
1736 copy
->n_skip_labels_signer
= rr
->n_skip_labels_signer
;
1737 copy
->n_skip_labels_source
= rr
->n_skip_labels_source
;
1738 copy
->unparsable
= rr
->unparsable
;
1740 switch (rr
->unparsable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1743 copy
->srv
.priority
= rr
->srv
.priority
;
1744 copy
->srv
.weight
= rr
->srv
.weight
;
1745 copy
->srv
.port
= rr
->srv
.port
;
1746 copy
->srv
.name
= strdup(rr
->srv
.name
);
1747 if (!copy
->srv
.name
)
1753 case DNS_TYPE_CNAME
:
1754 case DNS_TYPE_DNAME
:
1755 copy
->ptr
.name
= strdup(rr
->ptr
.name
);
1756 if (!copy
->ptr
.name
)
1760 case DNS_TYPE_HINFO
:
1761 copy
->hinfo
.cpu
= strdup(rr
->hinfo
.cpu
);
1762 if (!copy
->hinfo
.cpu
)
1765 copy
->hinfo
.os
= strdup(rr
->hinfo
.os
);
1766 if (!copy
->hinfo
.os
)
1772 copy
->txt
.items
= dns_txt_item_copy(rr
->txt
.items
);
1773 if (!copy
->txt
.items
)
1782 copy
->aaaa
= rr
->aaaa
;
1786 copy
->soa
.mname
= strdup(rr
->soa
.mname
);
1787 if (!copy
->soa
.mname
)
1789 copy
->soa
.rname
= strdup(rr
->soa
.rname
);
1790 if (!copy
->soa
.rname
)
1792 copy
->soa
.serial
= rr
->soa
.serial
;
1793 copy
->soa
.refresh
= rr
->soa
.refresh
;
1794 copy
->soa
.retry
= rr
->soa
.retry
;
1795 copy
->soa
.expire
= rr
->soa
.expire
;
1796 copy
->soa
.minimum
= rr
->soa
.minimum
;
1800 copy
->mx
.priority
= rr
->mx
.priority
;
1801 copy
->mx
.exchange
= strdup(rr
->mx
.exchange
);
1802 if (!copy
->mx
.exchange
)
1807 copy
->loc
= rr
->loc
;
1810 case DNS_TYPE_SSHFP
:
1811 copy
->sshfp
.algorithm
= rr
->sshfp
.algorithm
;
1812 copy
->sshfp
.fptype
= rr
->sshfp
.fptype
;
1813 copy
->sshfp
.fingerprint
= memdup(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
1814 if (!copy
->sshfp
.fingerprint
)
1816 copy
->sshfp
.fingerprint_size
= rr
->sshfp
.fingerprint_size
;
1819 case DNS_TYPE_DNSKEY
:
1820 copy
->dnskey
.flags
= rr
->dnskey
.flags
;
1821 copy
->dnskey
.protocol
= rr
->dnskey
.protocol
;
1822 copy
->dnskey
.algorithm
= rr
->dnskey
.algorithm
;
1823 copy
->dnskey
.key
= memdup(rr
->dnskey
.key
, rr
->dnskey
.key_size
);
1824 if (!copy
->dnskey
.key
)
1826 copy
->dnskey
.key_size
= rr
->dnskey
.key_size
;
1829 case DNS_TYPE_RRSIG
:
1830 copy
->rrsig
.type_covered
= rr
->rrsig
.type_covered
;
1831 copy
->rrsig
.algorithm
= rr
->rrsig
.algorithm
;
1832 copy
->rrsig
.labels
= rr
->rrsig
.labels
;
1833 copy
->rrsig
.original_ttl
= rr
->rrsig
.original_ttl
;
1834 copy
->rrsig
.expiration
= rr
->rrsig
.expiration
;
1835 copy
->rrsig
.inception
= rr
->rrsig
.inception
;
1836 copy
->rrsig
.key_tag
= rr
->rrsig
.key_tag
;
1837 copy
->rrsig
.signer
= strdup(rr
->rrsig
.signer
);
1838 if (!copy
->rrsig
.signer
)
1840 copy
->rrsig
.signature
= memdup(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
);
1841 if (!copy
->rrsig
.signature
)
1843 copy
->rrsig
.signature_size
= rr
->rrsig
.signature_size
;
1847 copy
->nsec
.next_domain_name
= strdup(rr
->nsec
.next_domain_name
);
1848 if (!copy
->nsec
.next_domain_name
)
1850 if (rr
->nsec
.types
) {
1851 copy
->nsec
.types
= bitmap_copy(rr
->nsec
.types
);
1852 if (!copy
->nsec
.types
)
1858 copy
->ds
.key_tag
= rr
->ds
.key_tag
;
1859 copy
->ds
.algorithm
= rr
->ds
.algorithm
;
1860 copy
->ds
.digest_type
= rr
->ds
.digest_type
;
1861 copy
->ds
.digest
= memdup(rr
->ds
.digest
, rr
->ds
.digest_size
);
1862 if (!copy
->ds
.digest
)
1864 copy
->ds
.digest_size
= rr
->ds
.digest_size
;
1867 case DNS_TYPE_NSEC3
:
1868 copy
->nsec3
.algorithm
= rr
->nsec3
.algorithm
;
1869 copy
->nsec3
.flags
= rr
->nsec3
.flags
;
1870 copy
->nsec3
.iterations
= rr
->nsec3
.iterations
;
1871 copy
->nsec3
.salt
= memdup(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
);
1872 if (!copy
->nsec3
.salt
)
1874 copy
->nsec3
.salt_size
= rr
->nsec3
.salt_size
;
1875 copy
->nsec3
.next_hashed_name
= memdup(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
);
1876 if (!copy
->nsec3
.next_hashed_name
)
1878 copy
->nsec3
.next_hashed_name_size
= rr
->nsec3
.next_hashed_name_size
;
1879 if (rr
->nsec3
.types
) {
1880 copy
->nsec3
.types
= bitmap_copy(rr
->nsec3
.types
);
1881 if (!copy
->nsec3
.types
)
1887 copy
->tlsa
.cert_usage
= rr
->tlsa
.cert_usage
;
1888 copy
->tlsa
.selector
= rr
->tlsa
.selector
;
1889 copy
->tlsa
.matching_type
= rr
->tlsa
.matching_type
;
1890 copy
->tlsa
.data
= memdup(rr
->tlsa
.data
, rr
->tlsa
.data_size
);
1891 if (!copy
->tlsa
.data
)
1893 copy
->tlsa
.data_size
= rr
->tlsa
.data_size
;
1897 copy
->caa
.flags
= rr
->caa
.flags
;
1898 copy
->caa
.tag
= strdup(rr
->caa
.tag
);
1901 copy
->caa
.value
= memdup(rr
->caa
.value
, rr
->caa
.value_size
);
1902 if (!copy
->caa
.value
)
1904 copy
->caa
.value_size
= rr
->caa
.value_size
;
1908 case DNS_TYPE_HTTPS
:
1909 copy
->svcb
.priority
= rr
->svcb
.priority
;
1910 copy
->svcb
.target_name
= strdup(rr
->svcb
.target_name
);
1911 if (!copy
->svcb
.target_name
)
1913 copy
->svcb
.params
= dns_svc_params_copy(rr
->svcb
.params
);
1914 if (rr
->svcb
.params
&& !copy
->svcb
.params
)
1918 case DNS_TYPE_NAPTR
:
1919 copy
->naptr
.order
= rr
->naptr
.order
;
1920 copy
->naptr
.preference
= rr
->naptr
.preference
;
1921 copy
->naptr
.flags
= strdup(rr
->naptr
.flags
);
1922 if (!copy
->naptr
.flags
)
1924 copy
->naptr
.services
= strdup(rr
->naptr
.services
);
1925 if (!copy
->naptr
.services
)
1927 copy
->naptr
.regexp
= strdup(rr
->naptr
.regexp
);
1928 if (!copy
->naptr
.regexp
)
1930 copy
->naptr
.replacement
= strdup(rr
->naptr
.replacement
);
1931 if (!copy
->naptr
.replacement
)
1937 copy
->generic
.data
= memdup(rr
->generic
.data
, rr
->generic
.data_size
);
1938 if (!copy
->generic
.data
)
1940 copy
->generic
.data_size
= rr
->generic
.data_size
;
1948 int dns_resource_record_clamp_ttl(DnsResourceRecord
**rr
, uint32_t max_ttl
) {
1949 DnsResourceRecord
*old_rr
, *new_rr
;
1955 if (old_rr
->key
->type
== DNS_TYPE_OPT
)
1958 new_ttl
= MIN(old_rr
->ttl
, max_ttl
);
1959 if (new_ttl
== old_rr
->ttl
)
1962 if (old_rr
->n_ref
== 1) {
1963 /* Patch in place */
1964 old_rr
->ttl
= new_ttl
;
1968 new_rr
= dns_resource_record_copy(old_rr
);
1972 new_rr
->ttl
= new_ttl
;
1974 DNS_RR_REPLACE(*rr
, new_rr
);
1978 bool dns_resource_record_is_link_local_address(DnsResourceRecord
*rr
) {
1981 if (rr
->key
->class != DNS_CLASS_IN
)
1984 if (rr
->key
->type
== DNS_TYPE_A
)
1985 return in4_addr_is_link_local(&rr
->a
.in_addr
);
1987 if (rr
->key
->type
== DNS_TYPE_AAAA
)
1988 return in6_addr_is_link_local(&rr
->aaaa
.in6_addr
);
1993 int dns_resource_record_get_cname_target(DnsResourceKey
*key
, DnsResourceRecord
*cname
, char **ret
) {
1994 _cleanup_free_
char *d
= NULL
;
2000 /* Checks if the RR `cname` is a CNAME/DNAME RR that matches the specified `key`. If so, returns the
2001 * target domain. If not, returns -EUNATCH */
2003 if (key
->class != cname
->key
->class && key
->class != DNS_CLASS_ANY
)
2006 if (!dns_type_may_redirect(key
->type
)) /* This key type is not subject to CNAME/DNAME redirection?
2007 * Then let's refuse right-away */
2010 if (cname
->key
->type
== DNS_TYPE_CNAME
) {
2011 r
= dns_name_equal(dns_resource_key_name(key
),
2012 dns_resource_key_name(cname
->key
));
2016 return -EUNATCH
; /* CNAME RR key doesn't actually match the original key */
2018 d
= strdup(cname
->cname
.name
);
2022 } else if (cname
->key
->type
== DNS_TYPE_DNAME
) {
2024 r
= dns_name_change_suffix(
2025 dns_resource_key_name(key
),
2026 dns_resource_key_name(cname
->key
),
2032 return -EUNATCH
; /* DNAME RR key doesn't actually match the original key */
2035 return -EUNATCH
; /* Not a CNAME/DNAME RR, hence doesn't match the proposition either */
2041 DnsTxtItem
*dns_txt_item_free_all(DnsTxtItem
*first
) {
2042 LIST_FOREACH(items
, i
, first
)
2048 DnsSvcParam
*dns_svc_param_free_all(DnsSvcParam
*first
) {
2049 LIST_FOREACH(params
, i
, first
)
2055 bool dns_txt_item_equal(DnsTxtItem
*a
, DnsTxtItem
*b
) {
2061 LIST_FOREACH(items
, aa
, a
) {
2065 if (memcmp_nn(aa
->data
, aa
->length
, bb
->data
, bb
->length
) != 0)
2068 bb
= bb
->items_next
;
2074 DnsTxtItem
*dns_txt_item_copy(DnsTxtItem
*first
) {
2075 DnsTxtItem
*copy
= NULL
, *end
= NULL
;
2077 LIST_FOREACH(items
, i
, first
) {
2080 j
= memdup(i
, offsetof(DnsTxtItem
, data
) + i
->length
+ 1);
2082 return dns_txt_item_free_all(copy
);
2084 LIST_INSERT_AFTER(items
, copy
, end
, j
);
2091 bool dns_svc_params_equal(DnsSvcParam
*a
, DnsSvcParam
*b
) {
2092 DnsSvcParam
*bb
= b
;
2097 LIST_FOREACH(params
, aa
, a
) {
2101 if (aa
->key
!= bb
->key
)
2104 if (memcmp_nn(aa
->value
, aa
->length
, bb
->value
, bb
->length
) != 0)
2107 bb
= bb
->params_next
;
2113 DnsSvcParam
*dns_svc_params_copy(DnsSvcParam
*first
) {
2114 DnsSvcParam
*copy
= NULL
, *end
= NULL
;
2116 LIST_FOREACH(params
, i
, first
) {
2119 j
= memdup(i
, offsetof(DnsSvcParam
, value
) + i
->length
);
2121 return dns_svc_param_free_all(copy
);
2123 LIST_INSERT_AFTER(params
, copy
, end
, j
);
2130 int dns_txt_item_new_empty(DnsTxtItem
**ret
) {
2135 /* RFC 6763, section 6.1 suggests to treat
2136 * empty TXT RRs as equivalent to a TXT record
2137 * with a single empty string. */
2139 i
= malloc0(offsetof(DnsTxtItem
, data
) + 1); /* for safety reasons we add an extra NUL byte */
2147 int dns_resource_record_new_from_raw(DnsResourceRecord
**ret
, const void *data
, size_t size
) {
2148 _cleanup_(dns_packet_unrefp
) DnsPacket
*p
= NULL
;
2151 r
= dns_packet_new(&p
, DNS_PROTOCOL_DNS
, 0, DNS_PACKET_SIZE_MAX
);
2155 p
->refuse_compression
= true;
2157 r
= dns_packet_append_blob(p
, data
, size
, NULL
);
2161 return dns_packet_read_rr(p
, ret
, NULL
, NULL
);
2164 int dns_resource_key_to_json(DnsResourceKey
*key
, sd_json_variant
**ret
) {
2168 return sd_json_buildo(
2170 SD_JSON_BUILD_PAIR("class", SD_JSON_BUILD_INTEGER(key
->class)),
2171 SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_INTEGER(key
->type
)),
2172 SD_JSON_BUILD_PAIR("name", SD_JSON_BUILD_STRING(dns_resource_key_name(key
))));
2175 int dns_resource_key_from_json(sd_json_variant
*v
, DnsResourceKey
**ret
) {
2182 static const sd_json_dispatch_field dispatch_table
[] = {
2183 { "class", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_uint16
, offsetof(struct params
, class), SD_JSON_MANDATORY
},
2184 { "type", _SD_JSON_VARIANT_TYPE_INVALID
, sd_json_dispatch_uint16
, offsetof(struct params
, type
), SD_JSON_MANDATORY
},
2185 { "name", SD_JSON_VARIANT_STRING
, sd_json_dispatch_const_string
, offsetof(struct params
, name
), SD_JSON_MANDATORY
},
2189 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
2196 r
= sd_json_dispatch(v
, dispatch_table
, 0, &p
);
2200 key
= dns_resource_key_new(p
.class, p
.type
, p
.name
);
2204 *ret
= TAKE_PTR(key
);
2208 static int type_bitmap_to_json(Bitmap
*b
, sd_json_variant
**ret
) {
2209 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*l
= NULL
;
2215 BITMAP_FOREACH(t
, b
) {
2216 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
2218 r
= sd_json_variant_new_unsigned(&v
, t
);
2222 r
= sd_json_variant_append_array(&l
, v
);
2228 return sd_json_variant_new_array(ret
, NULL
, 0);
2234 static int txt_to_json(DnsTxtItem
*items
, sd_json_variant
**ret
) {
2235 sd_json_variant
**elements
= NULL
;
2241 LIST_FOREACH(items
, i
, items
) {
2242 if (!GREEDY_REALLOC(elements
, n
+ 1)) {
2247 r
= sd_json_variant_new_octescape(elements
+ n
, i
->data
, i
->length
);
2254 r
= sd_json_variant_new_array(ret
, elements
, n
);
2257 sd_json_variant_unref_many(elements
, n
);
2261 static int svc_params_to_json(DnsSvcParam
*params
, sd_json_variant
**ret
) {
2262 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*w
= NULL
;
2267 LIST_FOREACH(params
, i
, params
) {
2268 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*v
= NULL
;
2269 r
= sd_json_variant_new_base64(&v
, i
->value
, i
->length
);
2273 r
= sd_json_variant_set_field(&w
, FORMAT_DNS_SVC_PARAM_KEY(i
->key
), v
);
2282 int dns_resource_record_to_json(DnsResourceRecord
*rr
, sd_json_variant
**ret
) {
2283 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*k
= NULL
;
2289 r
= dns_resource_key_to_json(rr
->key
, &k
);
2293 switch (rr
->unparsable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
2296 return sd_json_buildo(
2298 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2299 SD_JSON_BUILD_PAIR("priority", SD_JSON_BUILD_UNSIGNED(rr
->srv
.priority
)),
2300 SD_JSON_BUILD_PAIR("weight", SD_JSON_BUILD_UNSIGNED(rr
->srv
.weight
)),
2301 SD_JSON_BUILD_PAIR("port", SD_JSON_BUILD_UNSIGNED(rr
->srv
.port
)),
2302 SD_JSON_BUILD_PAIR("name", SD_JSON_BUILD_STRING(rr
->srv
.name
)));
2306 case DNS_TYPE_CNAME
:
2307 case DNS_TYPE_DNAME
:
2308 return sd_json_buildo(
2310 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2311 SD_JSON_BUILD_PAIR("name", SD_JSON_BUILD_STRING(rr
->ptr
.name
)));
2313 case DNS_TYPE_HINFO
:
2314 return sd_json_buildo(
2316 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2317 SD_JSON_BUILD_PAIR("cpu", SD_JSON_BUILD_STRING(rr
->hinfo
.cpu
)),
2318 SD_JSON_BUILD_PAIR("os", SD_JSON_BUILD_STRING(rr
->hinfo
.os
)));
2321 case DNS_TYPE_TXT
: {
2322 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*l
= NULL
;
2324 r
= txt_to_json(rr
->txt
.items
, &l
);
2328 return sd_json_buildo(
2330 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2331 SD_JSON_BUILD_PAIR("items", SD_JSON_BUILD_VARIANT(l
)));
2335 return sd_json_buildo(
2337 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2338 SD_JSON_BUILD_PAIR("address", JSON_BUILD_IN4_ADDR(&rr
->a
.in_addr
)));
2341 return sd_json_buildo(
2343 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2344 SD_JSON_BUILD_PAIR("address", JSON_BUILD_IN6_ADDR(&rr
->aaaa
.in6_addr
)));
2347 return sd_json_buildo(
2349 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2350 SD_JSON_BUILD_PAIR("mname", SD_JSON_BUILD_STRING(rr
->soa
.mname
)),
2351 SD_JSON_BUILD_PAIR("rname", SD_JSON_BUILD_STRING(rr
->soa
.rname
)),
2352 SD_JSON_BUILD_PAIR("serial", SD_JSON_BUILD_UNSIGNED(rr
->soa
.serial
)),
2353 SD_JSON_BUILD_PAIR("refresh", SD_JSON_BUILD_UNSIGNED(rr
->soa
.refresh
)),
2354 SD_JSON_BUILD_PAIR("expire", SD_JSON_BUILD_UNSIGNED(rr
->soa
.retry
)),
2355 SD_JSON_BUILD_PAIR("minimum", SD_JSON_BUILD_UNSIGNED(rr
->soa
.minimum
)));
2358 return sd_json_buildo(
2360 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2361 SD_JSON_BUILD_PAIR("priority", SD_JSON_BUILD_UNSIGNED(rr
->mx
.priority
)),
2362 SD_JSON_BUILD_PAIR("exchange", SD_JSON_BUILD_STRING(rr
->mx
.exchange
)));
2364 return sd_json_buildo(
2366 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2367 SD_JSON_BUILD_PAIR("version", SD_JSON_BUILD_UNSIGNED(rr
->loc
.version
)),
2368 SD_JSON_BUILD_PAIR("size", SD_JSON_BUILD_UNSIGNED(rr
->loc
.size
)),
2369 SD_JSON_BUILD_PAIR("horiz_pre", SD_JSON_BUILD_UNSIGNED(rr
->loc
.horiz_pre
)),
2370 SD_JSON_BUILD_PAIR("vert_pre", SD_JSON_BUILD_UNSIGNED(rr
->loc
.vert_pre
)),
2371 SD_JSON_BUILD_PAIR("latitude", SD_JSON_BUILD_UNSIGNED(rr
->loc
.latitude
)),
2372 SD_JSON_BUILD_PAIR("longitude", SD_JSON_BUILD_UNSIGNED(rr
->loc
.longitude
)),
2373 SD_JSON_BUILD_PAIR("altitude", SD_JSON_BUILD_UNSIGNED(rr
->loc
.altitude
)));
2376 return sd_json_buildo(
2378 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2379 SD_JSON_BUILD_PAIR("keyTag", SD_JSON_BUILD_UNSIGNED(rr
->ds
.key_tag
)),
2380 SD_JSON_BUILD_PAIR("algorithm", SD_JSON_BUILD_UNSIGNED(rr
->ds
.algorithm
)),
2381 SD_JSON_BUILD_PAIR("digestType", SD_JSON_BUILD_UNSIGNED(rr
->ds
.digest_type
)),
2382 SD_JSON_BUILD_PAIR("digest", SD_JSON_BUILD_HEX(rr
->ds
.digest
, rr
->ds
.digest_size
)));
2384 case DNS_TYPE_SSHFP
:
2385 return sd_json_buildo(
2387 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2388 SD_JSON_BUILD_PAIR("algorithm", SD_JSON_BUILD_UNSIGNED(rr
->sshfp
.algorithm
)),
2389 SD_JSON_BUILD_PAIR("fptype", SD_JSON_BUILD_UNSIGNED(rr
->sshfp
.fptype
)),
2390 SD_JSON_BUILD_PAIR("fingerprint", SD_JSON_BUILD_HEX(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
)));
2392 case DNS_TYPE_DNSKEY
:
2393 return sd_json_buildo(
2395 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2396 SD_JSON_BUILD_PAIR("flags", SD_JSON_BUILD_UNSIGNED(rr
->dnskey
.flags
)),
2397 SD_JSON_BUILD_PAIR("protocol", SD_JSON_BUILD_UNSIGNED(rr
->dnskey
.protocol
)),
2398 SD_JSON_BUILD_PAIR("algorithm", SD_JSON_BUILD_UNSIGNED(rr
->dnskey
.algorithm
)),
2399 SD_JSON_BUILD_PAIR("dnskey", SD_JSON_BUILD_BASE64(rr
->dnskey
.key
, rr
->dnskey
.key_size
)));
2401 case DNS_TYPE_RRSIG
:
2402 return sd_json_buildo(
2404 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2405 SD_JSON_BUILD_PAIR("signer", SD_JSON_BUILD_STRING(rr
->rrsig
.signer
)),
2406 SD_JSON_BUILD_PAIR("typeCovered", SD_JSON_BUILD_UNSIGNED(rr
->rrsig
.type_covered
)),
2407 SD_JSON_BUILD_PAIR("algorithm", SD_JSON_BUILD_UNSIGNED(rr
->rrsig
.algorithm
)),
2408 SD_JSON_BUILD_PAIR("labels", SD_JSON_BUILD_UNSIGNED(rr
->rrsig
.labels
)),
2409 SD_JSON_BUILD_PAIR("originalTtl", SD_JSON_BUILD_UNSIGNED(rr
->rrsig
.original_ttl
)),
2410 SD_JSON_BUILD_PAIR("expiration", SD_JSON_BUILD_UNSIGNED(rr
->rrsig
.expiration
)),
2411 SD_JSON_BUILD_PAIR("inception", SD_JSON_BUILD_UNSIGNED(rr
->rrsig
.inception
)),
2412 SD_JSON_BUILD_PAIR("keyTag", SD_JSON_BUILD_UNSIGNED(rr
->rrsig
.key_tag
)),
2413 SD_JSON_BUILD_PAIR("signature", SD_JSON_BUILD_BASE64(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
)));
2415 case DNS_TYPE_NSEC
: {
2416 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*bm
= NULL
;
2418 r
= type_bitmap_to_json(rr
->nsec
.types
, &bm
);
2422 return sd_json_buildo(
2424 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2425 SD_JSON_BUILD_PAIR("nextDomain", SD_JSON_BUILD_STRING(rr
->nsec
.next_domain_name
)),
2426 SD_JSON_BUILD_PAIR("types", SD_JSON_BUILD_VARIANT(bm
)));
2429 case DNS_TYPE_NSEC3
: {
2430 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*bm
= NULL
;
2432 r
= type_bitmap_to_json(rr
->nsec3
.types
, &bm
);
2436 return sd_json_buildo(
2438 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2439 SD_JSON_BUILD_PAIR("algorithm", SD_JSON_BUILD_UNSIGNED(rr
->nsec3
.algorithm
)),
2440 SD_JSON_BUILD_PAIR("flags", SD_JSON_BUILD_UNSIGNED(rr
->nsec3
.flags
)),
2441 SD_JSON_BUILD_PAIR("iterations", SD_JSON_BUILD_UNSIGNED(rr
->nsec3
.iterations
)),
2442 SD_JSON_BUILD_PAIR("salt", SD_JSON_BUILD_HEX(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
)),
2443 SD_JSON_BUILD_PAIR("hash", SD_JSON_BUILD_BASE32HEX(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
)),
2444 SD_JSON_BUILD_PAIR("types", SD_JSON_BUILD_VARIANT(bm
)));
2448 return sd_json_buildo(
2450 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2451 SD_JSON_BUILD_PAIR("certUsage", SD_JSON_BUILD_UNSIGNED(rr
->tlsa
.cert_usage
)),
2452 SD_JSON_BUILD_PAIR("selector", SD_JSON_BUILD_UNSIGNED(rr
->tlsa
.selector
)),
2453 SD_JSON_BUILD_PAIR("matchingType", SD_JSON_BUILD_UNSIGNED(rr
->tlsa
.matching_type
)),
2454 SD_JSON_BUILD_PAIR("data", SD_JSON_BUILD_HEX(rr
->tlsa
.data
, rr
->tlsa
.data_size
)));
2457 case DNS_TYPE_HTTPS
: {
2458 _cleanup_(sd_json_variant_unrefp
) sd_json_variant
*p
= NULL
;
2459 r
= svc_params_to_json(rr
->svcb
.params
, &p
);
2463 return sd_json_buildo(
2465 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2466 SD_JSON_BUILD_PAIR("priority", SD_JSON_BUILD_UNSIGNED(rr
->svcb
.priority
)),
2467 SD_JSON_BUILD_PAIR("target", SD_JSON_BUILD_STRING(rr
->svcb
.target_name
)),
2468 SD_JSON_BUILD_PAIR("svcparams", SD_JSON_BUILD_VARIANT(p
)));
2472 return sd_json_buildo(
2474 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2475 SD_JSON_BUILD_PAIR("flags", SD_JSON_BUILD_UNSIGNED(rr
->caa
.flags
)),
2476 SD_JSON_BUILD_PAIR("tag", SD_JSON_BUILD_STRING(rr
->caa
.tag
)),
2477 SD_JSON_BUILD_PAIR("value", SD_JSON_BUILD_OCTESCAPE(rr
->caa
.value
, rr
->caa
.value_size
)));
2479 case DNS_TYPE_NAPTR
:
2480 return sd_json_buildo(
2482 SD_JSON_BUILD_PAIR("key", SD_JSON_BUILD_VARIANT(k
)),
2483 SD_JSON_BUILD_PAIR("order", SD_JSON_BUILD_UNSIGNED(rr
->naptr
.order
)),
2484 SD_JSON_BUILD_PAIR("preference", SD_JSON_BUILD_UNSIGNED(rr
->naptr
.preference
)),
2485 /* NB: we name this flags field here naptrFlags, because there's already another "flags" field (for example in CAA) which has a different type */
2486 SD_JSON_BUILD_PAIR("naptrFlags", SD_JSON_BUILD_STRING(rr
->naptr
.flags
)),
2487 SD_JSON_BUILD_PAIR("services", SD_JSON_BUILD_STRING(rr
->naptr
.services
)),
2488 SD_JSON_BUILD_PAIR("regexp", SD_JSON_BUILD_STRING(rr
->naptr
.regexp
)),
2489 SD_JSON_BUILD_PAIR("replacement", SD_JSON_BUILD_STRING(rr
->naptr
.replacement
)));
2492 /* Can't provide broken-down format */
2498 static const char* const dnssec_algorithm_table
[_DNSSEC_ALGORITHM_MAX_DEFINED
] = {
2499 /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
2500 [DNSSEC_ALGORITHM_RSAMD5
] = "RSAMD5",
2501 [DNSSEC_ALGORITHM_DH
] = "DH",
2502 [DNSSEC_ALGORITHM_DSA
] = "DSA",
2503 [DNSSEC_ALGORITHM_ECC
] = "ECC",
2504 [DNSSEC_ALGORITHM_RSASHA1
] = "RSASHA1",
2505 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1
] = "DSA-NSEC3-SHA1",
2506 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1
] = "RSASHA1-NSEC3-SHA1",
2507 [DNSSEC_ALGORITHM_RSASHA256
] = "RSASHA256",
2508 [DNSSEC_ALGORITHM_RSASHA512
] = "RSASHA512",
2509 [DNSSEC_ALGORITHM_ECC_GOST
] = "ECC-GOST",
2510 [DNSSEC_ALGORITHM_ECDSAP256SHA256
] = "ECDSAP256SHA256",
2511 [DNSSEC_ALGORITHM_ECDSAP384SHA384
] = "ECDSAP384SHA384",
2512 [DNSSEC_ALGORITHM_ED25519
] = "ED25519",
2513 [DNSSEC_ALGORITHM_ED448
] = "ED448",
2514 [DNSSEC_ALGORITHM_INDIRECT
] = "INDIRECT",
2515 [DNSSEC_ALGORITHM_PRIVATEDNS
] = "PRIVATEDNS",
2516 [DNSSEC_ALGORITHM_PRIVATEOID
] = "PRIVATEOID",
2518 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm
, int, 255);
2520 static const char* const dnssec_digest_table
[_DNSSEC_DIGEST_MAX_DEFINED
] = {
2521 /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
2522 [DNSSEC_DIGEST_SHA1
] = "SHA-1",
2523 [DNSSEC_DIGEST_SHA256
] = "SHA-256",
2524 [DNSSEC_DIGEST_GOST_R_34_11_94
] = "GOST_R_34.11-94",
2525 [DNSSEC_DIGEST_SHA384
] = "SHA-384",
2527 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest
, int, 255);
2529 static const char* const sshfp_algorithm_table
[_SSHFP_ALGORITHM_MAX_DEFINED
] = {
2530 [SSHFP_ALGORITHM_RSA
] = "RSA", /* RFC 4255 */
2531 [SSHFP_ALGORITHM_DSA
] = "DSA", /* RFC 4255 */
2532 [SSHFP_ALGORITHM_ECDSA
] = "ECDSA", /* RFC 6594 */
2533 [SSHFP_ALGORITHM_ED25519
] = "Ed25519", /* RFC 7479 */
2534 [SSHFP_ALGORITHM_ED448
] = "Ed448", /* RFC 8709 */
2536 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sshfp_algorithm
, int, 255);
2538 static const char* const sshfp_key_type_table
[_SSHFP_KEY_TYPE_MAX_DEFINED
] = {
2539 [SSHFP_KEY_TYPE_SHA1
] = "SHA-1", /* RFC 4255 */
2540 [SSHFP_KEY_TYPE_SHA256
] = "SHA-256", /* RFC 4255 */
2542 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(sshfp_key_type
, int, 255);