From: Ondřej Surý Date: Mon, 11 Sep 2023 08:35:28 +0000 (+0200) Subject: Use hashtable when parsing a message X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0ceed03ebea395da1a39ad1cb39205ce75a3f768;p=thirdparty%2Fbind9.git Use hashtable when parsing a message When parsing messages use a hashtable instead of a linear search to reduce the amount of work done in findname when there's more than one name in the section. There are two hashtables: 1) hashtable for owner names - that's constructed for each section when we hit the second name in the section and destroyed right after parsing that section; 2) per-name hashtable - for each name in the section, we construct a new hashtable for that name if there are more than one rdataset for that particular name. (cherry picked from commit b8a96317544c7b310b4f74360825a87b6402ddc2) --- diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index f64522b43ab..96c5ef1f79c 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -758,45 +758,6 @@ dns_message_findtype(dns_name_t *name, dns_rdatatype_t type, *\li #ISC_R_NOTFOUND -- the desired type does not exist. */ -isc_result_t -dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass, - dns_rdatatype_t type, dns_rdatatype_t covers, - dns_rdataset_t **rdataset); -/*%< - * Search the name for the specified rdclass and type. If it is found, - * *rdataset is filled in with a pointer to that rdataset. - * - * Requires: - *\li if '**rdataset' is non-NULL, *rdataset needs to be NULL. - * - *\li 'type' be a valid type, and NOT dns_rdatatype_any. - * - *\li If 'type' is dns_rdatatype_rrsig, 'covers' must be a valid type. - * Otherwise it should be 0. - * - * Returns: - *\li #ISC_R_SUCCESS -- all is well. - *\li #ISC_R_NOTFOUND -- the desired type does not exist. - */ - -void -dns_message_movename(dns_message_t *msg, dns_name_t *name, - dns_section_t fromsection, - dns_section_t tosection); -/*%< - * Move a name from one section to another. - * - * Requires: - * - *\li 'msg' be valid. - * - *\li 'name' must be a name already in 'fromsection'. - * - *\li 'fromsection' must be a valid section. - * - *\li 'tosection' must be a valid section. - */ - void dns_message_addname(dns_message_t *msg, dns_name_t *name, dns_section_t section); diff --git a/lib/dns/include/dns/name.h b/lib/dns/include/dns/name.h index 0ca5d475462..2b8c0390ffb 100644 --- a/lib/dns/include/dns/name.h +++ b/lib/dns/include/dns/name.h @@ -68,6 +68,7 @@ #include #include +#include #include #include #include /* Required for storage size of dns_label_t. */ @@ -111,6 +112,7 @@ struct dns_name { isc_buffer_t * buffer; ISC_LINK(dns_name_t) link; ISC_LIST(dns_rdataset_t) list; + isc_ht_t *ht; }; #define DNS_NAME_MAGIC ISC_MAGIC('D','N','S','n') @@ -171,7 +173,7 @@ LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_wildcardname; A, (sizeof(A) - 1), sizeof(B), \ DNS_NAMEATTR_READONLY, \ B, NULL, { (void *)-1, (void *)-1}, \ - {NULL, NULL} \ + {NULL, NULL}, NULL \ } #define DNS_NAME_INITABSOLUTE(A,B) { \ @@ -179,12 +181,12 @@ LIBDNS_EXTERNAL_DATA extern dns_name_t *dns_wildcardname; A, sizeof(A), sizeof(B), \ DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, \ B, NULL, { (void *)-1, (void *)-1}, \ - {NULL, NULL} \ + {NULL, NULL}, NULL \ } #define DNS_NAME_INITEMPTY { \ DNS_NAME_MAGIC, NULL, 0, 0, 0, NULL, NULL, \ - { (void *)-1, (void *)-1 }, { NULL, NULL } \ + { (void *)-1, (void *)-1 }, { NULL, NULL }, NULL \ } /*% @@ -1374,6 +1376,7 @@ do { \ _n->buffer = NULL; \ ISC_LINK_INIT(_n, link); \ ISC_LIST_INIT(_n->list); \ + _n->ht = NULL; \ } while (0) #define DNS_NAME_RESET(n) \ diff --git a/lib/dns/message.c b/lib/dns/message.c index 2812ab5a37a..1d2b08de9a5 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -21,6 +21,8 @@ #include #include +#include +#include #include #include #include @@ -189,6 +191,9 @@ msgblock_allocate(isc_mem_t *, unsigned int, unsigned int); #define msgblock_get(block, type) \ ((type *)msgblock_internalget(block, sizeof(type))) +static void +dns__message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **rdatasetp); + static inline void * msgblock_internalget(dns_msgblock_t *, unsigned int); @@ -502,7 +507,7 @@ msgresetopt(dns_message_t *msg) } INSIST(dns_rdataset_isassociated(msg->opt)); dns_rdataset_disassociate(msg->opt); - isc_mempool_put(msg->rdspool, msg->opt); + dns__message_puttemprdataset(msg, &msg->opt); msg->opt = NULL; msg->cc_ok = 0; msg->cc_bad = 0; @@ -523,10 +528,11 @@ msgresetsigs(dns_message_t *msg, bool replying) { msg->querytsig = msg->tsig; } else { dns_rdataset_disassociate(msg->tsig); - isc_mempool_put(msg->rdspool, msg->tsig); + dns__message_puttemprdataset(msg, &msg->tsig); if (msg->querytsig != NULL) { dns_rdataset_disassociate(msg->querytsig); - isc_mempool_put(msg->rdspool, msg->querytsig); + dns__message_puttemprdataset(msg, + &msg->querytsig); } } if (dns_name_dynamic(msg->tsigname)) @@ -536,13 +542,10 @@ msgresetsigs(dns_message_t *msg, bool replying) { msg->tsigname = NULL; } else if (msg->querytsig != NULL && !replying) { dns_rdataset_disassociate(msg->querytsig); - isc_mempool_put(msg->rdspool, msg->querytsig); - msg->querytsig = NULL; + dns__message_puttemprdataset(msg, &msg->querytsig); } if (msg->sig0 != NULL) { - INSIST(dns_rdataset_isassociated(msg->sig0)); - dns_rdataset_disassociate(msg->sig0); - isc_mempool_put(msg->rdspool, msg->sig0); + dns__message_puttemprdataset(msg, &msg->sig0); if (msg->sig0name != NULL) { if (dns_name_dynamic(msg->sig0name)) dns_name_free(msg->sig0name, msg->mctx); @@ -863,6 +866,22 @@ dns_message_detach(dns_message_t **messagep) { } } +static isc_result_t +name_hash_add(isc_ht_t *ht, dns_name_t *name, dns_name_t **foundp) { + dns_fixedname_t fixed; + dns_name_t *key = dns_fixedname_initname(&fixed); + dns_name_downcase(name, key, NULL); + + isc_result_t result = isc_ht_find(ht, key->ndata, key->length, + (void **)foundp); + if (result == ISC_R_SUCCESS) { + return (ISC_R_EXISTS); + } + result = isc_ht_add(ht, key->ndata, key->length, (void *)name); + INSIST(result == ISC_R_SUCCESS); + return (ISC_R_SUCCESS); +} + static isc_result_t findname(dns_name_t **foundname, dns_name_t *target, dns_namelist_t *section) @@ -882,28 +901,26 @@ findname(dns_name_t **foundname, dns_name_t *target, return (ISC_R_NOTFOUND); } -isc_result_t -dns_message_find(dns_name_t *name, dns_rdataclass_t rdclass, - dns_rdatatype_t type, dns_rdatatype_t covers, - dns_rdataset_t **rdataset) -{ - dns_rdataset_t *curr; - - REQUIRE(name != NULL); - REQUIRE(rdataset == NULL || *rdataset == NULL); +typedef struct __attribute__((__packed__)) rds_key { + dns_rdataclass_t rdclass; + dns_rdatatype_t type; + dns_rdatatype_t covers; +} rds_key_t; - for (curr = ISC_LIST_TAIL(name->list); - curr != NULL; - curr = ISC_LIST_PREV(curr, link)) { - if (curr->rdclass == rdclass && - curr->type == type && curr->covers == covers) { - if (rdataset != NULL) - *rdataset = curr; - return (ISC_R_SUCCESS); - } +static isc_result_t +rds_hash_add(isc_ht_t *ht, dns_rdataset_t *rds, dns_rdataset_t **foundp) { + rds_key_t key = { .rdclass = rds->rdclass, + .type = rds->type, + .covers = rds->covers }; + isc_result_t result = isc_ht_find(ht, (const unsigned char *)&key, + sizeof(key), (void **)foundp); + if (result == ISC_R_SUCCESS) { + return (ISC_R_EXISTS); } - - return (ISC_R_NOTFOUND); + result = isc_ht_add(ht, (const unsigned char *)&key, sizeof(key), + (void *)rds); + INSIST(result == ISC_R_SUCCESS); + return (ISC_R_SUCCESS); } isc_result_t @@ -1031,6 +1048,18 @@ getrdata(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, } \ } while (0) +static void +cleanup_name_hashmaps(dns_namelist_t *section) { + dns_name_t *name = NULL; + for (name = ISC_LIST_HEAD(*section); name != NULL; + name = ISC_LIST_NEXT(name, link)) + { + if (name->ht != NULL) { + isc_ht_destroy(&name->ht); + } + } +} + static isc_result_t getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, unsigned int options) @@ -1042,13 +1071,15 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, dns_offsets_t *offsets; dns_rdataset_t *rdataset; dns_rdatalist_t *rdatalist; - isc_result_t result; + isc_result_t result = ISC_R_SUCCESS; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass; dns_namelist_t *section; bool free_name; bool best_effort; bool seen_problem; + isc_ht_t *name_map = NULL; + bool free_ht = false; section = &msg->sections[DNS_SECTION_QUESTION]; @@ -1056,9 +1087,14 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, seen_problem = false; name = NULL; + name2 = NULL; rdataset = NULL; rdatalist = NULL; + if (msg->counts[DNS_SECTION_QUESTION] > 1) { + isc_ht_init(&name_map, msg->mctx, 1, ISC_HT_CASE_INSENSITIVE); + } + for (count = 0; count < msg->counts[DNS_SECTION_QUESTION]; count++) { name = isc_mempool_get(msg->namepool); if (name == NULL) @@ -1081,13 +1117,20 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, if (result != ISC_R_SUCCESS) goto cleanup; + + /* If there is only one QNAME, skip the duplicity checks */ + if (name_map == NULL) { + result = ISC_R_SUCCESS; + goto skip_name_check; + } + /* * Run through the section, looking to see if this name * is already there. If it is found, put back the allocated * name since we no longer need it, and set our name pointer * to point to the name we found. */ - result = findname(&name2, name, section); + result = name_hash_add(name_map, name, &name2); /* * If it is the first name in the section, accept it. @@ -1099,18 +1142,25 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, * this should be legal or not. In either case we no longer * need this name pointer. */ - if (result != ISC_R_SUCCESS) { - if (!ISC_LIST_EMPTY(*section)) + skip_name_check: + switch (result) { + case ISC_R_SUCCESS: + if (!ISC_LIST_EMPTY(*section)) { DO_ERROR(DNS_R_FORMERR); + } ISC_LIST_APPEND(*section, name, link); - free_name = false; - } else { - isc_mempool_put(msg->namepool, name); + break; + case ISC_R_EXISTS: + dns_message_puttempname(msg, &name); name = name2; name2 = NULL; - free_name = false; + break; + default: + ISC_UNREACHABLE(); } + free_name = false; + /* * Get type and class. */ @@ -1138,13 +1188,6 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, if (rdtype == dns_rdatatype_tkey) msg->tkey = 1; - /* - * Can't ask the same question twice. - */ - result = dns_message_find(name, rdclass, rdtype, 0, NULL); - if (result == ISC_R_SUCCESS) - DO_ERROR(DNS_R_FORMERR); - /* * Allocate a new rdatalist. */ @@ -1153,7 +1196,7 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, result = ISC_R_NOMEMORY; goto cleanup; } - rdataset = isc_mempool_get(msg->rdspool); + dns_message_gettemprdataset(msg, &rdataset); if (rdataset == NULL) { result = ISC_R_NOMEMORY; goto cleanup; @@ -1166,32 +1209,71 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, rdatalist->type = rdtype; rdatalist->rdclass = rdclass; - dns_rdataset_init(rdataset); result = dns_rdatalist_tordataset(rdatalist, rdataset); if (result != ISC_R_SUCCESS) goto cleanup; rdataset->attributes |= DNS_RDATASETATTR_QUESTION; + /* + * Skip the duplicity check for first rdataset + */ + if (ISC_LIST_EMPTY(name->list)) { + goto skip_rds_check; + } + + /* + * Can't ask the same question twice. + */ + if (name->ht == NULL) { + isc_ht_init(&name->ht, msg->mctx, 1); + free_ht = true; + + dns_rdataset_t *old_rdataset = NULL; + for (old_rdataset = ISC_LIST_HEAD(name->list); + old_rdataset != NULL; + old_rdataset = ISC_LIST_NEXT(old_rdataset, link)) + { + result = rds_hash_add(name->ht, old_rdataset, + NULL); + INSIST(result == ISC_R_SUCCESS); + } + } + result = rds_hash_add(name->ht, rdataset, NULL); + if (result == ISC_R_EXISTS) { + DO_ERROR(DNS_R_FORMERR); + } + + skip_rds_check: ISC_LIST_APPEND(name->list, rdataset, link); + rdataset = NULL; } - if (seen_problem) - return (DNS_R_RECOVERABLE); - return (ISC_R_SUCCESS); + + if (seen_problem) { + result = DNS_R_RECOVERABLE; + } cleanup: if (rdataset != NULL) { - INSIST(!dns_rdataset_isassociated(rdataset)); - isc_mempool_put(msg->rdspool, rdataset); + dns_message_puttemprdataset(msg, &rdataset); } #if 0 if (rdatalist != NULL) isc_mempool_put(msg->rdlpool, rdatalist); #endif - if (free_name) - isc_mempool_put(msg->namepool, name); + if (free_name) { + dns_message_puttempname(msg, &name); + } + + if (free_ht) { + cleanup_name_hashmaps(section); + } + + if (name_map != NULL) { + isc_ht_destroy(&name_map); + } return (result); } @@ -1272,17 +1354,20 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, dns_name_t *name = NULL; dns_name_t *name2 = NULL; dns_offsets_t *offsets; - dns_rdataset_t *rdataset; + dns_rdataset_t *rdataset = NULL; + dns_rdataset_t *rdataset2 = NULL; dns_rdatalist_t *rdatalist; - isc_result_t result; + isc_result_t result = ISC_R_SUCCESS; dns_rdatatype_t rdtype, covers; dns_rdataclass_t rdclass; dns_rdata_t *rdata; dns_ttl_t ttl; dns_namelist_t *section; - bool free_name = false, free_rdataset = false; + bool free_name = false; bool preserve_order, best_effort, seen_problem; bool isedns, issigzero, istsig; + isc_ht_t *name_map = NULL; + bool free_ht = false; preserve_order = ((options & DNS_MESSAGEPARSE_PRESERVEORDER) != 0); best_effort = ((options & DNS_MESSAGEPARSE_BESTEFFORT) != 0); @@ -1290,13 +1375,16 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, section = &msg->sections[sectionid]; + if (msg->counts[sectionid] > 1) { + isc_ht_init(&name_map, msg->mctx, 1, ISC_HT_CASE_INSENSITIVE); + } + for (count = 0; count < msg->counts[sectionid]; count++) { int recstart = source->current; bool skip_name_search, skip_type_search; skip_name_search = false; skip_type_search = false; - free_rdataset = false; isedns = false; issigzero = false; istsig = false; @@ -1521,97 +1609,136 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, free_name = false; } } else { + if (name_map == NULL) { + result = ISC_R_SUCCESS; + goto skip_name_check; + } + /* * Run through the section, looking to see if this name * is already there. If it is found, put back the * allocated name since we no longer need it, and set * our name pointer to point to the name we found. */ - result = findname(&name2, name, section); + result = name_hash_add(name_map, name, &name2); /* * If it is a new name, append to the section. */ - if (result == ISC_R_SUCCESS) { - isc_mempool_put(msg->namepool, name); - name = name2; - } else { + skip_name_check: + switch (result) { + case ISC_R_SUCCESS: ISC_LIST_APPEND(*section, name, link); + break; + case ISC_R_EXISTS: + dns_message_puttempname(msg, &name); + name = name2; + name2 = NULL; + break; + default: + ISC_UNREACHABLE(); } free_name = false; } + rdatalist = newrdatalist(msg); + if (rdatalist == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + dns_message_gettemprdataset(msg, &rdataset); + if (rdataset == NULL) { + result = ISC_R_NOMEMORY; + goto cleanup; + } + + rdatalist->type = rdtype; + rdatalist->covers = covers; + rdatalist->rdclass = rdclass; + rdatalist->ttl = ttl; + + RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, rdataset) == + ISC_R_SUCCESS); + dns_rdataset_setownercase(rdataset, name); + rdatalist = NULL; + /* * Search name for the particular type and class. * Skip this stage if in update mode or this is a meta-type. */ - if (preserve_order || msg->opcode == dns_opcode_update || - skip_type_search) - result = ISC_R_NOTFOUND; - else { + if (isedns || istsig || issigzero) { + /* Skip adding the rdataset to the tables */ + } else if (preserve_order || msg->opcode == dns_opcode_update || + skip_type_search) + { + result = ISC_R_SUCCESS; + + ISC_LIST_APPEND(name->list, rdataset, link); + } else { /* * If this is a type that can only occur in * the question section, fail. */ - if (dns_rdatatype_questiononly(rdtype)) + if (dns_rdatatype_questiononly(rdtype)) { + dns_message_puttemprdataset(msg, &rdataset); DO_ERROR(DNS_R_FORMERR); + } - rdataset = NULL; - result = dns_message_find(name, rdclass, rdtype, - covers, &rdataset); - } + if (ISC_LIST_EMPTY(name->list)) { + goto skip_rds_check; + } + + if (name->ht == NULL) { + isc_ht_init(&name->ht, msg->mctx, 1, + ISC_HT_CASE_SENSITIVE); + free_ht = true; + } + rdataset2 = NULL; + result = rds_hash_add(name->ht, rdataset, + &rdataset2); + + /* + * If we found an rdataset that matches, we need to + * append this rdata to that set. If we did not, we + * need to create a new rdatalist, store the important + * bits there, convert it to an rdataset, and link the + * latter to the name. Yuck. When appending, make + * certain that the type isn't a singleton type, such as + * SOA or CNAME. + * + * Note that this check will be bypassed when preserving + * order, the opcode is an update, or the type search is + * skipped. + */ + skip_rds_check: + switch (result) { + case ISC_R_EXISTS: + /* Free the rdataset we used as the key */ + dns_rdataset_disassociate(rdataset); + dns__message_puttemprdataset(msg, &rdataset); + rdataset = rdataset2; + rdataset2 = NULL; + + result = ISC_R_SUCCESS; + + if (!dns_rdatatype_issingleton(rdtype)) { + break; + } - /* - * If we found an rdataset that matches, we need to - * append this rdata to that set. If we did not, we need - * to create a new rdatalist, store the important bits there, - * convert it to an rdataset, and link the latter to the name. - * Yuck. When appending, make certain that the type isn't - * a singleton type, such as SOA or CNAME. - * - * Note that this check will be bypassed when preserving order, - * the opcode is an update, or the type search is skipped. - */ - if (result == ISC_R_SUCCESS) { - if (dns_rdatatype_issingleton(rdtype)) { dns_rdata_t *first; dns_rdatalist_fromrdataset(rdataset, &rdatalist); first = ISC_LIST_HEAD(rdatalist->rdata); INSIST(first != NULL); - if (dns_rdata_compare(rdata, first) != 0) + if (dns_rdata_compare(rdata, first) != 0) { DO_ERROR(DNS_R_FORMERR); - } - } - - if (result == ISC_R_NOTFOUND) { - rdataset = isc_mempool_get(msg->rdspool); - if (rdataset == NULL) { - result = ISC_R_NOMEMORY; - goto cleanup; - } - free_rdataset = true; - - rdatalist = newrdatalist(msg); - if (rdatalist == NULL) { - result = ISC_R_NOMEMORY; - goto cleanup; - } - - rdatalist->type = rdtype; - rdatalist->covers = covers; - rdatalist->rdclass = rdclass; - rdatalist->ttl = ttl; - - dns_rdataset_init(rdataset); - RUNTIME_CHECK(dns_rdatalist_tordataset(rdatalist, - rdataset) - == ISC_R_SUCCESS); - dns_rdataset_setownercase(rdataset, name); - - if (!isedns && !istsig && !issigzero) { + } + break; + case ISC_R_SUCCESS: ISC_LIST_APPEND(name->list, rdataset, link); - free_rdataset = false; + break; + default: + ISC_UNREACHABLE(); } } @@ -1646,7 +1773,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, msg->opt = rdataset; rdataset = NULL; - free_rdataset = false; ercode = (dns_rcode_t) ((msg->opt->ttl & DNS_MESSAGE_EDNSRCODE_MASK) >> 20); @@ -1658,7 +1784,6 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, msg->sig0name = name; msg->sigstart = recstart; rdataset = NULL; - free_rdataset = false; free_name = false; } else if (istsig) { msg->tsig = rdataset; @@ -1669,19 +1794,17 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, */ msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; rdataset = NULL; - free_rdataset = false; free_name = false; } if (seen_problem) { if (free_name) isc_mempool_put(msg->namepool, name); - if (free_rdataset) - isc_mempool_put(msg->rdspool, rdataset); - free_name = free_rdataset = false; + free_name = false; } INSIST(free_name == false); - INSIST(free_rdataset == false); + + rdataset = NULL; } /* @@ -1697,15 +1820,22 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t *dctx, !auth_signed(section)) DO_ERROR(DNS_R_FORMERR); - if (seen_problem) - return (DNS_R_RECOVERABLE); - return (ISC_R_SUCCESS); + if (seen_problem) { + result = DNS_R_RECOVERABLE; + } - cleanup: - if (free_name) - isc_mempool_put(msg->namepool, name); - if (free_rdataset) - isc_mempool_put(msg->rdspool, rdataset); +cleanup: + if (free_name) { + dns_message_puttempname(msg, &name); + } + + if (free_ht) { + cleanup_name_hashmaps(section); + } + + if (name_map != NULL) { + isc_ht_destroy(&name_map); + } return (result); } @@ -2438,11 +2568,11 @@ dns_message_renderreset(dns_message_t *msg) { dns_message_puttempname(msg, &msg->tsigname); if (msg->tsig != NULL) { dns_rdataset_disassociate(msg->tsig); - dns_message_puttemprdataset(msg, &msg->tsig); + dns__message_puttemprdataset(msg, &msg->tsig); } if (msg->sig0 != NULL) { dns_rdataset_disassociate(msg->sig0); - dns_message_puttemprdataset(msg, &msg->sig0); + dns__message_puttemprdataset(msg, &msg->sig0); } } @@ -2535,24 +2665,6 @@ dns_message_findname(dns_message_t *msg, dns_section_t section, return (result); } -void -dns_message_movename(dns_message_t *msg, dns_name_t *name, - dns_section_t fromsection, - dns_section_t tosection) -{ - REQUIRE(msg != NULL); - REQUIRE(msg->from_to_wire == DNS_MESSAGE_INTENTRENDER); - REQUIRE(name != NULL); - REQUIRE(VALID_NAMED_SECTION(fromsection)); - REQUIRE(VALID_NAMED_SECTION(tosection)); - - /* - * Unlink the name from the old section - */ - ISC_LIST_UNLINK(msg->sections[fromsection], name, link); - ISC_LIST_APPEND(msg->sections[tosection], name, link); -} - void dns_message_addname(dns_message_t *msg, dns_name_t *name, dns_section_t section) @@ -2645,6 +2757,9 @@ dns_message_puttempname(dns_message_t *msg, dns_name_t **item) { REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(item != NULL && *item != NULL); + if ((*item)->ht != NULL) { + isc_ht_destroy(&(*item)->ht); + } if (dns_name_dynamic(*item)) dns_name_free(*item, msg->mctx); isc_mempool_put(msg->namepool, *item); @@ -2660,14 +2775,19 @@ dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) { *item = NULL; } +static void +dns__message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) { + isc_mempool_put(msg->rdspool, *item); + *item = NULL; +} + void dns_message_puttemprdataset(dns_message_t *msg, dns_rdataset_t **item) { REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(item != NULL && *item != NULL); REQUIRE(!dns_rdataset_isassociated(*item)); - isc_mempool_put(msg->rdspool, *item); - *item = NULL; + dns__message_puttemprdataset(msg, item); } void @@ -2832,7 +2952,7 @@ dns_message_setopt(dns_message_t *msg, dns_rdataset_t *opt) { cleanup: dns_rdataset_disassociate(opt); - dns_message_puttemprdataset(msg, &opt); + dns__message_puttemprdataset(msg, &opt); return (result); } diff --git a/lib/dns/name.c b/lib/dns/name.c index 9713cf5f4ea..a0a53b26d60 100644 --- a/lib/dns/name.c +++ b/lib/dns/name.c @@ -215,6 +215,7 @@ dns_name_invalidate(dns_name_t *name) { name->offsets = NULL; name->buffer = NULL; ISC_LINK_INIT(name, link); + INSIST(name->ht == NULL); } bool