diff --git a/lib/dns/include/dns/name.h b/lib/dns/include/dns/name.h index 793da57b88..3d11f292b4 100644 --- a/lib/dns/include/dns/name.h +++ b/lib/dns/include/dns/name.h @@ -501,6 +501,33 @@ void dns_name_getlabelsequence(dns_name_t *source, * first + n <= dns_label_countlabels(name) */ + +void +dns_name_clone(dns_name_t *source, dns_name_t *target); +/* + * Make 'target' refer to the same name as 'source'. + * + * Notes: + * + * 'target' refers to the same memory as 'source', so 'source' + * must not be changed while 'target' is still in use. + * + * This call is functionally equivalent to: + * + * dns_name_getlabelsequence(source, 0, + * dns_label_countlabels(source), + * target); + * + * but is more efficient. Also, dns_name_clone() works even if 'source' + * is empty. + * + * Requires: + * + * 'source' is a valid name. + * + * 'target' is a valid name that is not read-only. + */ + /*** *** Conversions ***/ diff --git a/lib/dns/name.c b/lib/dns/name.c index 4ca5911ae1..d896810dbf 100644 --- a/lib/dns/name.c +++ b/lib/dns/name.c @@ -777,6 +777,31 @@ dns_name_getlabelsequence(dns_name_t *source, ISC_FALSE); } +void +dns_name_clone(dns_name_t *source, dns_name_t *target) { + + /* + * Make 'target' refer to the same name as 'source'. + */ + + REQUIRE(VALID_NAME(source)); + REQUIRE(VALID_NAME(target)); + REQUIRE((target->attributes & DNS_NAMEATTR_READONLY) == 0); + + target->ndata = source->ndata; + target->length = source->length; + target->labels = source->labels; + target->attributes = source->attributes; + if (target->offsets != NULL && source->labels > 0) { + if (source->offsets != NULL) + memcpy(target->offsets, source->offsets, + source->labels); + else + set_offsets(target, target->offsets, ISC_FALSE, + ISC_FALSE, ISC_FALSE); + } +} + void dns_name_fromregion(dns_name_t *name, isc_region_t *r) { unsigned char *offsets;