2 This file is part of systemd.
4 Copyright 2014 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 #include "alloc-util.h"
23 #include "dns-domain.h"
25 #include "hexdecoct.h"
26 #include "resolved-dns-dnssec.h"
27 #include "resolved-dns-packet.h"
28 #include "resolved-dns-rr.h"
29 #include "string-table.h"
30 #include "string-util.h"
32 #include "terminal-util.h"
34 DnsResourceKey
* dns_resource_key_new(uint16_t class, uint16_t type
, const char *name
) {
41 k
= malloc0(sizeof(DnsResourceKey
) + l
+ 1);
49 strcpy((char*) k
+ sizeof(DnsResourceKey
), name
);
54 DnsResourceKey
* dns_resource_key_new_redirect(const DnsResourceKey
*key
, const DnsResourceRecord
*cname
) {
60 assert(IN_SET(cname
->key
->type
, DNS_TYPE_CNAME
, DNS_TYPE_DNAME
));
62 if (cname
->key
->type
== DNS_TYPE_CNAME
)
63 return dns_resource_key_new(key
->class, key
->type
, cname
->cname
.name
);
66 char *destination
= NULL
;
68 r
= dns_name_change_suffix(DNS_RESOURCE_KEY_NAME(key
), DNS_RESOURCE_KEY_NAME(cname
->key
), cname
->dname
.name
, &destination
);
72 return dns_resource_key_ref((DnsResourceKey
*) key
);
74 k
= dns_resource_key_new_consume(key
->class, key
->type
, destination
);
84 int dns_resource_key_new_append_suffix(DnsResourceKey
**ret
, DnsResourceKey
*key
, char *name
) {
85 DnsResourceKey
*new_key
;
93 if (dns_name_is_root(name
)) {
94 *ret
= dns_resource_key_ref(key
);
98 r
= dns_name_concat(DNS_RESOURCE_KEY_NAME(key
), name
, &joined
);
102 new_key
= dns_resource_key_new_consume(key
->class, key
->type
, joined
);
112 DnsResourceKey
* dns_resource_key_new_consume(uint16_t class, uint16_t type
, char *name
) {
117 k
= new0(DnsResourceKey
, 1);
129 DnsResourceKey
* dns_resource_key_ref(DnsResourceKey
*k
) {
134 /* Static/const keys created with DNS_RESOURCE_KEY_CONST will
135 * set this to -1, they should not be reffed/unreffed */
136 assert(k
->n_ref
!= (unsigned) -1);
138 assert(k
->n_ref
> 0);
144 DnsResourceKey
* dns_resource_key_unref(DnsResourceKey
*k
) {
148 assert(k
->n_ref
!= (unsigned) -1);
149 assert(k
->n_ref
> 0);
160 bool dns_resource_key_is_address(const DnsResourceKey
*key
) {
163 /* Check if this is an A or AAAA resource key */
165 return key
->class == DNS_CLASS_IN
&& IN_SET(key
->type
, DNS_TYPE_A
, DNS_TYPE_AAAA
);
168 int dns_resource_key_equal(const DnsResourceKey
*a
, const DnsResourceKey
*b
) {
174 r
= dns_name_equal(DNS_RESOURCE_KEY_NAME(a
), DNS_RESOURCE_KEY_NAME(b
));
178 if (a
->class != b
->class)
181 if (a
->type
!= b
->type
)
187 int dns_resource_key_match_rr(const DnsResourceKey
*key
, DnsResourceRecord
*rr
, const char *search_domain
) {
196 /* Checks if an rr matches the specified key. If a search
197 * domain is specified, it will also be checked if the key
198 * with the search domain suffixed might match the RR. */
200 if (rr
->key
->class != key
->class && key
->class != DNS_CLASS_ANY
)
203 if (rr
->key
->type
!= key
->type
&& key
->type
!= DNS_TYPE_ANY
)
206 r
= dns_name_equal(DNS_RESOURCE_KEY_NAME(rr
->key
), DNS_RESOURCE_KEY_NAME(key
));
211 _cleanup_free_
char *joined
= NULL
;
213 r
= dns_name_concat(DNS_RESOURCE_KEY_NAME(key
), search_domain
, &joined
);
217 return dns_name_equal(DNS_RESOURCE_KEY_NAME(rr
->key
), joined
);
223 int dns_resource_key_match_cname_or_dname(const DnsResourceKey
*key
, const DnsResourceKey
*cname
, const char *search_domain
) {
229 if (cname
->class != key
->class && key
->class != DNS_CLASS_ANY
)
232 if (cname
->type
== DNS_TYPE_CNAME
)
233 r
= dns_name_equal(DNS_RESOURCE_KEY_NAME(key
), DNS_RESOURCE_KEY_NAME(cname
));
234 else if (cname
->type
== DNS_TYPE_DNAME
)
235 r
= dns_name_endswith(DNS_RESOURCE_KEY_NAME(key
), DNS_RESOURCE_KEY_NAME(cname
));
243 _cleanup_free_
char *joined
= NULL
;
245 r
= dns_name_concat(DNS_RESOURCE_KEY_NAME(key
), search_domain
, &joined
);
249 if (cname
->type
== DNS_TYPE_CNAME
)
250 return dns_name_equal(joined
, DNS_RESOURCE_KEY_NAME(cname
));
251 else if (cname
->type
== DNS_TYPE_DNAME
)
252 return dns_name_endswith(joined
, DNS_RESOURCE_KEY_NAME(cname
));
258 int dns_resource_key_match_soa(const DnsResourceKey
*key
, const DnsResourceKey
*soa
) {
262 /* Checks whether 'soa' is a SOA record for the specified key. */
264 if (soa
->class != key
->class)
267 if (soa
->type
!= DNS_TYPE_SOA
)
270 return dns_name_endswith(DNS_RESOURCE_KEY_NAME(key
), DNS_RESOURCE_KEY_NAME(soa
));
273 static void dns_resource_key_hash_func(const void *i
, struct siphash
*state
) {
274 const DnsResourceKey
*k
= i
;
278 dns_name_hash_func(DNS_RESOURCE_KEY_NAME(k
), state
);
279 siphash24_compress(&k
->class, sizeof(k
->class), state
);
280 siphash24_compress(&k
->type
, sizeof(k
->type
), state
);
283 static int dns_resource_key_compare_func(const void *a
, const void *b
) {
284 const DnsResourceKey
*x
= a
, *y
= b
;
287 ret
= dns_name_compare_func(DNS_RESOURCE_KEY_NAME(x
), DNS_RESOURCE_KEY_NAME(y
));
291 if (x
->type
< y
->type
)
293 if (x
->type
> y
->type
)
296 if (x
->class < y
->class)
298 if (x
->class > y
->class)
304 const struct hash_ops dns_resource_key_hash_ops
= {
305 .hash
= dns_resource_key_hash_func
,
306 .compare
= dns_resource_key_compare_func
309 int dns_resource_key_to_string(const DnsResourceKey
*key
, char **ret
) {
310 char cbuf
[strlen("CLASS") + DECIMAL_STR_MAX(uint16_t)], tbuf
[strlen("TYPE") + DECIMAL_STR_MAX(uint16_t)];
311 const char *c
, *t
, *n
;
314 /* If we cannot convert the CLASS/TYPE into a known string,
315 use the format recommended by RFC 3597, Section 5. */
317 c
= dns_class_to_string(key
->class);
319 sprintf(cbuf
, "CLASS%u", key
->class);
323 t
= dns_type_to_string(key
->type
);
325 sprintf(tbuf
, "TYPE%u", key
->type
);
329 n
= DNS_RESOURCE_KEY_NAME(key
);
330 if (asprintf(&s
, "%s%s %s %-5s", n
, endswith(n
, ".") ? "" : ".", c
, t
) < 0)
337 bool dns_resource_key_reduce(DnsResourceKey
**a
, DnsResourceKey
**b
) {
341 /* Try to replace one RR key by another if they are identical, thus saving a bit of memory. Note that we do
342 * this only for RR keys, not for RRs themselves, as they carry a lot of additional metadata (where they come
343 * from, validity data, and suchlike), and cannot be replaced so easily by other RRs that have the same
344 * superficial data. */
351 /* We refuse merging const keys */
352 if ((*a
)->n_ref
== (unsigned) -1)
354 if ((*b
)->n_ref
== (unsigned) -1)
357 /* Already the same? */
361 /* Are they really identical? */
362 if (dns_resource_key_equal(*a
, *b
) <= 0)
365 /* Keep the one which already has more references. */
366 if ((*a
)->n_ref
> (*b
)->n_ref
) {
367 dns_resource_key_unref(*b
);
368 *b
= dns_resource_key_ref(*a
);
370 dns_resource_key_unref(*a
);
371 *a
= dns_resource_key_ref(*b
);
377 DnsResourceRecord
* dns_resource_record_new(DnsResourceKey
*key
) {
378 DnsResourceRecord
*rr
;
380 rr
= new0(DnsResourceRecord
, 1);
385 rr
->key
= dns_resource_key_ref(key
);
386 rr
->expiry
= USEC_INFINITY
;
387 rr
->n_skip_labels_signer
= rr
->n_skip_labels_source
= (unsigned) -1;
392 DnsResourceRecord
* dns_resource_record_new_full(uint16_t class, uint16_t type
, const char *name
) {
393 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
395 key
= dns_resource_key_new(class, type
, name
);
399 return dns_resource_record_new(key
);
402 DnsResourceRecord
* dns_resource_record_ref(DnsResourceRecord
*rr
) {
406 assert(rr
->n_ref
> 0);
412 DnsResourceRecord
* dns_resource_record_unref(DnsResourceRecord
*rr
) {
416 assert(rr
->n_ref
> 0);
424 switch(rr
->key
->type
) {
444 dns_txt_item_free_all(rr
->txt
.items
);
453 free(rr
->mx
.exchange
);
461 free(rr
->sshfp
.fingerprint
);
464 case DNS_TYPE_DNSKEY
:
465 free(rr
->dnskey
.key
);
469 free(rr
->rrsig
.signer
);
470 free(rr
->rrsig
.signature
);
474 free(rr
->nsec
.next_domain_name
);
475 bitmap_free(rr
->nsec
.types
);
479 free(rr
->nsec3
.next_hashed_name
);
480 free(rr
->nsec3
.salt
);
481 bitmap_free(rr
->nsec3
.types
);
493 case DNS_TYPE_OPENPGPKEY
:
495 free(rr
->generic
.data
);
498 free(rr
->wire_format
);
499 dns_resource_key_unref(rr
->key
);
508 int dns_resource_record_new_reverse(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *hostname
) {
509 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
510 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
511 _cleanup_free_
char *ptr
= NULL
;
518 r
= dns_name_reverse(family
, address
, &ptr
);
522 key
= dns_resource_key_new_consume(DNS_CLASS_IN
, DNS_TYPE_PTR
, ptr
);
528 rr
= dns_resource_record_new(key
);
532 rr
->ptr
.name
= strdup(hostname
);
542 int dns_resource_record_new_address(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *name
) {
543 DnsResourceRecord
*rr
;
549 if (family
== AF_INET
) {
551 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, name
);
555 rr
->a
.in_addr
= address
->in
;
557 } else if (family
== AF_INET6
) {
559 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_AAAA
, name
);
563 rr
->aaaa
.in6_addr
= address
->in6
;
565 return -EAFNOSUPPORT
;
572 #define FIELD_EQUAL(a, b, field) \
573 ((a).field ## _size == (b).field ## _size && \
574 memcmp((a).field, (b).field, (a).field ## _size) == 0)
576 int dns_resource_record_equal(const DnsResourceRecord
*a
, const DnsResourceRecord
*b
) {
585 r
= dns_resource_key_equal(a
->key
, b
->key
);
589 if (a
->unparseable
!= b
->unparseable
)
592 switch (a
->unparseable
? _DNS_TYPE_INVALID
: a
->key
->type
) {
595 r
= dns_name_equal(a
->srv
.name
, b
->srv
.name
);
599 return a
->srv
.priority
== b
->srv
.priority
&&
600 a
->srv
.weight
== b
->srv
.weight
&&
601 a
->srv
.port
== b
->srv
.port
;
607 return dns_name_equal(a
->ptr
.name
, b
->ptr
.name
);
610 return strcaseeq(a
->hinfo
.cpu
, b
->hinfo
.cpu
) &&
611 strcaseeq(a
->hinfo
.os
, b
->hinfo
.os
);
613 case DNS_TYPE_SPF
: /* exactly the same as TXT */
615 return dns_txt_item_equal(a
->txt
.items
, b
->txt
.items
);
618 return memcmp(&a
->a
.in_addr
, &b
->a
.in_addr
, sizeof(struct in_addr
)) == 0;
621 return memcmp(&a
->aaaa
.in6_addr
, &b
->aaaa
.in6_addr
, sizeof(struct in6_addr
)) == 0;
624 r
= dns_name_equal(a
->soa
.mname
, b
->soa
.mname
);
627 r
= dns_name_equal(a
->soa
.rname
, b
->soa
.rname
);
631 return a
->soa
.serial
== b
->soa
.serial
&&
632 a
->soa
.refresh
== b
->soa
.refresh
&&
633 a
->soa
.retry
== b
->soa
.retry
&&
634 a
->soa
.expire
== b
->soa
.expire
&&
635 a
->soa
.minimum
== b
->soa
.minimum
;
638 if (a
->mx
.priority
!= b
->mx
.priority
)
641 return dns_name_equal(a
->mx
.exchange
, b
->mx
.exchange
);
644 assert(a
->loc
.version
== b
->loc
.version
);
646 return a
->loc
.size
== b
->loc
.size
&&
647 a
->loc
.horiz_pre
== b
->loc
.horiz_pre
&&
648 a
->loc
.vert_pre
== b
->loc
.vert_pre
&&
649 a
->loc
.latitude
== b
->loc
.latitude
&&
650 a
->loc
.longitude
== b
->loc
.longitude
&&
651 a
->loc
.altitude
== b
->loc
.altitude
;
654 return a
->ds
.key_tag
== b
->ds
.key_tag
&&
655 a
->ds
.algorithm
== b
->ds
.algorithm
&&
656 a
->ds
.digest_type
== b
->ds
.digest_type
&&
657 FIELD_EQUAL(a
->ds
, b
->ds
, digest
);
660 return a
->sshfp
.algorithm
== b
->sshfp
.algorithm
&&
661 a
->sshfp
.fptype
== b
->sshfp
.fptype
&&
662 FIELD_EQUAL(a
->sshfp
, b
->sshfp
, fingerprint
);
664 case DNS_TYPE_DNSKEY
:
665 return a
->dnskey
.flags
== b
->dnskey
.flags
&&
666 a
->dnskey
.protocol
== b
->dnskey
.protocol
&&
667 a
->dnskey
.algorithm
== b
->dnskey
.algorithm
&&
668 FIELD_EQUAL(a
->dnskey
, b
->dnskey
, key
);
671 /* do the fast comparisons first */
672 return a
->rrsig
.type_covered
== b
->rrsig
.type_covered
&&
673 a
->rrsig
.algorithm
== b
->rrsig
.algorithm
&&
674 a
->rrsig
.labels
== b
->rrsig
.labels
&&
675 a
->rrsig
.original_ttl
== b
->rrsig
.original_ttl
&&
676 a
->rrsig
.expiration
== b
->rrsig
.expiration
&&
677 a
->rrsig
.inception
== b
->rrsig
.inception
&&
678 a
->rrsig
.key_tag
== b
->rrsig
.key_tag
&&
679 FIELD_EQUAL(a
->rrsig
, b
->rrsig
, signature
) &&
680 dns_name_equal(a
->rrsig
.signer
, b
->rrsig
.signer
);
683 return dns_name_equal(a
->nsec
.next_domain_name
, b
->nsec
.next_domain_name
) &&
684 bitmap_equal(a
->nsec
.types
, b
->nsec
.types
);
687 return a
->nsec3
.algorithm
== b
->nsec3
.algorithm
&&
688 a
->nsec3
.flags
== b
->nsec3
.flags
&&
689 a
->nsec3
.iterations
== b
->nsec3
.iterations
&&
690 FIELD_EQUAL(a
->nsec3
, b
->nsec3
, salt
) &&
691 FIELD_EQUAL(a
->nsec3
, b
->nsec3
, next_hashed_name
) &&
692 bitmap_equal(a
->nsec3
.types
, b
->nsec3
.types
);
695 return a
->tlsa
.cert_usage
== b
->tlsa
.cert_usage
&&
696 a
->tlsa
.selector
== b
->tlsa
.selector
&&
697 a
->tlsa
.matching_type
== b
->tlsa
.matching_type
&&
698 FIELD_EQUAL(a
->tlsa
, b
->tlsa
, data
);
701 return FIELD_EQUAL(a
->generic
, b
->generic
, data
);
705 static char* format_location(uint32_t latitude
, uint32_t longitude
, uint32_t altitude
,
706 uint8_t size
, uint8_t horiz_pre
, uint8_t vert_pre
) {
708 char NS
= latitude
>= 1U<<31 ? 'N' : 'S';
709 char EW
= longitude
>= 1U<<31 ? 'E' : 'W';
711 int lat
= latitude
>= 1U<<31 ? (int) (latitude
- (1U<<31)) : (int) ((1U<<31) - latitude
);
712 int lon
= longitude
>= 1U<<31 ? (int) (longitude
- (1U<<31)) : (int) ((1U<<31) - longitude
);
713 double alt
= altitude
>= 10000000u ? altitude
- 10000000u : -(double)(10000000u - altitude
);
714 double siz
= (size
>> 4) * exp10((double) (size
& 0xF));
715 double hor
= (horiz_pre
>> 4) * exp10((double) (horiz_pre
& 0xF));
716 double ver
= (vert_pre
>> 4) * exp10((double) (vert_pre
& 0xF));
718 if (asprintf(&s
, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
721 (lat
% 60000) / 1000.,
725 (lon
% 60000) / 1000.,
736 static int format_timestamp_dns(char *buf
, size_t l
, time_t sec
) {
740 assert(l
> strlen("YYYYMMDDHHmmSS"));
742 if (!gmtime_r(&sec
, &tm
))
745 if (strftime(buf
, l
, "%Y%m%d%H%M%S", &tm
) <= 0)
751 static char *format_types(Bitmap
*types
) {
752 _cleanup_strv_free_
char **strv
= NULL
;
753 _cleanup_free_
char *str
= NULL
;
758 BITMAP_FOREACH(type
, types
, i
) {
759 if (dns_type_to_string(type
)) {
760 r
= strv_extend(&strv
, dns_type_to_string(type
));
766 r
= asprintf(&t
, "TYPE%u", type
);
770 r
= strv_consume(&strv
, t
);
776 str
= strv_join(strv
, " ");
780 return strjoin("( ", str
, " )", NULL
);
783 static char *format_txt(DnsTxtItem
*first
) {
788 LIST_FOREACH(items
, i
, first
)
789 c
+= i
->length
* 4 + 3;
791 p
= s
= new(char, c
);
795 LIST_FOREACH(items
, i
, first
) {
803 for (j
= 0; j
< i
->length
; j
++) {
804 if (i
->data
[j
] < ' ' || i
->data
[j
] == '"' || i
->data
[j
] >= 127) {
806 *(p
++) = '0' + (i
->data
[j
] / 100);
807 *(p
++) = '0' + ((i
->data
[j
] / 10) % 10);
808 *(p
++) = '0' + (i
->data
[j
] % 10);
820 const char *dns_resource_record_to_string(DnsResourceRecord
*rr
) {
821 _cleanup_free_
char *k
= NULL
, *t
= NULL
;
828 return rr
->to_string
;
830 r
= dns_resource_key_to_string(rr
->key
, &k
);
834 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
837 r
= asprintf(&s
, "%s %u %u %u %s",
842 strna(rr
->srv
.name
));
851 s
= strjoin(k
, " ", rr
->ptr
.name
, NULL
);
858 s
= strjoin(k
, " ", rr
->hinfo
.cpu
, " ", rr
->hinfo
.os
, NULL
);
863 case DNS_TYPE_SPF
: /* exactly the same as TXT */
865 t
= format_txt(rr
->txt
.items
);
869 s
= strjoin(k
, " ", t
, NULL
);
875 _cleanup_free_
char *x
= NULL
;
877 r
= in_addr_to_string(AF_INET
, (const union in_addr_union
*) &rr
->a
.in_addr
, &x
);
881 s
= strjoin(k
, " ", x
, NULL
);
888 r
= in_addr_to_string(AF_INET6
, (const union in_addr_union
*) &rr
->aaaa
.in6_addr
, &t
);
892 s
= strjoin(k
, " ", t
, NULL
);
898 r
= asprintf(&s
, "%s %s %s %u %u %u %u %u",
900 strna(rr
->soa
.mname
),
901 strna(rr
->soa
.rname
),
912 r
= asprintf(&s
, "%s %u %s",
921 assert(rr
->loc
.version
== 0);
923 t
= format_location(rr
->loc
.latitude
,
932 s
= strjoin(k
, " ", t
, NULL
);
938 t
= hexmem(rr
->ds
.digest
, rr
->ds
.digest_size
);
942 r
= asprintf(&s
, "%s %u %u %u %s",
953 t
= hexmem(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
957 r
= asprintf(&s
, "%s %u %u %s",
966 case DNS_TYPE_DNSKEY
: {
967 _cleanup_free_
char *alg
= NULL
;
972 key_tag
= dnssec_keytag(rr
, true);
974 r
= dnssec_algorithm_to_string_alloc(rr
->dnskey
.algorithm
, &alg
);
978 r
= asprintf(&s
, "%s %n%u %u %s %n",
988 r
= base64_append(&s
, n
,
989 rr
->dnskey
.key
, rr
->dnskey
.key_size
,
994 r
= asprintf(&ss
, "%s\n"
995 "%*s-- Flags:%s%s%s\n"
999 rr
->dnskey
.flags
& DNSKEY_FLAG_SEP
? " SEP" : "",
1000 rr
->dnskey
.flags
& DNSKEY_FLAG_REVOKE
? " REVOKE" : "",
1001 rr
->dnskey
.flags
& DNSKEY_FLAG_ZONE_KEY
? " ZONE_KEY" : "",
1012 case DNS_TYPE_RRSIG
: {
1013 _cleanup_free_
char *alg
= NULL
;
1014 char expiration
[strlen("YYYYMMDDHHmmSS") + 1], inception
[strlen("YYYYMMDDHHmmSS") + 1];
1018 type
= dns_type_to_string(rr
->rrsig
.type_covered
);
1020 r
= dnssec_algorithm_to_string_alloc(rr
->rrsig
.algorithm
, &alg
);
1024 r
= format_timestamp_dns(expiration
, sizeof(expiration
), rr
->rrsig
.expiration
);
1028 r
= format_timestamp_dns(inception
, sizeof(inception
), rr
->rrsig
.inception
);
1033 * http://tools.ietf.org/html/rfc3597#section-5 */
1035 r
= asprintf(&s
, "%s %s%.*u %s %u %u %s %s %u %s %n",
1038 type
? 0 : 1, type
? 0u : (unsigned) rr
->rrsig
.type_covered
,
1041 rr
->rrsig
.original_ttl
,
1050 r
= base64_append(&s
, n
,
1051 rr
->rrsig
.signature
, rr
->rrsig
.signature_size
,
1060 t
= format_types(rr
->nsec
.types
);
1064 r
= asprintf(&s
, "%s %s %s",
1066 rr
->nsec
.next_domain_name
,
1072 case DNS_TYPE_NSEC3
: {
1073 _cleanup_free_
char *salt
= NULL
, *hash
= NULL
;
1075 if (rr
->nsec3
.salt_size
> 0) {
1076 salt
= hexmem(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
);
1081 hash
= base32hexmem(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, false);
1085 t
= format_types(rr
->nsec3
.types
);
1089 r
= asprintf(&s
, "%s %"PRIu8
" %"PRIu8
" %"PRIu16
" %s %s %s",
1091 rr
->nsec3
.algorithm
,
1093 rr
->nsec3
.iterations
,
1094 rr
->nsec3
.salt_size
> 0 ? salt
: "-",
1103 case DNS_TYPE_TLSA
: {
1104 const char *cert_usage
, *selector
, *matching_type
;
1108 cert_usage
= tlsa_cert_usage_to_string(rr
->tlsa
.cert_usage
);
1109 selector
= tlsa_selector_to_string(rr
->tlsa
.selector
);
1110 matching_type
= tlsa_matching_type_to_string(rr
->tlsa
.matching_type
);
1112 r
= asprintf(&s
, "%s %u %u %u %n",
1114 rr
->tlsa
.cert_usage
,
1116 rr
->tlsa
.matching_type
,
1121 r
= base64_append(&s
, n
,
1122 rr
->tlsa
.data
, rr
->tlsa
.data_size
,
1127 r
= asprintf(&ss
, "%s\n"
1128 "%*s-- Cert. usage: %s\n"
1129 "%*s-- Selector: %s\n"
1130 "%*s-- Matching type: %s",
1132 n
- 6, "", cert_usage
,
1133 n
- 6, "", selector
,
1134 n
- 6, "", matching_type
);
1143 case DNS_TYPE_OPENPGPKEY
: {
1146 r
= asprintf(&s
, "%s %n",
1152 r
= base64_append(&s
, n
,
1153 rr
->generic
.data
, rr
->generic
.data_size
,
1161 t
= hexmem(rr
->generic
.data
, rr
->generic
.data_size
);
1165 /* Format as documented in RFC 3597, Section 5 */
1166 r
= asprintf(&s
, "%s \\# %zu %s", k
, rr
->generic
.data_size
, t
);
1176 int dns_resource_record_to_wire_format(DnsResourceRecord
*rr
, bool canonical
) {
1178 DnsPacket packet
= {
1180 .protocol
= DNS_PROTOCOL_DNS
,
1182 .refuse_compression
= true,
1183 .canonical_form
= canonical
,
1191 /* Generates the RR in wire-format, optionally in the
1192 * canonical form as discussed in the DNSSEC RFC 4034, Section
1193 * 6.2. We allocate a throw-away DnsPacket object on the stack
1194 * here, because we need some book-keeping for memory
1195 * management, and can reuse the DnsPacket serializer, that
1196 * can generate the canonical form, too, but also knows label
1197 * compression and suchlike. */
1199 if (rr
->wire_format
&& rr
->wire_format_canonical
== canonical
)
1202 r
= dns_packet_append_rr(&packet
, rr
, &start
, &rds
);
1207 assert(packet
._data
);
1209 free(rr
->wire_format
);
1210 rr
->wire_format
= packet
._data
;
1211 rr
->wire_format_size
= packet
.size
;
1212 rr
->wire_format_rdata_offset
= rds
;
1213 rr
->wire_format_canonical
= canonical
;
1215 packet
._data
= NULL
;
1216 dns_packet_unref(&packet
);
1221 int dns_resource_record_signer(DnsResourceRecord
*rr
, const char **ret
) {
1228 /* Returns the RRset's signer, if it is known. */
1230 if (rr
->n_skip_labels_signer
== (unsigned) -1)
1233 n
= DNS_RESOURCE_KEY_NAME(rr
->key
);
1234 r
= dns_name_skip(n
, rr
->n_skip_labels_signer
, &n
);
1244 int dns_resource_record_source(DnsResourceRecord
*rr
, const char **ret
) {
1251 /* Returns the RRset's synthesizing source, if it is known. */
1253 if (rr
->n_skip_labels_source
== (unsigned) -1)
1256 n
= DNS_RESOURCE_KEY_NAME(rr
->key
);
1257 r
= dns_name_skip(n
, rr
->n_skip_labels_source
, &n
);
1267 int dns_resource_record_is_signer(DnsResourceRecord
*rr
, const char *zone
) {
1273 r
= dns_resource_record_signer(rr
, &signer
);
1277 return dns_name_equal(zone
, signer
);
1280 int dns_resource_record_is_synthetic(DnsResourceRecord
*rr
) {
1285 /* Returns > 0 if the RR is generated from a wildcard, and is not the asterisk name itself */
1287 if (rr
->n_skip_labels_source
== (unsigned) -1)
1290 if (rr
->n_skip_labels_source
== 0)
1293 if (rr
->n_skip_labels_source
> 1)
1296 r
= dns_name_startswith(DNS_RESOURCE_KEY_NAME(rr
->key
), "*");
1303 static void dns_resource_record_hash_func(const void *i
, struct siphash
*state
) {
1304 const DnsResourceRecord
*rr
= i
;
1308 dns_resource_key_hash_func(rr
->key
, state
);
1310 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
1313 siphash24_compress(&rr
->srv
.priority
, sizeof(rr
->srv
.priority
), state
);
1314 siphash24_compress(&rr
->srv
.weight
, sizeof(rr
->srv
.weight
), state
);
1315 siphash24_compress(&rr
->srv
.port
, sizeof(rr
->srv
.port
), state
);
1316 dns_name_hash_func(rr
->srv
.name
, state
);
1321 case DNS_TYPE_CNAME
:
1322 case DNS_TYPE_DNAME
:
1323 dns_name_hash_func(rr
->ptr
.name
, state
);
1326 case DNS_TYPE_HINFO
:
1327 string_hash_func(rr
->hinfo
.cpu
, state
);
1328 string_hash_func(rr
->hinfo
.os
, state
);
1332 case DNS_TYPE_SPF
: {
1335 LIST_FOREACH(items
, j
, rr
->txt
.items
) {
1336 siphash24_compress(j
->data
, j
->length
, state
);
1338 /* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
1339 * followed by "". */
1340 siphash24_compress_byte(0, state
);
1346 siphash24_compress(&rr
->a
.in_addr
, sizeof(rr
->a
.in_addr
), state
);
1350 siphash24_compress(&rr
->aaaa
.in6_addr
, sizeof(rr
->aaaa
.in6_addr
), state
);
1354 dns_name_hash_func(rr
->soa
.mname
, state
);
1355 dns_name_hash_func(rr
->soa
.rname
, state
);
1356 siphash24_compress(&rr
->soa
.serial
, sizeof(rr
->soa
.serial
), state
);
1357 siphash24_compress(&rr
->soa
.refresh
, sizeof(rr
->soa
.refresh
), state
);
1358 siphash24_compress(&rr
->soa
.retry
, sizeof(rr
->soa
.retry
), state
);
1359 siphash24_compress(&rr
->soa
.expire
, sizeof(rr
->soa
.expire
), state
);
1360 siphash24_compress(&rr
->soa
.minimum
, sizeof(rr
->soa
.minimum
), state
);
1364 siphash24_compress(&rr
->mx
.priority
, sizeof(rr
->mx
.priority
), state
);
1365 dns_name_hash_func(rr
->mx
.exchange
, state
);
1369 siphash24_compress(&rr
->loc
.version
, sizeof(rr
->loc
.version
), state
);
1370 siphash24_compress(&rr
->loc
.size
, sizeof(rr
->loc
.size
), state
);
1371 siphash24_compress(&rr
->loc
.horiz_pre
, sizeof(rr
->loc
.horiz_pre
), state
);
1372 siphash24_compress(&rr
->loc
.vert_pre
, sizeof(rr
->loc
.vert_pre
), state
);
1373 siphash24_compress(&rr
->loc
.latitude
, sizeof(rr
->loc
.latitude
), state
);
1374 siphash24_compress(&rr
->loc
.longitude
, sizeof(rr
->loc
.longitude
), state
);
1375 siphash24_compress(&rr
->loc
.altitude
, sizeof(rr
->loc
.altitude
), state
);
1378 case DNS_TYPE_SSHFP
:
1379 siphash24_compress(&rr
->sshfp
.algorithm
, sizeof(rr
->sshfp
.algorithm
), state
);
1380 siphash24_compress(&rr
->sshfp
.fptype
, sizeof(rr
->sshfp
.fptype
), state
);
1381 siphash24_compress(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
, state
);
1384 case DNS_TYPE_DNSKEY
:
1385 siphash24_compress(&rr
->dnskey
.flags
, sizeof(rr
->dnskey
.flags
), state
);
1386 siphash24_compress(&rr
->dnskey
.protocol
, sizeof(rr
->dnskey
.protocol
), state
);
1387 siphash24_compress(&rr
->dnskey
.algorithm
, sizeof(rr
->dnskey
.algorithm
), state
);
1388 siphash24_compress(rr
->dnskey
.key
, rr
->dnskey
.key_size
, state
);
1391 case DNS_TYPE_RRSIG
:
1392 siphash24_compress(&rr
->rrsig
.type_covered
, sizeof(rr
->rrsig
.type_covered
), state
);
1393 siphash24_compress(&rr
->rrsig
.algorithm
, sizeof(rr
->rrsig
.algorithm
), state
);
1394 siphash24_compress(&rr
->rrsig
.labels
, sizeof(rr
->rrsig
.labels
), state
);
1395 siphash24_compress(&rr
->rrsig
.original_ttl
, sizeof(rr
->rrsig
.original_ttl
), state
);
1396 siphash24_compress(&rr
->rrsig
.expiration
, sizeof(rr
->rrsig
.expiration
), state
);
1397 siphash24_compress(&rr
->rrsig
.inception
, sizeof(rr
->rrsig
.inception
), state
);
1398 siphash24_compress(&rr
->rrsig
.key_tag
, sizeof(rr
->rrsig
.key_tag
), state
);
1399 dns_name_hash_func(rr
->rrsig
.signer
, state
);
1400 siphash24_compress(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
, state
);
1404 dns_name_hash_func(rr
->nsec
.next_domain_name
, state
);
1405 /* FIXME: we leave out the type bitmap here. Hash
1406 * would be better if we'd take it into account
1411 siphash24_compress(&rr
->ds
.key_tag
, sizeof(rr
->ds
.key_tag
), state
);
1412 siphash24_compress(&rr
->ds
.algorithm
, sizeof(rr
->ds
.algorithm
), state
);
1413 siphash24_compress(&rr
->ds
.digest_type
, sizeof(rr
->ds
.digest_type
), state
);
1414 siphash24_compress(rr
->ds
.digest
, rr
->ds
.digest_size
, state
);
1417 case DNS_TYPE_NSEC3
:
1418 siphash24_compress(&rr
->nsec3
.algorithm
, sizeof(rr
->nsec3
.algorithm
), state
);
1419 siphash24_compress(&rr
->nsec3
.flags
, sizeof(rr
->nsec3
.flags
), state
);
1420 siphash24_compress(&rr
->nsec3
.iterations
, sizeof(rr
->nsec3
.iterations
), state
);
1421 siphash24_compress(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
, state
);
1422 siphash24_compress(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, state
);
1423 /* FIXME: We leave the bitmaps out */
1427 siphash24_compress(&rr
->tlsa
.cert_usage
, sizeof(rr
->tlsa
.cert_usage
), state
);
1428 siphash24_compress(&rr
->tlsa
.selector
, sizeof(rr
->tlsa
.selector
), state
);
1429 siphash24_compress(&rr
->tlsa
.matching_type
, sizeof(rr
->tlsa
.matching_type
), state
);
1430 siphash24_compress(&rr
->tlsa
.data
, rr
->tlsa
.data_size
, state
);
1433 case DNS_TYPE_OPENPGPKEY
:
1435 siphash24_compress(rr
->generic
.data
, rr
->generic
.data_size
, state
);
1440 static int dns_resource_record_compare_func(const void *a
, const void *b
) {
1441 const DnsResourceRecord
*x
= a
, *y
= b
;
1444 ret
= dns_resource_key_compare_func(x
->key
, y
->key
);
1448 if (dns_resource_record_equal(x
, y
))
1451 /* This is a bit dirty, we don't implement proper ordering, but
1452 * the hashtable doesn't need ordering anyway, hence we don't
1454 return x
< y
? -1 : 1;
1457 const struct hash_ops dns_resource_record_hash_ops
= {
1458 .hash
= dns_resource_record_hash_func
,
1459 .compare
= dns_resource_record_compare_func
,
1462 DnsTxtItem
*dns_txt_item_free_all(DnsTxtItem
*i
) {
1471 return dns_txt_item_free_all(n
);
1474 bool dns_txt_item_equal(DnsTxtItem
*a
, DnsTxtItem
*b
) {
1485 if (a
->length
!= b
->length
)
1488 if (memcmp(a
->data
, b
->data
, a
->length
) != 0)
1491 return dns_txt_item_equal(a
->items_next
, b
->items_next
);
1494 static const char* const dnssec_algorithm_table
[_DNSSEC_ALGORITHM_MAX_DEFINED
] = {
1495 /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
1496 [DNSSEC_ALGORITHM_RSAMD5
] = "RSAMD5",
1497 [DNSSEC_ALGORITHM_DH
] = "DH",
1498 [DNSSEC_ALGORITHM_DSA
] = "DSA",
1499 [DNSSEC_ALGORITHM_ECC
] = "ECC",
1500 [DNSSEC_ALGORITHM_RSASHA1
] = "RSASHA1",
1501 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1
] = "DSA-NSEC3-SHA1",
1502 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1
] = "RSASHA1-NSEC3-SHA1",
1503 [DNSSEC_ALGORITHM_RSASHA256
] = "RSASHA256",
1504 [DNSSEC_ALGORITHM_RSASHA512
] = "RSASHA512",
1505 [DNSSEC_ALGORITHM_ECC_GOST
] = "ECC-GOST",
1506 [DNSSEC_ALGORITHM_ECDSAP256SHA256
] = "ECDSAP256SHA256",
1507 [DNSSEC_ALGORITHM_ECDSAP384SHA384
] = "ECDSAP384SHA384",
1508 [DNSSEC_ALGORITHM_INDIRECT
] = "INDIRECT",
1509 [DNSSEC_ALGORITHM_PRIVATEDNS
] = "PRIVATEDNS",
1510 [DNSSEC_ALGORITHM_PRIVATEOID
] = "PRIVATEOID",
1512 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_algorithm
, int, 255);
1514 static const char* const dnssec_digest_table
[_DNSSEC_DIGEST_MAX_DEFINED
] = {
1515 /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
1516 [DNSSEC_DIGEST_SHA1
] = "SHA-1",
1517 [DNSSEC_DIGEST_SHA256
] = "SHA-256",
1518 [DNSSEC_DIGEST_GOST_R_34_11_94
] = "GOST_R_34.11-94",
1519 [DNSSEC_DIGEST_SHA384
] = "SHA-384",
1521 DEFINE_STRING_TABLE_LOOKUP_WITH_FALLBACK(dnssec_digest
, int, 255);