diff --git a/bin/named/client.c b/bin/named/client.c index c9b0811635..6713d31173 100644 --- a/bin/named/client.c +++ b/bin/named/client.c @@ -323,11 +323,11 @@ ns_client_send(ns_client_t *client) { client->opt = NULL; } result = dns_message_rendersection(client->message, - DNS_SECTION_QUESTION, 0, 0); + DNS_SECTION_QUESTION, 0); if (result != ISC_R_SUCCESS) goto done; result = dns_message_rendersection(client->message, - DNS_SECTION_ANSWER, 0, 0); + DNS_SECTION_ANSWER, 0); if (result == ISC_R_NOSPACE) { client->message->flags |= DNS_MESSAGEFLAG_TC; goto renderend; @@ -335,7 +335,7 @@ ns_client_send(ns_client_t *client) { if (result != ISC_R_SUCCESS) goto done; result = dns_message_rendersection(client->message, - DNS_SECTION_AUTHORITY, 0, 0); + DNS_SECTION_AUTHORITY, 0); if (result == ISC_R_NOSPACE) { client->message->flags |= DNS_MESSAGEFLAG_TC; goto renderend; @@ -343,7 +343,7 @@ ns_client_send(ns_client_t *client) { if (result != ISC_R_SUCCESS) goto done; result = dns_message_rendersection(client->message, - DNS_SECTION_ADDITIONAL, 0, 0); + DNS_SECTION_ADDITIONAL, 0); if (result != ISC_R_SUCCESS && result != ISC_R_NOSPACE) goto done; renderend: diff --git a/bin/named/xfrout.c b/bin/named/xfrout.c index a0869d58bd..db61d572d0 100644 --- a/bin/named/xfrout.c +++ b/bin/named/xfrout.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: xfrout.c,v 1.31 1999/12/21 00:33:17 marka Exp $ */ + /* $Id: xfrout.c,v 1.32 1999/12/22 03:22:56 explorer Exp $ */ #include @@ -1281,10 +1281,8 @@ sendstream(xfrout_ctx_t *xfr) if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) { CHECK(dns_message_renderbegin(msg, &xfr->txbuf)); - CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, - 0, 0)); - CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, - 0, 0)); + CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0)); + CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0)); CHECK(dns_message_renderend(msg)); isc_buffer_used(&xfr->txbuf, &used); diff --git a/bin/tests/dispatch_tcp_test.c b/bin/tests/dispatch_tcp_test.c index a8a4ab8dbc..cda80d7dad 100644 --- a/bin/tests/dispatch_tcp_test.c +++ b/bin/tests/dispatch_tcp_test.c @@ -212,16 +212,16 @@ start_response(void) rdataset.attributes |= DNS_RDATASETATTR_QUESTION; - result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0); CHECKRESULT(result, "dns_message_rendersection(QUESTION)"); - result = dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0); CHECKRESULT(result, "dns_message_rendersection(ANSWER)"); - result = dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0); CHECKRESULT(result, "dns_message_rendersection(ADDITIONAL)"); - result = dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0); CHECKRESULT(result, "dns_message_rendersection(AUTHORITY)"); printf("--- adding response\n"); diff --git a/bin/tests/dispatch_test.c b/bin/tests/dispatch_test.c index 038d07a9e4..76d6656b38 100644 --- a/bin/tests/dispatch_test.c +++ b/bin/tests/dispatch_test.c @@ -188,16 +188,16 @@ start_response(clictx_t *cli, char *query, isc_task_t *task) cli->rdataset.attributes |= DNS_RDATASETATTR_QUESTION; - result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0); CHECKRESULT(result, "dns_message_rendersection(QUESTION)"); - result = dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0); CHECKRESULT(result, "dns_message_rendersection(ANSWER)"); - result = dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0); CHECKRESULT(result, "dns_message_rendersection(ADDITIONAL)"); - result = dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0); CHECKRESULT(result, "dns_message_rendersection(AUTHORITY)"); printf("--- adding response\n"); diff --git a/bin/tests/sdig.c b/bin/tests/sdig.c index b0b3e76e7e..bfcbccc47f 100644 --- a/bin/tests/sdig.c +++ b/bin/tests/sdig.c @@ -355,8 +355,7 @@ main(int argc, char *argv[]) { check_result(result, "dns_message_renderbegin()"); if (edns0) add_opt(message, (isc_uint16_t)bufsize); - result = dns_message_rendersection(message, DNS_SECTION_QUESTION, - 0, 0); + result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0); check_result(result, "dns_message_rendersection()"); result = dns_message_renderend(message); check_result(result, "dns_message_renderend()"); diff --git a/bin/tests/tkey_test.c b/bin/tests/tkey_test.c index ba1c2d79bb..9f2f2b012f 100644 --- a/bin/tests/tkey_test.c +++ b/bin/tests/tkey_test.c @@ -189,13 +189,13 @@ buildquery(void) { result = dns_message_renderbegin(query, &qbuffer); CHECK("dns_message_renderbegin", result); - result = dns_message_rendersection(query, DNS_SECTION_QUESTION, 0, 0); + result = dns_message_rendersection(query, DNS_SECTION_QUESTION, 0); CHECK("dns_message_rendersection(question)", result); - result = dns_message_rendersection(query, DNS_SECTION_ANSWER, 0, 0); + result = dns_message_rendersection(query, DNS_SECTION_ANSWER, 0); CHECK("dns_message_rendersection(answer)", result); - result = dns_message_rendersection(query, DNS_SECTION_AUTHORITY, 0, 0); + result = dns_message_rendersection(query, DNS_SECTION_AUTHORITY, 0); CHECK("dns_message_rendersection(auth)", result); - result = dns_message_rendersection(query, DNS_SECTION_ADDITIONAL, 0, 0); + result = dns_message_rendersection(query, DNS_SECTION_ADDITIONAL, 0); CHECK("dns_message_rendersection(add)", result); result = dns_message_renderend(query); CHECK("dns_message_renderend", result); @@ -229,14 +229,13 @@ buildquery2(void) { result = dns_message_renderbegin(query2, &qbuffer); CHECK("dns_message_renderbegin", result); - result = dns_message_rendersection(query2, DNS_SECTION_QUESTION, 0, 0); + result = dns_message_rendersection(query2, DNS_SECTION_QUESTION, 0); CHECK("dns_message_rendersection(question)", result); - result = dns_message_rendersection(query2, DNS_SECTION_ANSWER, 0, 0); + result = dns_message_rendersection(query2, DNS_SECTION_ANSWER, 0); CHECK("dns_message_rendersection(answer)", result); - result = dns_message_rendersection(query2, DNS_SECTION_AUTHORITY, 0, 0); + result = dns_message_rendersection(query2, DNS_SECTION_AUTHORITY, 0); CHECK("dns_message_rendersection(auth)", result); - result = dns_message_rendersection(query2, DNS_SECTION_ADDITIONAL, - 0, 0); + result = dns_message_rendersection(query2, DNS_SECTION_ADDITIONAL, 0); CHECK("dns_message_rendersection(add)", result); result = dns_message_renderend(query2); CHECK("dns_message_renderend", result); diff --git a/bin/tests/wire_test.c b/bin/tests/wire_test.c index 06e352db0f..6262d334df 100644 --- a/bin/tests/wire_test.c +++ b/bin/tests/wire_test.c @@ -157,24 +157,19 @@ main(int argc, char *argv[]) { result = dns_message_renderbegin(message, &source); CHECKRESULT(result, "dns_message_renderbegin() failed"); - result = dns_message_rendersection(message, DNS_SECTION_QUESTION, - 0, 0); + result = dns_message_rendersection(message, DNS_SECTION_QUESTION, 0); CHECKRESULT(result, "dns_message_rendersection(QUESTION) failed"); - result = dns_message_rendersection(message, DNS_SECTION_ANSWER, - 0, 0); + result = dns_message_rendersection(message, DNS_SECTION_ANSWER, 0); CHECKRESULT(result, "dns_message_rendersection(ANSWER) failed"); - result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, - 0, 0); + result = dns_message_rendersection(message, DNS_SECTION_AUTHORITY, 0); CHECKRESULT(result, "dns_message_rendersection(AUTHORITY) failed"); - result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, - 0, 0); + result = dns_message_rendersection(message, DNS_SECTION_ADDITIONAL, 0); CHECKRESULT(result, "dns_message_rendersection(ADDITIONAL) failed"); - result = dns_message_rendersection(message, DNS_SECTION_TSIG, - 0, 0); + result = dns_message_rendersection(message, DNS_SECTION_TSIG, 0); CHECKRESULT(result, "dns_message_rendersection(TSIG) failed"); dns_message_renderend(message); diff --git a/lib/dns/include/dns/message.h b/lib/dns/include/dns/message.h index 9df9657b53..4def7035ac 100644 --- a/lib/dns/include/dns/message.h +++ b/lib/dns/include/dns/message.h @@ -138,6 +138,11 @@ typedef int dns_section_t; #define DNS_MESSAGE_INTENTPARSE 1 /* parsing messages */ #define DNS_MESSAGE_INTENTRENDER 2 /* rendering */ +/* + * Control behavior of rendering + */ +#define DNS_MESSAGERENDER_ORDERED 0x0001 /* don't change order */ + typedef struct dns_msgblock dns_msgblock_t; struct dns_message { @@ -394,7 +399,7 @@ dns_message_renderrelease(dns_message_t *msg, unsigned int space); dns_result_t dns_message_rendersection(dns_message_t *msg, dns_section_t section, - unsigned int priority, unsigned int options); + unsigned int options); /* * Render all names, rdatalists, etc from the given section at the * specified priority or higher. diff --git a/lib/dns/message.c b/lib/dns/message.c index 8a1345ffee..b2a7426536 100644 --- a/lib/dns/message.c +++ b/lib/dns/message.c @@ -1441,9 +1441,40 @@ dns_message_renderreserve(dns_message_t *msg, unsigned int space) return (DNS_R_SUCCESS); } +static inline isc_boolean_t +wrong_priority(dns_rdataset_t *rds, int pass) +{ + int pass_needed; + + /* + * If we are not rendering class IN, this ordering is bogus. + */ + if (rds->rdclass != dns_rdataclass_in) + return (ISC_FALSE); + + switch (rds->type) { + case dns_rdatatype_a: + case dns_rdatatype_aaaa: + case dns_rdatatype_a6: + pass_needed = 3; + break; + case dns_rdatatype_sig: + case dns_rdatatype_key: + pass_needed = 2; + break; + default: + pass_needed = 1; + } + + if (pass_needed >= pass) + return (ISC_FALSE); + + return (ISC_TRUE); +} + dns_result_t dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, - unsigned int priority, unsigned int options) + unsigned int options) { dns_namelist_t *section; dns_name_t *name, *next_name; @@ -1451,9 +1482,7 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, unsigned int count, total; dns_result_t result; isc_buffer_t st; /* for rollbacks */ - - (void)priority; /* XXXMLG implement */ - (void)options; /* XXXMLG implement */ + int pass; REQUIRE(DNS_MESSAGE_VALID(msg)); REQUIRE(msg->buffer != NULL); @@ -1461,9 +1490,11 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, section = &msg->sections[sectionid]; - name = ISC_LIST_HEAD(*section); - if (name == NULL) - return (DNS_R_SUCCESS); + if ((sectionid == DNS_SECTION_ADDITIONAL) + && (options & DNS_MESSAGERENDER_ORDERED) == 0) + pass = 3; + else + pass = 1; /* * Shrink the space in the buffer by the reserved amount. @@ -1471,66 +1502,77 @@ dns_message_rendersection(dns_message_t *msg, dns_section_t sectionid, msg->buffer->length -= msg->reserved; total = 0; - while (name != NULL) { - next_name = ISC_LIST_NEXT(name, link); - rdataset = ISC_LIST_HEAD(name->list); - while (rdataset != NULL) { - next_rdataset = ISC_LIST_NEXT(rdataset, link); + do { + name = ISC_LIST_HEAD(*section); + if (name == NULL) + return (DNS_R_SUCCESS); - if (rdataset->attributes & DNS_RDATASETATTR_RENDERED) { + while (name != NULL) { + next_name = ISC_LIST_NEXT(name, link); + + rdataset = ISC_LIST_HEAD(name->list); + while (rdataset != NULL) { + next_rdataset = ISC_LIST_NEXT(rdataset, link); + + if (rdataset->attributes & DNS_RDATASETATTR_RENDERED) + goto next; + + if (((options & DNS_MESSAGERENDER_ORDERED) == 0) + && (sectionid == DNS_SECTION_ADDITIONAL) + && wrong_priority(rdataset, pass)) + goto next; + + st = *(msg->buffer); + + count = 0; + result = dns_rdataset_towire(rdataset, name, + &msg->cctx, + msg->buffer, &count); + + total += count; + + /* + * If out of space, record stats on what we rendered + * so far, and return that status. + * + * XXXMLG Need to change this when + * dns_rdataset_towire() can render partial + * sets starting at some arbitary point in the set. + * This will include setting a bit in the + * rdataset to indicate that a partial rendering + * was done, and some state saved somewhere + * (probably in the message struct) + * to indicate where to continue from. + */ + if (result != DNS_R_SUCCESS) { + INSIST(st.used < 65536); + dns_compress_rollback(&msg->cctx, + (isc_uint16_t)st.used); + *(msg->buffer) = st; /* rollback */ + msg->buffer->length += msg->reserved; + msg->counts[sectionid] += total; + return (result); + } + + /* + * If we have rendered pending data, ensure that the + * AD bit is not set. + */ + if (rdataset->trust == dns_trust_pending && + (sectionid == DNS_SECTION_ANSWER || + sectionid == DNS_SECTION_AUTHORITY)) + msg->flags &= ~DNS_MESSAGEFLAG_AD; + + rdataset->attributes |= DNS_RDATASETATTR_RENDERED; + + next: rdataset = next_rdataset; - continue; } - st = *(msg->buffer); - - count = 0; - result = dns_rdataset_towire(rdataset, name, - &msg->cctx, - msg->buffer, &count); - - total += count; - - /* - * If out of space, record stats on what we rendered - * so far, and return that status. - * - * XXXMLG Need to change this when - * dns_rdataset_towire() can render partial - * sets starting at some arbitary point in the set. - * This will include setting a bit in the - * rdataset to indicate that a partial rendering - * was done, and some state saved somewhere - * (probably in the message struct) - * to indicate where to continue from. - */ - if (result != DNS_R_SUCCESS) { - INSIST(st.used < 65536); - dns_compress_rollback(&msg->cctx, - (isc_uint16_t)st.used); - *(msg->buffer) = st; /* rollback */ - msg->buffer->length += msg->reserved; - msg->counts[sectionid] += total; - return (result); - } - - /* - * If we have rendered pending data, ensure that the - * AD bit is not set. - */ - if (rdataset->trust == dns_trust_pending && - (sectionid == DNS_SECTION_ANSWER || - sectionid == DNS_SECTION_AUTHORITY)) - msg->flags &= ~DNS_MESSAGEFLAG_AD; - - rdataset->attributes |= DNS_RDATASETATTR_RENDERED; - - rdataset = next_rdataset; + name = next_name; } - - name = next_name; - } + } while (--pass != 0); msg->buffer->length += msg->reserved; msg->counts[sectionid] += total; @@ -1622,7 +1664,7 @@ dns_message_renderend(dns_message_t *msg) result = dns_tsig_sign(msg); if (result != DNS_R_SUCCESS) return (result); - result = dns_message_rendersection(msg, DNS_SECTION_TSIG, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_TSIG, 0); if (result != DNS_R_SUCCESS) return (result); } @@ -1631,7 +1673,7 @@ dns_message_renderend(dns_message_t *msg) result = dns_dnssec_signmessage(msg, msg->sig0key); if (result != DNS_R_SUCCESS) return (result); - result = dns_message_rendersection(msg, DNS_SECTION_SIG0, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_SIG0, 0); if (result != DNS_R_SUCCESS) return (result); } diff --git a/lib/dns/resolver.c b/lib/dns/resolver.c index 6dbaaff7ec..c494c2cac3 100644 --- a/lib/dns/resolver.c +++ b/lib/dns/resolver.c @@ -750,7 +750,7 @@ resquery_send(resquery_t *query) { goto cleanup_message; result = dns_message_rendersection(fctx->qmessage, - DNS_SECTION_QUESTION, 0, 0); + DNS_SECTION_QUESTION, 0); if (result != ISC_R_SUCCESS) goto cleanup_message; @@ -785,7 +785,7 @@ resquery_send(resquery_t *query) { */ result = dns_message_rendersection(fctx->qmessage, - DNS_SECTION_ADDITIONAL, 0, 0); + DNS_SECTION_ADDITIONAL, 0); if (result != ISC_R_SUCCESS) goto cleanup_message; diff --git a/lib/dns/xfrin.c b/lib/dns/xfrin.c index fe94d8571e..a7efb2d6bc 100644 --- a/lib/dns/xfrin.c +++ b/lib/dns/xfrin.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: xfrin.c,v 1.33 1999/12/13 07:57:36 marka Exp $ */ + /* $Id: xfrin.c,v 1.34 1999/12/22 03:22:59 explorer Exp $ */ #include @@ -690,11 +690,11 @@ static dns_result_t render(dns_message_t *msg, isc_buffer_t *buf) { dns_result_t result; CHECK(dns_message_renderbegin(msg, buf)); - CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0, 0)); - CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0, 0)); - CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0, 0)); - CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0, 0)); - CHECK(dns_message_rendersection(msg, DNS_SECTION_TSIG, 0, 0)); + CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0)); + CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0)); + CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0)); + CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0)); + CHECK(dns_message_rendersection(msg, DNS_SECTION_TSIG, 0)); CHECK(dns_message_renderend(msg)); result = DNS_R_SUCCESS; failure: diff --git a/lib/dns/zone.c b/lib/dns/zone.c index ec517d4858..6165e319ec 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: zone.c,v 1.49 1999/12/16 23:29:06 explorer Exp $ */ + /* $Id: zone.c,v 1.50 1999/12/22 03:22:59 explorer Exp $ */ #include @@ -2274,16 +2274,16 @@ dns_notify(dns_name_t *name, isc_sockaddr_t *addr, dns_rdatatype_t type, result = dns_message_renderbegin(msg, &target); if (result != DNS_R_SUCCESS) goto cleanup; - result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0); if (result != DNS_R_SUCCESS) goto cleanup; - result = dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0); if (result != DNS_R_SUCCESS) goto cleanup; - result = dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0); if (result != DNS_R_SUCCESS) goto cleanup; - result = dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0, 0); + result = dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0); if (result != DNS_R_SUCCESS) goto cleanup;