From: Andreas Gustafsson Date: Mon, 8 Jan 2001 20:11:40 +0000 (+0000) Subject: pullup to 9.0: X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e9607e31b7d81f06f82ee2170d4ef43bc357a42;p=thirdparty%2Fbind9.git pullup to 9.0: 661. [bug] Certain UDP IXFR requests caused an assertion failure (mpctx->allocated == 0). [RT #355, #394, #623] --- diff --git a/CHANGES b/CHANGES index 370437453a8..fe339b79b31 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,7 @@ + 661. [bug] Certain UDP IXFR requests caused an assertion failure + (mpctx->allocated == 0). [RT #355, #394, #623] + 589. [bug] The server could deadlock if a zone was updated while being transferred out. diff --git a/bin/named/xfrout.c b/bin/named/xfrout.c index ee823c326ef..68155f6d76e 100644 --- a/bin/named/xfrout.c +++ b/bin/named/xfrout.c @@ -15,7 +15,7 @@ * SOFTWARE. */ -/* $Id: xfrout.c,v 1.68.2.4 2000/12/04 18:59:40 bwelling Exp $ */ +/* $Id: xfrout.c,v 1.68.2.5 2001/01/08 20:11:40 gson Exp $ */ #include @@ -1233,7 +1233,8 @@ failure: */ static void sendstream(xfrout_ctx_t *xfr) { - dns_message_t *msg = NULL; + dns_message_t *tcpmsg = NULL; + dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */ isc_result_t result; isc_region_t used; isc_region_t region; @@ -1244,67 +1245,78 @@ sendstream(xfrout_ctx_t *xfr) { isc_buffer_clear(&xfr->txlenbuf); isc_buffer_clear(&xfr->txbuf); - /* - * Build a response dns_message_t, temporarily storing the raw, - * uncompressed owner names and RR data contiguously in xfr->buf. - * We know that if the uncompressed data fits in xfr->buf, - * the compressed data will surely fit in a TCP message. - */ - - msg = NULL; - CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg)); + if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) { + /* + * In the UDP case, we put the response data directly into + * the client message. + */ + msg = xfr->client->message; + CHECK(dns_message_reply(msg, ISC_TRUE)); + } else { + /* + * TCP. Build a response dns_message_t, temporarily storing + * the raw, uncompressed owner names and RR data contiguously + * in xfr->buf. We know that if the uncompressed data fits + * in xfr->buf, the compressed data will surely fit in a TCP + * message. + */ - msg->id = xfr->id; - msg->rcode = dns_rcode_noerror; - msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA; - if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0) - msg->flags |= DNS_MESSAGEFLAG_RA; - dns_message_settsigkey(msg, xfr->tsigkey); - CHECK(dns_message_setquerytsig(msg, xfr->lasttsig)); - if (xfr->lasttsig != NULL) - isc_buffer_free(&xfr->lasttsig); + CHECK(dns_message_create(xfr->mctx, + DNS_MESSAGE_INTENTRENDER, &tcpmsg)); + msg = tcpmsg; - /* - * Include a question section in the first message only. - * BIND 8.2.1 will not recognize an IXFR if it does not have a - * question section. - */ - if (xfr->nmsg == 0) { - dns_name_t *qname = NULL; - isc_region_t r; + msg->id = xfr->id; + msg->rcode = dns_rcode_noerror; + msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA; + if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0) + msg->flags |= DNS_MESSAGEFLAG_RA; + dns_message_settsigkey(msg, xfr->tsigkey); + CHECK(dns_message_setquerytsig(msg, xfr->lasttsig)); + if (xfr->lasttsig != NULL) + isc_buffer_free(&xfr->lasttsig); /* - * Reserve space for the 12-byte message header - * and 4 bytes of question. + * Include a question section in the first message only. + * BIND 8.2.1 will not recognize an IXFR if it does not + * have a question section. */ - isc_buffer_add(&xfr->buf, 12 + 4); + if (xfr->nmsg == 0) { + dns_name_t *qname = NULL; + isc_region_t r; - qrdataset = NULL; - result = dns_message_gettemprdataset(msg, &qrdataset); - if (result != ISC_R_SUCCESS) - goto failure; - dns_rdataset_init(qrdataset); - dns_rdataset_makequestion(qrdataset, - xfr->client->message->rdclass, - xfr->qtype); + /* + * Reserve space for the 12-byte message header + * and 4 bytes of question. + */ + isc_buffer_add(&xfr->buf, 12 + 4); - result = dns_message_gettempname(msg, &qname); - if (result != ISC_R_SUCCESS) - goto failure; - dns_name_init(qname, NULL); - isc_buffer_availableregion(&xfr->buf, &r); - INSIST(r.length >= xfr->qname->length); - r.length = xfr->qname->length; - isc_buffer_putmem(&xfr->buf, xfr->qname->ndata, - xfr->qname->length); - dns_name_fromregion(qname, &r); - ISC_LIST_INIT(qname->list); - ISC_LIST_APPEND(qname->list, qrdataset, link); - - dns_message_addname(msg, qname, DNS_SECTION_QUESTION); + qrdataset = NULL; + result = dns_message_gettemprdataset(msg, &qrdataset); + if (result != ISC_R_SUCCESS) + goto failure; + dns_rdataset_init(qrdataset); + dns_rdataset_makequestion(qrdataset, + xfr->client->message->rdclass, + xfr->qtype); + + result = dns_message_gettempname(msg, &qname); + if (result != ISC_R_SUCCESS) + goto failure; + dns_name_init(qname, NULL); + isc_buffer_availableregion(&xfr->buf, &r); + INSIST(r.length >= xfr->qname->length); + r.length = xfr->qname->length; + isc_buffer_putmem(&xfr->buf, xfr->qname->ndata, + xfr->qname->length); + dns_name_fromregion(qname, &r); + ISC_LIST_INIT(qname->list); + ISC_LIST_APPEND(qname->list, qrdataset, link); + + dns_message_addname(msg, qname, DNS_SECTION_QUESTION); + } + else + msg->tcp_continuation = 1; } - else - msg->tcp_continuation = 1; /* * Try to fit in as many RRs as possible, unless "one-answer" @@ -1420,16 +1432,11 @@ sendstream(xfrout_ctx_t *xfr) { xfr)); xfr->sends++; } else { - xfrout_log(xfr, ISC_LOG_DEBUG(8), - "sending IXFR UDP response"); - /* XXX kludge */ - dns_message_destroy(&xfr->client->message); - xfr->client->message = msg; - msg = NULL; + xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response"); ns_client_send(xfr->client); + xfr->stream->methods->pause(xfr->stream); xfrout_ctx_destroy(&xfr); - result = ISC_R_SUCCESS; - goto done; + return; } /* Advance lasttsig to be the last TSIG generated */ @@ -1441,11 +1448,9 @@ sendstream(xfrout_ctx_t *xfr) { /* * XXXRTH need to cleanup qname and qrdataset... */ - if (msg != NULL) { - dns_message_destroy(&msg); - } + if (tcpmsg != NULL) + dns_message_destroy(&tcpmsg); - done: /* * Make sure to release any locks held by database * iterators before returning from the event handler.