This is a discussion on Re: BIND 8.2.7 master ixfr to 9.2.2 slave within the Bind Users forums, part of the DNS and Related Forums category; About once a day I have a BIND 9.2.2 slave truncate a zone after an IXFR from a ...
|
|||||||
| FAQ | Members List | Calendar | Search | Today's Posts | Mark Forums Read |
|
|||
|
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 |