* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: xfrin.h,v 1.18.136.2 2004/03/06 08:14:01 marka Exp $ */
+/* $Id: xfrin.h,v 1.18.136.2.18.1 2006/08/03 23:16:40 marka Exp $ */
#ifndef DNS_XFRIN_H
#define DNS_XFRIN_H 1
* code as arguments when the transfer finishes.
*
* Requires:
- * 'xfrtype' is dns_rdatatype_axfr or dns_rdatatype_ixfr.
+ * 'xfrtype' is dns_rdatatype_axfr, dns_rdatatype_ixfr
+ * of dns_rdatatype_soa (soa query followed by axfr if
+ * serial is greater than current serial).
*
- * If 'xfrtype' is dns_rdatatype_ixfr, the zone has a
- * database.
+ * If 'xfrtype' is dns_rdatatype_ixfr or dns_rdatatype_soa,
+ * the zone has a database.
*/
void
* 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.12.2.1 2006/08/03 23:16:40 marka Exp $ */
#include <config.h>
* when the first two (2) response RRs have already been received.
*/
typedef enum {
+ XFRST_SOAQUERY,
+ XFRST_GOTSOA,
XFRST_INITIALSOA,
XFRST_FIRSTDATA,
XFRST_IXFR_DELSOA,
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,
(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));
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;
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++;
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;
}
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.
*/
* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.c,v 1.333.2.23.2.59.4.3 2006/06/04 23:33:26 marka Exp $ */
+/* $Id: zone.c,v 1.333.2.23.2.59.4.4 2006/08/03 23:16:40 marka Exp $ */
#include <config.h>
#define DNS_ZONEFLG_FLUSH 0x00200000U
#define DNS_ZONEFLG_NOEDNS 0x00400000U
#define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U
+#define DNS_ZONEFLG_SOABEFOREAXFR 0x01000000U
#define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
master, source);
/* Try with slave with TCP. */
if (zone->type == dns_zone_slave &&
- DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH))
+ DNS_ZONE_OPTION(zone, DNS_ZONEOPT_TRYTCPREFRESH)) {
+ LOCK_ZONE(zone);
+ DNS_ZONE_SETFLAG(zone,
+ DNS_ZONEFLG_SOABEFOREAXFR);
+ UNLOCK_ZONE(zone);
goto tcp_transfer;
+ }
} else
dns_zone_log(zone, ISC_LOG_INFO,
"refresh: failure trying master "
"initiating TCP zone xfer "
"for master %s (source %s)",
master, source);
+ LOCK_ZONE(zone);
+ DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
+ UNLOCK_ZONE(zone);
goto tcp_transfer;
} else {
INSIST(zone->type == dns_zone_stub);
LOCK_ZONE(zone);
INSIST((zone->flags & DNS_ZONEFLG_REFRESH) != 0);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR);
TIME_NOW(&now);
switch (result) {
"IXFR disabled, "
"requesting AXFR from %s",
mastertext);
- xfrtype = dns_rdatatype_axfr;
+ if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR))
+ xfrtype = dns_rdatatype_soa;
+ else
+ xfrtype = dns_rdatatype_axfr;
} else {
dns_zone_log(zone, ISC_LOG_DEBUG(1),
"requesting IXFR from %s",