Merge branch 'ondrej/dns_message-refactoring' into 'main'

Refactor and cleanup the dns_message unit

See merge request isc-projects/bind9!8400
This commit is contained in:
Ondřej Surý 2023-10-25 10:37:16 +00:00
commit 8983bf8ed2
4 changed files with 159 additions and 186 deletions

View file

@ -78,4 +78,4 @@ PenaltyBreakString: 80
PenaltyExcessCharacter: 100
Standard: Cpp11
ContinuationIndentWidth: 8
ForEachMacros: [ 'cds_lfs_for_each', 'cds_lfs_for_each_safe', 'cds_list_for_each_entry_safe', 'ISC_LIST_FOREACH', 'ISC_LIST_FOREACH_SAFE' ]
ForEachMacros: [ 'cds_lfs_for_each', 'cds_lfs_for_each_safe', 'cds_list_for_each_entry_safe', 'ISC_LIST_FOREACH', 'ISC_LIST_FOREACH_SAFE', 'ISC_LIST_FOREACH_REV', 'ISC_LIST_FOREACH_REV_SAFE' ]

View file

@ -880,23 +880,6 @@ dns_message_find(const dns_name_t *name, dns_rdataclass_t rdclass,
*\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);

View file

@ -178,6 +178,15 @@ msgblock_allocate(isc_mem_t *, unsigned int, unsigned int);
#define msgblock_get(block, type) \
((type *)msgblock_internalget(block, sizeof(type)))
/*
* This function differs from public dns_message_puttemprdataset() that it
* requires the *rdatasetp to be associated, and it will disassociate and
* put it back to the memory pool.
*/
static void
dns__message_putassociatedrdataset(dns_message_t *msg,
dns_rdataset_t **rdatasetp);
static void *
msgblock_internalget(dns_msgblock_t *, unsigned int);
@ -434,32 +443,29 @@ msginit(dns_message_t *m) {
}
static void
msgresetnames(dns_message_t *msg, unsigned int first_section) {
unsigned int i;
dns_name_t *name, *next_name;
dns_rdataset_t *rds, *next_rds;
msgresetname(dns_message_t *msg, dns_name_t *name) {
dns_rdataset_t *rds = NULL, *next_rds = NULL;
/*
* Clean up name lists by calling the rdataset disassociate function.
*/
for (i = first_section; i < DNS_SECTION_MAX; i++) {
name = ISC_LIST_HEAD(msg->sections[i]);
while (name != NULL) {
next_name = ISC_LIST_NEXT(name, link);
ISC_LIST_FOREACH_SAFE (name->list, rds, link, next_rds) {
ISC_LIST_UNLINK(name->list, rds, link);
dns__message_putassociatedrdataset(msg, &rds);
}
}
static void
msgresetnames(dns_message_t *msg, unsigned int first_section) {
/* Clean up name lists. */
for (size_t i = first_section; i < DNS_SECTION_MAX; i++) {
dns_name_t *name = NULL, *next_name = NULL;
ISC_LIST_FOREACH_SAFE (msg->sections[i], name, link, next_name)
{
ISC_LIST_UNLINK(msg->sections[i], name, link);
rds = ISC_LIST_HEAD(name->list);
while (rds != NULL) {
next_rds = ISC_LIST_NEXT(rds, link);
ISC_LIST_UNLINK(name->list, rds, link);
msgresetname(msg, name);
INSIST(dns_rdataset_isassociated(rds));
dns_rdataset_disassociate(rds);
isc_mempool_put(msg->rdspool, rds);
rds = next_rds;
}
dns_message_puttempname(msg, &name);
name = next_name;
}
}
}
@ -471,9 +477,7 @@ msgresetopt(dns_message_t *msg) {
dns_message_renderrelease(msg, msg->opt_reserved);
msg->opt_reserved = 0;
}
INSIST(dns_rdataset_isassociated(msg->opt));
dns_rdataset_disassociate(msg->opt);
isc_mempool_put(msg->rdspool, msg->opt);
dns__message_putassociatedrdataset(msg, &msg->opt);
msg->opt = NULL;
msg->cc_ok = 0;
msg->cc_bad = 0;
@ -493,24 +497,20 @@ msgresetsigs(dns_message_t *msg, bool replying) {
INSIST(msg->querytsig == NULL);
msg->querytsig = msg->tsig;
} else {
dns_rdataset_disassociate(msg->tsig);
isc_mempool_put(msg->rdspool, msg->tsig);
dns__message_putassociatedrdataset(msg, &msg->tsig);
if (msg->querytsig != NULL) {
dns_rdataset_disassociate(msg->querytsig);
isc_mempool_put(msg->rdspool, msg->querytsig);
dns__message_putassociatedrdataset(
msg, &msg->querytsig);
}
}
dns_message_puttempname(msg, &msg->tsigname);
msg->tsig = NULL;
} else if (msg->querytsig != NULL && !replying) {
dns_rdataset_disassociate(msg->querytsig);
isc_mempool_put(msg->rdspool, msg->querytsig);
dns__message_putassociatedrdataset(msg, &msg->querytsig);
msg->querytsig = NULL;
}
if (msg->sig0 != NULL) {
INSIST(dns_rdataset_isassociated(msg->sig0));
dns_rdataset_disassociate(msg->sig0);
isc_mempool_put(msg->rdspool, msg->sig0);
dns__message_putassociatedrdataset(msg, &msg->sig0);
msg->sig0 = NULL;
}
if (msg->sig0name != NULL) {
@ -524,10 +524,10 @@ msgresetsigs(dns_message_t *msg, bool replying) {
*/
static void
msgreset(dns_message_t *msg, bool everything) {
dns_msgblock_t *msgblock, *next_msgblock;
isc_buffer_t *dynbuf, *next_dynbuf;
dns_rdata_t *rdata;
dns_rdatalist_t *rdatalist;
dns_msgblock_t *msgblock = NULL, *next_msgblock = NULL;
isc_buffer_t *dynbuf = NULL, *next_dynbuf = NULL;
dns_rdata_t *rdata = NULL;
dns_rdatalist_t *rdatalist = NULL;
msgresetnames(msg, 0);
msgresetopt(msg);
@ -782,14 +782,12 @@ ISC_REFCOUNT_IMPL(dns_message, dns__message_destroy);
static isc_result_t
findname(dns_name_t **foundname, const dns_name_t *target,
dns_namelist_t *section) {
dns_name_t *curr;
dns_name_t *name = NULL;
for (curr = ISC_LIST_TAIL(*section); curr != NULL;
curr = ISC_LIST_PREV(curr, link))
{
if (dns_name_equal(curr, target)) {
ISC_LIST_FOREACH_REV (*section, name, link) {
if (dns_name_equal(name, target)) {
if (foundname != NULL) {
*foundname = curr;
*foundname = name;
}
return (ISC_R_SUCCESS);
}
@ -801,21 +799,18 @@ findname(dns_name_t **foundname, const dns_name_t *target,
isc_result_t
dns_message_find(const dns_name_t *name, dns_rdataclass_t rdclass,
dns_rdatatype_t type, dns_rdatatype_t covers,
dns_rdataset_t **rdataset) {
dns_rdataset_t *curr;
dns_rdataset_t **rdatasetp) {
dns_rdataset_t *rds = NULL;
REQUIRE(name != NULL);
REQUIRE(rdataset == NULL || *rdataset == NULL);
REQUIRE(rdatasetp == NULL || *rdatasetp == NULL);
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)
ISC_LIST_FOREACH_REV (name->list, rds, link) {
if (rds->rdclass == rdclass && rds->type == type &&
rds->covers == covers)
{
if (rdataset != NULL) {
*rdataset = curr;
}
SET_IF_NOT_NULL(rdatasetp, rds);
return (ISC_R_SUCCESS);
}
}
@ -825,19 +820,16 @@ dns_message_find(const dns_name_t *name, dns_rdataclass_t rdclass,
isc_result_t
dns_message_findtype(const dns_name_t *name, dns_rdatatype_t type,
dns_rdatatype_t covers, dns_rdataset_t **rdataset) {
dns_rdataset_t *curr;
dns_rdatatype_t covers, dns_rdataset_t **rdatasetp) {
dns_rdataset_t *rds = NULL;
REQUIRE(name != NULL);
REQUIRE(rdataset == NULL || *rdataset == NULL);
REQUIRE(rdatasetp == NULL || *rdatasetp == NULL);
ISC_LIST_FOREACH_REV (name->list, rds, link) {
if (rds->type == type && rds->covers == covers) {
SET_IF_NOT_NULL(rdatasetp, rds);
for (curr = ISC_LIST_TAIL(name->list); curr != NULL;
curr = ISC_LIST_PREV(curr, link))
{
if (curr->type == type && curr->covers == covers) {
if (rdataset != NULL) {
*rdataset = curr;
}
return (ISC_R_SUCCESS);
}
}
@ -1081,8 +1073,7 @@ getquestions(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
cleanup:
if (rdataset != NULL) {
INSIST(!dns_rdataset_isassociated(rdataset));
isc_mempool_put(msg->rdspool, rdataset);
dns_message_puttemprdataset(msg, &rdataset);
}
if (free_name) {
dns_message_puttempname(msg, &name);
@ -1109,17 +1100,13 @@ update(dns_section_t section, dns_rdataclass_t rdclass) {
*/
static bool
auth_signed(dns_namelist_t *section) {
dns_name_t *name;
dns_name_t *name = NULL;
for (name = ISC_LIST_HEAD(*section); name != NULL;
name = ISC_LIST_NEXT(name, link))
{
ISC_LIST_FOREACH (*section, name, link) {
int auth_dnssec = 0, auth_rrsig = 0;
dns_rdataset_t *rds;
dns_rdataset_t *rds = NULL;
for (rds = ISC_LIST_HEAD(name->list); rds != NULL;
rds = ISC_LIST_NEXT(rds, link))
{
ISC_LIST_FOREACH (name->list, rds, link) {
switch (rds->type) {
case dns_rdatatype_ds:
auth_dnssec |= 0x1;
@ -1580,7 +1567,8 @@ getsection(isc_buffer_t *source, dns_message_t *msg, dns_decompress_t dctx,
dns_message_puttempname(msg, &name);
}
if (free_rdataset) {
isc_mempool_put(msg->rdspool, rdataset);
dns__message_putassociatedrdataset(msg,
&rdataset);
}
free_name = free_rdataset = false;
}
@ -1612,7 +1600,7 @@ cleanup:
dns_message_puttempname(msg, &name);
}
if (free_rdataset) {
isc_mempool_put(msg->rdspool, rdataset);
dns__message_putassociatedrdataset(msg, &rdataset);
}
return (result);
@ -2335,10 +2323,6 @@ dns_message_renderend(dns_message_t *msg) {
void
dns_message_renderreset(dns_message_t *msg) {
unsigned int i;
dns_name_t *name;
dns_rdataset_t *rds;
/*
* Reset the message so that it may be rendered again.
*/
@ -2348,15 +2332,14 @@ dns_message_renderreset(dns_message_t *msg) {
msg->buffer = NULL;
for (i = 0; i < DNS_SECTION_MAX; i++) {
for (size_t i = 0; i < DNS_SECTION_MAX; i++) {
dns_name_t *name = NULL;
msg->cursors[i] = NULL;
msg->counts[i] = 0;
for (name = ISC_LIST_HEAD(msg->sections[i]); name != NULL;
name = ISC_LIST_NEXT(name, link))
{
for (rds = ISC_LIST_HEAD(name->list); rds != NULL;
rds = ISC_LIST_NEXT(rds, link))
{
ISC_LIST_FOREACH (msg->sections[i], name, link) {
dns_rdataset_t *rds = NULL;
ISC_LIST_FOREACH (name->list, rds, link) {
rds->attributes &= ~DNS_RDATASETATTR_RENDERED;
}
}
@ -2469,22 +2452,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) {
@ -2580,6 +2547,13 @@ dns_message_puttemprdata(dns_message_t *msg, dns_rdata_t **item) {
*item = NULL;
}
static void
dns__message_putassociatedrdataset(dns_message_t *msg, dns_rdataset_t **item) {
dns_rdataset_disassociate(*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));
@ -3228,7 +3202,9 @@ dns_message_checksig(dns_message_t *msg, dns_view_t *view) {
dns_masterstyle_flags_t __flags = dns_master_styleflags(sp); \
if ((__flags & DNS_STYLEFLAG_INDENT) == 0ULL && \
(__flags & DNS_STYLEFLAG_YAML) == 0ULL) \
{ \
break; \
} \
for (__i = 0; __i < msg->indent.count; __i++) { \
ADD_STRING(target, msg->indent.string); \
} \
@ -3238,8 +3214,7 @@ isc_result_t
dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
const dns_master_style_t *style,
dns_messagetextflag_t flags, isc_buffer_t *target) {
dns_name_t *name, empty_name;
dns_rdataset_t *rdataset;
dns_name_t empty_name;
isc_result_t result = ISC_R_SUCCESS;
bool seensoa = false;
size_t saved_count;
@ -3284,13 +3259,13 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
msg->indent.count++;
}
do {
name = NULL;
dns_name_t *name = NULL;
dns_message_currentname(msg, section, &name);
for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link))
{
dns_rdataset_t *rds = NULL;
ISC_LIST_FOREACH (name->list, rds, link) {
if (section == DNS_SECTION_ANSWER &&
rdataset->type == dns_rdatatype_soa)
rds->type == dns_rdatatype_soa)
{
if ((flags & DNS_MESSAGETEXTFLAG_OMITSOA) != 0)
{
@ -3311,11 +3286,10 @@ dns_message_sectiontotext(dns_message_t *msg, dns_section_t section,
ADD_STRING(target, ";");
}
result = dns_master_questiontotext(
name, rdataset, style, target);
name, rds, style, target);
} else {
result = dns_master_rdatasettotext(
name, rdataset, style, &msg->indent,
target);
name, rds, style, &msg->indent, target);
}
if (result != ISC_R_SUCCESS) {
goto cleanup;
@ -3345,7 +3319,7 @@ cleanup:
static isc_result_t
render_ecs(isc_buffer_t *ecsbuf, isc_buffer_t *target) {
int i;
char addr[16], addr_text[64];
char addr[16] = { 0 }, addr_text[64];
uint16_t family;
uint8_t addrlen, addrbytes, scopelen;
isc_result_t result;
@ -3370,7 +3344,6 @@ render_ecs(isc_buffer_t *ecsbuf, isc_buffer_t *target) {
return (DNS_R_OPTERR);
}
memset(addr, 0, sizeof(addr));
for (i = 0; i < addrbytes; i++) {
addr[i] = isc_buffer_getuint8(ecsbuf);
}
@ -4660,10 +4633,56 @@ dns_message_clonebuffer(dns_message_t *msg) {
}
static isc_result_t
message_authority_soa_min(dns_message_t *msg, dns_ttl_t *pttl) {
rdataset_soa_min(dns_rdataset_t *rds, dns_ttl_t *ttlp) {
isc_result_t result;
/* loop over the rdatas */
for (result = dns_rdataset_first(rds); result == ISC_R_SUCCESS;
result = dns_rdataset_next(rds))
{
dns_name_t tmp;
isc_region_t r = { 0 };
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_current(rds, &rdata);
switch (rdata.type) {
case dns_rdatatype_soa:
/* SOA rdataset */
break;
case dns_rdatatype_none:
/*
* Negative cache rdataset: we need
* to inspect the rdata to determine
* whether it's an SOA.
*/
dns_rdata_toregion(&rdata, &r);
dns_name_init(&tmp, NULL);
dns_name_fromregion(&tmp, &r);
isc_region_consume(&r, tmp.length);
if (r.length < 2) {
continue;
}
rdata.type = r.base[0] << 8 | r.base[1];
if (rdata.type != dns_rdatatype_soa) {
continue;
}
break;
default:
continue;
}
if (rdata.type == dns_rdatatype_soa) {
*ttlp = ISC_MIN(rds->ttl, dns_soa_getminimum(&rdata));
return (ISC_R_SUCCESS);
}
}
return (ISC_R_NOTFOUND);
}
static isc_result_t
message_authority_soa_min(dns_message_t *msg, dns_ttl_t *ttlp) {
isc_result_t result;
dns_rdataset_t *rdataset = NULL;
dns_name_t *name = NULL;
if (msg->counts[DNS_SECTION_AUTHORITY] == 0) {
return (ISC_R_NOTFOUND);
@ -4673,62 +4692,19 @@ message_authority_soa_min(dns_message_t *msg, dns_ttl_t *pttl) {
result == ISC_R_SUCCESS;
result = dns_message_nextname(msg, DNS_SECTION_AUTHORITY))
{
name = NULL;
dns_name_t *name = NULL;
dns_message_currentname(msg, DNS_SECTION_AUTHORITY, &name);
for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL;
rdataset = ISC_LIST_NEXT(rdataset, link))
{
isc_result_t tresult;
if ((rdataset->attributes &
DNS_RDATASETATTR_RENDERED) == 0)
dns_rdataset_t *rds = NULL;
ISC_LIST_FOREACH (name->list, rds, link) {
if ((rds->attributes & DNS_RDATASETATTR_RENDERED) == 0)
{
continue;
}
/* loop over the rdatas */
for (tresult = dns_rdataset_first(rdataset);
tresult == ISC_R_SUCCESS;
tresult = dns_rdataset_next(rdataset))
{
dns_name_t tmp;
isc_region_t r = { 0 };
dns_rdata_t rdata = DNS_RDATA_INIT;
dns_rdataset_current(rdataset, &rdata);
switch (rdata.type) {
case dns_rdatatype_soa:
/* SOA rdataset */
break;
case dns_rdatatype_none:
/*
* Negative cache rdataset: we need
* to inspect the rdata to determine
* whether it's an SOA.
*/
dns_rdata_toregion(&rdata, &r);
dns_name_init(&tmp, NULL);
dns_name_fromregion(&tmp, &r);
isc_region_consume(&r, tmp.length);
if (r.length < 2) {
continue;
}
rdata.type = r.base[0] << 8 | r.base[1];
if (rdata.type != dns_rdatatype_soa) {
continue;
}
break;
default:
continue;
}
if (rdata.type == dns_rdatatype_soa) {
*pttl = ISC_MIN(
rdataset->ttl,
dns_soa_getminimum(&rdata));
return (ISC_R_SUCCESS);
}
result = rdataset_soa_min(rds, ttlp);
if (result == ISC_R_SUCCESS) {
return (ISC_R_SUCCESS);
}
}
}

View file

@ -241,3 +241,17 @@
elt != NULL; \
elt = next, next = (elt != NULL) ? ISC_LIST_NEXT(elt, link) : NULL)
/* clang-format on */
/* clang-format off */
#define ISC_LIST_FOREACH_REV(list, elt, link) \
for (elt = ISC_LIST_TAIL(list); \
elt != NULL; \
elt = ISC_LIST_PREV(elt, link))
/* clang-format on */
/* clang-format off */
#define ISC_LIST_FOREACH_REV_SAFE(list, elt, link, prev) \
for (elt = ISC_LIST_TAIL(list), prev = (elt != NULL) ? ISC_LIST_PREV(elt, link) : NULL; \
elt != NULL; \
elt = prev, prev = (elt != NULL) ? ISC_LIST_PREV(elt, link) : NULL)
/* clang-format on */