summaryrefslogtreecommitdiffstats
path: root/contrib/bind9/lib/dns/xfrin.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/bind9/lib/dns/xfrin.c')
-rw-r--r--contrib/bind9/lib/dns/xfrin.c67
1 files changed, 59 insertions, 8 deletions
diff --git a/contrib/bind9/lib/dns/xfrin.c b/contrib/bind9/lib/dns/xfrin.c
index 8a824a73..fdeed14 100644
--- a/contrib/bind9/lib/dns/xfrin.c
+++ b/contrib/bind9/lib/dns/xfrin.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2004, 2005 Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
* Copyright (C) 1999-2003 Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
@@ -15,7 +15,7 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: xfrin.c,v 1.124.2.4.2.12 2005/11/03 23:08:41 marka Exp $ */
+/* $Id: xfrin.c,v 1.124.2.4.2.16 2006/07/19 01:04:24 marka Exp $ */
#include <config.h>
@@ -73,6 +73,8 @@
* when the first two (2) response RRs have already been received.
*/
typedef enum {
+ XFRST_SOAQUERY,
+ XFRST_GOTSOA,
XFRST_INITIALSOA,
XFRST_FIRSTDATA,
XFRST_IXFR_DELSOA,
@@ -424,6 +426,30 @@ xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
redo:
switch (xfr->state) {
+ case XFRST_SOAQUERY:
+ if (rdata->type != dns_rdatatype_soa) {
+ xfrin_log(xfr, ISC_LOG_ERROR,
+ "non-SOA response to SOA query");
+ FAIL(DNS_R_FORMERR);
+ }
+ xfr->end_serial = dns_soa_getserial(rdata);
+ if (!DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) &&
+ !dns_zone_isforced(xfr->zone)) {
+ xfrin_log(xfr, ISC_LOG_DEBUG(3),
+ "requested serial %u, "
+ "master has %u, not updating",
+ xfr->ixfr.request_serial, xfr->end_serial);
+ FAIL(DNS_R_UPTODATE);
+ }
+ xfr->state = XFRST_GOTSOA;
+ break;
+
+ case XFRST_GOTSOA:
+ /*
+ * Skip other records in the answer section.
+ */
+ break;
+
case XFRST_INITIALSOA:
if (rdata->type != dns_rdatatype_soa) {
xfrin_log(xfr, ISC_LOG_ERROR,
@@ -589,6 +615,9 @@ dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype,
(void)dns_zone_getdb(zone, &db);
+ if (xfrtype == dns_rdatatype_soa || xfrtype == dns_rdatatype_ixfr)
+ REQUIRE(db != NULL);
+
CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename,
dns_zone_getclass(zone), xfrtype, masteraddr,
sourceaddr, tsigkey, &xfr));
@@ -754,7 +783,10 @@ xfrin_create(isc_mem_t *mctx,
dns_diff_init(xfr->mctx, &xfr->diff);
xfr->difflen = 0;
- xfr->state = XFRST_INITIALSOA;
+ if (reqtype == dns_rdatatype_soa)
+ xfr->state = XFRST_SOAQUERY;
+ else
+ xfr->state = XFRST_INITIALSOA;
/* end_serial */
xfr->nmsg = 0;
@@ -797,7 +829,18 @@ xfrin_create(isc_mem_t *mctx,
return (ISC_R_SUCCESS);
failure:
- xfrin_fail(xfr, result, "failed creating transfer context");
+ if (xfr->timer != NULL)
+ isc_timer_detach(&xfr->timer);
+ if (dns_name_dynamic(&xfr->name))
+ dns_name_free(&xfr->name, xfr->mctx);
+ if (xfr->tsigkey != NULL)
+ dns_tsigkey_detach(&xfr->tsigkey);
+ if (xfr->db != NULL)
+ dns_db_detach(&xfr->db);
+ isc_task_detach(&xfr->task);
+ dns_zone_idetach(&xfr->zone);
+ isc_mem_put(mctx, xfr, sizeof(*xfr));
+
return (result);
}
@@ -808,7 +851,9 @@ xfrin_start(dns_xfrin_ctx_t *xfr) {
isc_sockaddr_pf(&xfr->sourceaddr),
isc_sockettype_tcp,
&xfr->socket));
+#ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr));
+#endif
CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task,
xfrin_connect_done, xfr));
xfr->connects++;
@@ -987,7 +1032,9 @@ xfrin_send_request(dns_xfrin_ctx_t *xfr) {
CHECK(tuple2msgname(soatuple, msg, &msgsoaname));
dns_message_addname(msg, msgsoaname, DNS_SECTION_AUTHORITY);
- }
+ } else if (xfr->reqtype == dns_rdatatype_soa)
+ CHECK(dns_db_getsoaserial(xfr->db, NULL,
+ &xfr->ixfr.request_serial));
xfr->checkid = ISC_TRUE;
xfr->id++;
@@ -1148,8 +1195,8 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
try_axfr:
dns_message_destroy(&msg);
xfrin_reset(xfr);
- xfr->reqtype = dns_rdatatype_axfr;
- xfr->state = XFRST_INITIALSOA;
+ xfr->reqtype = dns_rdatatype_soa;
+ xfr->state = XFRST_SOAQUERY;
(void)xfrin_start(xfr);
return;
}
@@ -1246,7 +1293,11 @@ xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
dns_message_destroy(&msg);
- if (xfr->state == XFRST_END) {
+ if (xfr->state == XFRST_GOTSOA) {
+ xfr->reqtype = dns_rdatatype_axfr;
+ xfr->state = XFRST_INITIALSOA;
+ CHECK(xfrin_send_request(xfr));
+ } else if (xfr->state == XFRST_END) {
/*
* Inform the caller we succeeded.
*/
OpenPOWER on IntegriCloud