BIND 8.2.7 master ixfr to 9.2.2 slave

Mike Mitchell Mike.Mitchell at sas.com
Wed May 4 17:59:02 UTC 2005


About once a day I have a BIND 9.2.2 slave truncate a zone after an IXFR
from a BIND 8 master.  The packet trace shows the master sending an IXFR
response containing only two SOA records.  The SOA records are =
identical,
with serial numbers one more than the IXFR request.  I found this in RFC
1995:

    4. Response Format
       If incremental zone transfer is not available, the entire zone is
       returned. The first and the last RR of the response is the SOA
       record of the zone. I.e. the behavior is the same as an AXFR
       response except the query type is IXFR.

I read this to indicate that two SOA records in a row would be an empty
zone, so it makes sense that BIND 9 is truncating the zone.  This points
the finger back at BIND 8.  I haven't found the root cause of the =
problem
in BIND 8, but I have developed a patch against BIND 8.4.6 that aborts
the query instead of sending a two-SOA response.  Could someone look at
the patch and let me know if it's the right approach?  I have it in
testing now but it takes some time before the two-SOA response is
triggered.=20

Here's a unified diff against BIND 8.4.6:

--- src/bin/named/ns_ixfr.c.orig	2003-11-23 18:43:35.000000000 -0500
+++ src/bin/named/ns_ixfr.c	2005-05-04 11:38:22.000000000 -0400
@@ -189,7 +189,7 @@
 	struct databuf *old_soadp;
 	ns_delta *dp;
 	ns_updrec *rp;
-	int		foundsoa;
+	int		foundsoa, foundother;
=20
 	zp =3D &zones[qsp->xfr.zone];
 	soa_dp =3D (struct databuf *) findzonesoa(zp);
@@ -203,6 +203,8 @@
 		ns_panic(ns_log_update, 1, "sx_send_ixfr: out of memory");
 	memcpy(old_soadp, soa_dp, BIND_DATASIZE(soa_dp->d_size));
=20
+	foundother =3D 0;
+
  again:
 	switch (qsp->xfr.state) {
 	case s_x_firstsoa:
@@ -260,10 +262,12 @@
 					/*
 					 * Drop any SOA deletes
 					 */
-					if (rp->r_dp->d_type !=3D T_SOA &&
-					    sx_addrr(qsp, rp->r_dname,
-						     rp->r_dp) < 0)
-						goto cleanup;
+					if (rp->r_dp->d_type !=3D T_SOA) {
+						foundother =3D 1;
+						if (sx_addrr(qsp, rp->r_dname,
+							     rp->r_dp) < 0)
+							goto cleanup;
+					}
 					db_detach(&rp->r_dp);
 				}
 				rp =3D NEXT(rp, r_link);
@@ -323,6 +327,7 @@
 					if (rp->r_opcode =3D=3D ADD &&
 					    rp->r_dp !=3D NULL &&
 					    rp->r_dp->d_type !=3D T_SOA) {
+						foundother =3D 1;
 						if (sx_addrr(qsp, rp->r_dname,
 							     rp->r_dp) < 0)
 							goto cleanup;
@@ -360,9 +365,11 @@
 		break;
 	}
 	ns_debug(ns_log_default, 3, "IXFR: flushing %s", zp->z_origin);
-	qsp->xfr.state =3D s_x_done;
-	sx_flush(qsp);
-	sq_writeh(qsp, sq_flushw);
+	if (foundother) {
+		qsp->xfr.state =3D s_x_done;
+		sx_flush(qsp);
+		sq_writeh(qsp, sq_flushw);
+	}
 	if (qsp->xfr.top.ixfr !=3D NULL) {
 		if(!EMPTY(*qsp->xfr.top.ixfr)) {
 			while ((dp =3D HEAD(*qsp->xfr.top.ixfr)) !=3D NULL)  {
@@ -380,6 +387,11 @@
 		qsp->xfr.top.ixfr =3D NULL;
 	}
  cleanup:
+	if (qsp->xfr.state !=3D s_x_done) {
+		ns_error(ns_log_xfer_out, "ns_ixfr: transfer aborted");
+		(void) shutdown(qsp->s_rfd, 2);
+		sq_remove(qsp);
+	}
 	memput(old_soadp, BIND_DATASIZE(old_soadp->d_size));
 }
=20



More information about the bind-users mailing list