1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "alloc-util.h"
25 #include "dns-domain.h"
27 #include "hexdecoct.h"
28 #include "resolved-dns-packet.h"
29 #include "resolved-dns-rr.h"
30 #include "string-table.h"
31 #include "string-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)];
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 if (asprintf(&s
, "%s. %s %-5s", DNS_RESOURCE_KEY_NAME(key
), c
, t
) < 0)
336 DnsResourceRecord
* dns_resource_record_new(DnsResourceKey
*key
) {
337 DnsResourceRecord
*rr
;
339 rr
= new0(DnsResourceRecord
, 1);
344 rr
->key
= dns_resource_key_ref(key
);
345 rr
->expiry
= USEC_INFINITY
;
350 DnsResourceRecord
* dns_resource_record_new_full(uint16_t class, uint16_t type
, const char *name
) {
351 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
353 key
= dns_resource_key_new(class, type
, name
);
357 return dns_resource_record_new(key
);
360 DnsResourceRecord
* dns_resource_record_ref(DnsResourceRecord
*rr
) {
364 assert(rr
->n_ref
> 0);
370 DnsResourceRecord
* dns_resource_record_unref(DnsResourceRecord
*rr
) {
374 assert(rr
->n_ref
> 0);
382 switch(rr
->key
->type
) {
402 dns_txt_item_free_all(rr
->txt
.items
);
411 free(rr
->mx
.exchange
);
419 free(rr
->sshfp
.fingerprint
);
422 case DNS_TYPE_DNSKEY
:
423 free(rr
->dnskey
.key
);
427 free(rr
->rrsig
.signer
);
428 free(rr
->rrsig
.signature
);
432 free(rr
->nsec
.next_domain_name
);
433 bitmap_free(rr
->nsec
.types
);
437 free(rr
->nsec3
.next_hashed_name
);
438 free(rr
->nsec3
.salt
);
439 bitmap_free(rr
->nsec3
.types
);
448 free(rr
->generic
.data
);
451 free(rr
->wire_format
);
452 dns_resource_key_unref(rr
->key
);
461 int dns_resource_record_new_reverse(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *hostname
) {
462 _cleanup_(dns_resource_key_unrefp
) DnsResourceKey
*key
= NULL
;
463 _cleanup_(dns_resource_record_unrefp
) DnsResourceRecord
*rr
= NULL
;
464 _cleanup_free_
char *ptr
= NULL
;
471 r
= dns_name_reverse(family
, address
, &ptr
);
475 key
= dns_resource_key_new_consume(DNS_CLASS_IN
, DNS_TYPE_PTR
, ptr
);
481 rr
= dns_resource_record_new(key
);
485 rr
->ptr
.name
= strdup(hostname
);
495 int dns_resource_record_new_address(DnsResourceRecord
**ret
, int family
, const union in_addr_union
*address
, const char *name
) {
496 DnsResourceRecord
*rr
;
502 if (family
== AF_INET
) {
504 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_A
, name
);
508 rr
->a
.in_addr
= address
->in
;
510 } else if (family
== AF_INET6
) {
512 rr
= dns_resource_record_new_full(DNS_CLASS_IN
, DNS_TYPE_AAAA
, name
);
516 rr
->aaaa
.in6_addr
= address
->in6
;
518 return -EAFNOSUPPORT
;
525 int dns_resource_record_equal(const DnsResourceRecord
*a
, const DnsResourceRecord
*b
) {
534 r
= dns_resource_key_equal(a
->key
, b
->key
);
538 if (a
->unparseable
!= b
->unparseable
)
541 switch (a
->unparseable
? _DNS_TYPE_INVALID
: a
->key
->type
) {
544 r
= dns_name_equal(a
->srv
.name
, b
->srv
.name
);
548 return a
->srv
.priority
== b
->srv
.priority
&&
549 a
->srv
.weight
== b
->srv
.weight
&&
550 a
->srv
.port
== b
->srv
.port
;
556 return dns_name_equal(a
->ptr
.name
, b
->ptr
.name
);
559 return strcaseeq(a
->hinfo
.cpu
, b
->hinfo
.cpu
) &&
560 strcaseeq(a
->hinfo
.os
, b
->hinfo
.os
);
562 case DNS_TYPE_SPF
: /* exactly the same as TXT */
564 return dns_txt_item_equal(a
->txt
.items
, b
->txt
.items
);
567 return memcmp(&a
->a
.in_addr
, &b
->a
.in_addr
, sizeof(struct in_addr
)) == 0;
570 return memcmp(&a
->aaaa
.in6_addr
, &b
->aaaa
.in6_addr
, sizeof(struct in6_addr
)) == 0;
573 r
= dns_name_equal(a
->soa
.mname
, b
->soa
.mname
);
576 r
= dns_name_equal(a
->soa
.rname
, b
->soa
.rname
);
580 return a
->soa
.serial
== b
->soa
.serial
&&
581 a
->soa
.refresh
== b
->soa
.refresh
&&
582 a
->soa
.retry
== b
->soa
.retry
&&
583 a
->soa
.expire
== b
->soa
.expire
&&
584 a
->soa
.minimum
== b
->soa
.minimum
;
587 if (a
->mx
.priority
!= b
->mx
.priority
)
590 return dns_name_equal(a
->mx
.exchange
, b
->mx
.exchange
);
593 assert(a
->loc
.version
== b
->loc
.version
);
595 return a
->loc
.size
== b
->loc
.size
&&
596 a
->loc
.horiz_pre
== b
->loc
.horiz_pre
&&
597 a
->loc
.vert_pre
== b
->loc
.vert_pre
&&
598 a
->loc
.latitude
== b
->loc
.latitude
&&
599 a
->loc
.longitude
== b
->loc
.longitude
&&
600 a
->loc
.altitude
== b
->loc
.altitude
;
603 return a
->ds
.key_tag
== b
->ds
.key_tag
&&
604 a
->ds
.algorithm
== b
->ds
.algorithm
&&
605 a
->ds
.digest_type
== b
->ds
.digest_type
&&
606 a
->ds
.digest_size
== b
->ds
.digest_size
&&
607 memcmp(a
->ds
.digest
, b
->ds
.digest
, a
->ds
.digest_size
) == 0;
610 return a
->sshfp
.algorithm
== b
->sshfp
.algorithm
&&
611 a
->sshfp
.fptype
== b
->sshfp
.fptype
&&
612 a
->sshfp
.fingerprint_size
== b
->sshfp
.fingerprint_size
&&
613 memcmp(a
->sshfp
.fingerprint
, b
->sshfp
.fingerprint
, a
->sshfp
.fingerprint_size
) == 0;
615 case DNS_TYPE_DNSKEY
:
616 return a
->dnskey
.flags
== b
->dnskey
.flags
&&
617 a
->dnskey
.protocol
== b
->dnskey
.protocol
&&
618 a
->dnskey
.algorithm
== b
->dnskey
.algorithm
&&
619 a
->dnskey
.key_size
== b
->dnskey
.key_size
&&
620 memcmp(a
->dnskey
.key
, b
->dnskey
.key
, a
->dnskey
.key_size
) == 0;
623 /* do the fast comparisons first */
624 if (a
->rrsig
.type_covered
!= b
->rrsig
.type_covered
||
625 a
->rrsig
.algorithm
!= b
->rrsig
.algorithm
||
626 a
->rrsig
.labels
!= b
->rrsig
.labels
||
627 a
->rrsig
.original_ttl
!= b
->rrsig
.original_ttl
||
628 a
->rrsig
.expiration
!= b
->rrsig
.expiration
||
629 a
->rrsig
.inception
!= b
->rrsig
.inception
||
630 a
->rrsig
.key_tag
!= b
->rrsig
.key_tag
||
631 a
->rrsig
.signature_size
!= b
->rrsig
.signature_size
||
632 memcmp(a
->rrsig
.signature
, b
->rrsig
.signature
, a
->rrsig
.signature_size
) != 0)
635 return dns_name_equal(a
->rrsig
.signer
, b
->rrsig
.signer
);
638 return dns_name_equal(a
->nsec
.next_domain_name
, b
->nsec
.next_domain_name
) &&
639 bitmap_equal(a
->nsec
.types
, b
->nsec
.types
);
642 return a
->nsec3
.algorithm
== b
->nsec3
.algorithm
&&
643 a
->nsec3
.flags
== b
->nsec3
.flags
&&
644 a
->nsec3
.iterations
== b
->nsec3
.iterations
&&
645 a
->nsec3
.salt_size
== b
->nsec3
.salt_size
&&
646 memcmp(a
->nsec3
.salt
, b
->nsec3
.salt
, a
->nsec3
.salt_size
) == 0 &&
647 memcmp(a
->nsec3
.next_hashed_name
, b
->nsec3
.next_hashed_name
, a
->nsec3
.next_hashed_name_size
) == 0 &&
648 bitmap_equal(a
->nsec3
.types
, b
->nsec3
.types
);
651 return a
->generic
.size
== b
->generic
.size
&&
652 memcmp(a
->generic
.data
, b
->generic
.data
, a
->generic
.size
) == 0;
656 static char* format_location(uint32_t latitude
, uint32_t longitude
, uint32_t altitude
,
657 uint8_t size
, uint8_t horiz_pre
, uint8_t vert_pre
) {
659 char NS
= latitude
>= 1U<<31 ? 'N' : 'S';
660 char EW
= longitude
>= 1U<<31 ? 'E' : 'W';
662 int lat
= latitude
>= 1U<<31 ? (int) (latitude
- (1U<<31)) : (int) ((1U<<31) - latitude
);
663 int lon
= longitude
>= 1U<<31 ? (int) (longitude
- (1U<<31)) : (int) ((1U<<31) - longitude
);
664 double alt
= altitude
>= 10000000u ? altitude
- 10000000u : -(double)(10000000u - altitude
);
665 double siz
= (size
>> 4) * exp10((double) (size
& 0xF));
666 double hor
= (horiz_pre
>> 4) * exp10((double) (horiz_pre
& 0xF));
667 double ver
= (vert_pre
>> 4) * exp10((double) (vert_pre
& 0xF));
669 if (asprintf(&s
, "%d %d %.3f %c %d %d %.3f %c %.2fm %.2fm %.2fm %.2fm",
672 (lat
% 60000) / 1000.,
676 (lon
% 60000) / 1000.,
687 static int format_timestamp_dns(char *buf
, size_t l
, time_t sec
) {
691 assert(l
> strlen("YYYYMMDDHHmmSS"));
693 if (!gmtime_r(&sec
, &tm
))
696 if (strftime(buf
, l
, "%Y%m%d%H%M%S", &tm
) <= 0)
702 static char *format_types(Bitmap
*types
) {
703 _cleanup_strv_free_
char **strv
= NULL
;
704 _cleanup_free_
char *str
= NULL
;
709 BITMAP_FOREACH(type
, types
, i
) {
710 if (dns_type_to_string(type
)) {
711 r
= strv_extend(&strv
, dns_type_to_string(type
));
717 r
= asprintf(&t
, "TYPE%u", type
);
721 r
= strv_consume(&strv
, t
);
727 str
= strv_join(strv
, " ");
731 return strjoin("( ", str
, " )", NULL
);
734 static char *format_txt(DnsTxtItem
*first
) {
739 LIST_FOREACH(items
, i
, first
)
740 c
+= i
->length
* 4 + 3;
742 p
= s
= new(char, c
);
746 LIST_FOREACH(items
, i
, first
) {
754 for (j
= 0; j
< i
->length
; j
++) {
755 if (i
->data
[j
] < ' ' || i
->data
[j
] == '"' || i
->data
[j
] >= 127) {
757 *(p
++) = '0' + (i
->data
[j
] / 100);
758 *(p
++) = '0' + ((i
->data
[j
] / 10) % 10);
759 *(p
++) = '0' + (i
->data
[j
] % 10);
771 const char *dns_resource_record_to_string(DnsResourceRecord
*rr
) {
772 _cleanup_free_
char *k
= NULL
, *t
= NULL
;
779 return rr
->to_string
;
781 r
= dns_resource_key_to_string(rr
->key
, &k
);
785 switch (rr
->unparseable
? _DNS_TYPE_INVALID
: rr
->key
->type
) {
788 r
= asprintf(&s
, "%s %u %u %u %s",
793 strna(rr
->srv
.name
));
802 s
= strjoin(k
, " ", rr
->ptr
.name
, NULL
);
809 s
= strjoin(k
, " ", rr
->hinfo
.cpu
, " ", rr
->hinfo
.os
, NULL
);
814 case DNS_TYPE_SPF
: /* exactly the same as TXT */
816 t
= format_txt(rr
->txt
.items
);
820 s
= strjoin(k
, " ", t
, NULL
);
826 _cleanup_free_
char *x
= NULL
;
828 r
= in_addr_to_string(AF_INET
, (const union in_addr_union
*) &rr
->a
.in_addr
, &x
);
832 s
= strjoin(k
, " ", x
, NULL
);
839 r
= in_addr_to_string(AF_INET6
, (const union in_addr_union
*) &rr
->aaaa
.in6_addr
, &t
);
843 s
= strjoin(k
, " ", t
, NULL
);
849 r
= asprintf(&s
, "%s %s %s %u %u %u %u %u",
851 strna(rr
->soa
.mname
),
852 strna(rr
->soa
.rname
),
863 r
= asprintf(&s
, "%s %u %s",
872 assert(rr
->loc
.version
== 0);
874 t
= format_location(rr
->loc
.latitude
,
883 s
= strjoin(k
, " ", t
, NULL
);
889 t
= hexmem(rr
->ds
.digest
, rr
->ds
.digest_size
);
893 r
= asprintf(&s
, "%s %u %u %u %s",
904 t
= hexmem(rr
->sshfp
.fingerprint
, rr
->sshfp
.fingerprint_size
);
908 r
= asprintf(&s
, "%s %u %u %s",
917 case DNS_TYPE_DNSKEY
: {
920 alg
= dnssec_algorithm_to_string(rr
->dnskey
.algorithm
);
922 t
= base64mem(rr
->dnskey
.key
, rr
->dnskey
.key_size
);
926 r
= asprintf(&s
, "%s %u %u %.*s%.*u %s",
931 alg
? 0 : 1, alg
? 0u : (unsigned) rr
->dnskey
.algorithm
,
938 case DNS_TYPE_RRSIG
: {
939 const char *type
, *alg
;
940 char expiration
[strlen("YYYYMMDDHHmmSS") + 1], inception
[strlen("YYYYMMDDHHmmSS") + 1];
942 type
= dns_type_to_string(rr
->rrsig
.type_covered
);
943 alg
= dnssec_algorithm_to_string(rr
->rrsig
.algorithm
);
945 t
= base64mem(rr
->rrsig
.signature
, rr
->rrsig
.signature_size
);
949 r
= format_timestamp_dns(expiration
, sizeof(expiration
), rr
->rrsig
.expiration
);
953 r
= format_timestamp_dns(inception
, sizeof(inception
), rr
->rrsig
.inception
);
958 * http://tools.ietf.org/html/rfc3597#section-5 */
960 r
= asprintf(&s
, "%s %s%.*u %.*s%.*u %u %u %s %s %u %s %s",
963 type
? 0 : 1, type
? 0u : (unsigned) rr
->rrsig
.type_covered
,
965 alg
? 0 : 1, alg
? 0u : (unsigned) rr
->rrsig
.algorithm
,
967 rr
->rrsig
.original_ttl
,
979 t
= format_types(rr
->nsec
.types
);
983 r
= asprintf(&s
, "%s %s %s",
985 rr
->nsec
.next_domain_name
,
991 case DNS_TYPE_NSEC3
: {
992 _cleanup_free_
char *salt
= NULL
, *hash
= NULL
;
994 if (rr
->nsec3
.salt_size
> 0) {
995 salt
= hexmem(rr
->nsec3
.salt
, rr
->nsec3
.salt_size
);
1000 hash
= base32hexmem(rr
->nsec3
.next_hashed_name
, rr
->nsec3
.next_hashed_name_size
, false);
1004 t
= format_types(rr
->nsec3
.types
);
1008 r
= asprintf(&s
, "%s %"PRIu8
" %"PRIu8
" %"PRIu16
" %s %s %s",
1010 rr
->nsec3
.algorithm
,
1012 rr
->nsec3
.iterations
,
1013 rr
->nsec3
.salt_size
> 0 ? salt
: "-",
1023 t
= hexmem(rr
->generic
.data
, rr
->generic
.size
);
1027 /* Format as documented in RFC 3597, Section 5 */
1028 r
= asprintf(&s
, "%s \\# %zu %s", k
, rr
->generic
.size
, t
);
1038 int dns_resource_record_to_wire_format(DnsResourceRecord
*rr
, bool canonical
) {
1040 DnsPacket packet
= {
1042 .protocol
= DNS_PROTOCOL_DNS
,
1044 .refuse_compression
= true,
1045 .canonical_form
= canonical
,
1053 /* Generates the RR in wire-format, optionally in the
1054 * canonical form as discussed in the DNSSEC RFC 4034, Section
1055 * 6.2. We allocate a throw-away DnsPacket object on the stack
1056 * here, because we need some book-keeping for memory
1057 * management, and can reuse the DnsPacket serializer, that
1058 * can generate the canonical form, too, but also knows label
1059 * compression and suchlike. */
1061 if (rr
->wire_format
&& rr
->wire_format_canonical
== canonical
)
1064 r
= dns_packet_append_rr(&packet
, rr
, &start
, &rds
);
1069 assert(packet
._data
);
1071 free(rr
->wire_format
);
1072 rr
->wire_format
= packet
._data
;
1073 rr
->wire_format_size
= packet
.size
;
1074 rr
->wire_format_rdata_offset
= rds
;
1075 rr
->wire_format_canonical
= canonical
;
1077 packet
._data
= NULL
;
1078 dns_packet_unref(&packet
);
1083 DnsTxtItem
*dns_txt_item_free_all(DnsTxtItem
*i
) {
1092 return dns_txt_item_free_all(n
);
1095 bool dns_txt_item_equal(DnsTxtItem
*a
, DnsTxtItem
*b
) {
1106 if (a
->length
!= b
->length
)
1109 if (memcmp(a
->data
, b
->data
, a
->length
) != 0)
1112 return dns_txt_item_equal(a
->items_next
, b
->items_next
);
1115 static const char* const dnssec_algorithm_table
[_DNSSEC_ALGORITHM_MAX_DEFINED
] = {
1116 /* Mnemonics as listed on https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
1117 [DNSSEC_ALGORITHM_RSAMD5
] = "RSAMD5",
1118 [DNSSEC_ALGORITHM_DH
] = "DH",
1119 [DNSSEC_ALGORITHM_DSA
] = "DSA",
1120 [DNSSEC_ALGORITHM_ECC
] = "ECC",
1121 [DNSSEC_ALGORITHM_RSASHA1
] = "RSASHA1",
1122 [DNSSEC_ALGORITHM_DSA_NSEC3_SHA1
] = "DSA-NSEC3-SHA1",
1123 [DNSSEC_ALGORITHM_RSASHA1_NSEC3_SHA1
] = "RSASHA1-NSEC3-SHA1",
1124 [DNSSEC_ALGORITHM_RSASHA256
] = "RSASHA256",
1125 [DNSSEC_ALGORITHM_RSASHA512
] = "RSASHA512",
1126 [DNSSEC_ALGORITHM_ECC_GOST
] = "ECC-GOST",
1127 [DNSSEC_ALGORITHM_ECDSAP256SHA256
] = "ECDSAP256SHA256",
1128 [DNSSEC_ALGORITHM_ECDSAP384SHA384
] = "ECDSAP384SHA384",
1129 [DNSSEC_ALGORITHM_INDIRECT
] = "INDIRECT",
1130 [DNSSEC_ALGORITHM_PRIVATEDNS
] = "PRIVATEDNS",
1131 [DNSSEC_ALGORITHM_PRIVATEOID
] = "PRIVATEOID",
1133 DEFINE_STRING_TABLE_LOOKUP(dnssec_algorithm
, int);
1135 static const char* const dnssec_digest_table
[_DNSSEC_DIGEST_MAX_DEFINED
] = {
1136 /* Names as listed on https://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
1137 [DNSSEC_DIGEST_SHA1
] = "SHA-1",
1138 [DNSSEC_DIGEST_SHA256
] = "SHA-256",
1139 [DNSSEC_DIGEST_GOST_R_34_11_94
] = "GOST_R_34.11-94",
1140 [DNSSEC_DIGEST_SHA384
] = "SHA-384",
1142 DEFINE_STRING_TABLE_LOOKUP(dnssec_digest
, int);