]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
ixfr-from-differences backup file
authorMark Andrews <marka@isc.org>
Fri, 9 Dec 2011 13:32:42 +0000 (13:32 +0000)
committerMark Andrews <marka@isc.org>
Fri, 9 Dec 2011 13:32:42 +0000 (13:32 +0000)
bin/tests/system/inline/setup.sh
bin/tests/system/inline/tests.sh
lib/dns/zone.c

index 84c89c9a54ea670f520e62a9e4a06f0e75fd9e5b..e18ed87e2d57c5bae6ef9c27fbbc4ec8d5305ee4 100644 (file)
@@ -12,7 +12,7 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: setup.sh,v 1.5 2011/10/26 20:56:45 marka Exp $
+# $Id: setup.sh,v 1.6 2011/12/09 13:32:42 marka Exp $
 
 sh clean.sh
 
@@ -49,6 +49,7 @@ cp ns3/master.db.in ns3/dynamic.db
 touch ns4/trusted.conf
 cp ns4/noixfr.db.in ns4/noixfr.db
 rm -f ns4/noixfr.db.jnl
+rm -f ns?/*.pvt
 
 cp ns5/named.conf.pre ns5/named.conf
 
index fbcd96f9172ef0aa819000e0a3aaf963869731e0..21ea1b0bb054d60c26a6d432713b24fd7b1b1e1a 100644 (file)
@@ -14,7 +14,7 @@
 # OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 # PERFORMANCE OF THIS SOFTWARE.
 
-# $Id: tests.sh,v 1.7 2011/12/02 02:44:01 marka Exp $
+# $Id: tests.sh,v 1.8 2011/12/09 13:32:42 marka Exp $
 
 SYSTEMTESTTOP=..
 . $SYSTEMTESTTOP/conf.sh
@@ -605,4 +605,32 @@ done
 if [ $ret != 0 ]; then echo "I:failed"; fi
 status=`expr $status + $ret`
 
+n=`expr $n + 1`
+echo "I:check that changes to master made while server is stopped are detected"
+$PERL ../stop.pl --use-rndc . ns3 || { ret=1; echo "I: failed to stop server"; }
+sleep 1
+awk '$2 == ";" && $3 == "serial" { print $1 + 1, $2, $3; next; }
+     { print; }
+     END { print "stopped.master. 0 TXT stopped"; } ' ns3/master.db > ns3/master.db.new
+mv ns3/master.db.new ns3/master.db
+$PERL ../start.pl --noclean --restart . ns3 || { ret=1; "I: failed to restart server" ; }
+sleep 1;
+$RNDC -c ../common/rndc.conf -s 10.53.0.3 -p 9953 reload master 2>&1 | sed 's/^/I:ns3 /'
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
+n=`expr $n + 1`
+echo "I:check added record stopped.master ($n)"
+for i in 1 2 3 4 5 6 7 8 9
+do
+    ret=0
+    $DIG $DIGOPTS @10.53.0.3 -p 5300 stopped.master TXT > dig.out.ns3.test$n
+    grep "status: NOERROR" dig.out.ns3.test$n > /dev/null || ret=1
+    grep "ANSWER: 2," dig.out.ns3.test$n > /dev/null || ret=1
+    test $ret = 0 && break
+    sleep 1
+done
+if [ $ret != 0 ]; then echo "I:failed"; fi
+status=`expr $status + $ret`
+
 exit $status
index 34fe7c7a0ba9c95938643b2c542ec0dab15bb2c3..1a80c20977164b8747da0b508de0605ad36a4d43 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: zone.c,v 1.652 2011/12/08 23:46:48 tbox Exp $ */
+/* $Id: zone.c,v 1.653 2011/12/09 13:32:41 marka Exp $ */
 
 /*! \file */
 
@@ -205,6 +205,7 @@ struct dns_zone {
        dns_masterformat_t      masterformat;
        char                    *journal;
        isc_int32_t             journalsize;
+       char                    *privatefile;
        dns_rdataclass_t        rdclass;
        dns_zonetype_t          type;
        unsigned int            flags;
@@ -417,6 +418,7 @@ struct dns_zone {
 #define DNS_ZONEFLG_LOADPENDING        0x10000000U     /*%< Loading scheduled */
 #define DNS_ZONEFLG_NODELAY    0x20000000U
 #define DNS_ZONEFLG_SENDSECURE  0x40000000U
+#define DNS_ZONEFLG_LOADPRIVATE 0x80000000U
 
 #define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)
 #define DNS_ZONEKEY_OPTION(z,o) (((z)->keyopts & (o)) != 0)
@@ -642,6 +644,7 @@ static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db,
 static inline void zone_attachdb(dns_zone_t *zone, dns_db_t *db);
 static inline void zone_detachdb(dns_zone_t *zone);
 static isc_result_t default_journal(dns_zone_t *zone);
+static isc_result_t default_private(dns_zone_t *zone);
 static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);
 static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db,
                                  isc_time_t loadtime, isc_result_t result);
@@ -806,6 +809,7 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) {
        zone->keydirectory = NULL;
        zone->journalsize = -1;
        zone->journal = NULL;
+       zone->privatefile = NULL;
        zone->rdclass = dns_rdataclass_none;
        zone->type = dns_zone_none;
        zone->flags = 0;
@@ -989,6 +993,9 @@ zone_free(dns_zone_t *zone) {
        if (zone->journal != NULL)
                isc_mem_free(zone->mctx, zone->journal);
        zone->journal = NULL;
+       if (zone->privatefile != NULL)
+               isc_mem_free(zone->mctx, zone->privatefile);
+       zone->privatefile = NULL;
        if (zone->stats != NULL)
                isc_stats_detach(&zone->stats);
        if (zone->requeststats != NULL)
@@ -1370,6 +1377,8 @@ dns_zone_setfile2(dns_zone_t *zone, const char *file,
        if (result == ISC_R_SUCCESS) {
                zone->masterformat = format;
                result = default_journal(zone);
+               if (result == ISC_R_SUCCESS)
+                       result = default_private(zone);
        }
        UNLOCK_ZONE(zone);
 
@@ -1383,6 +1392,31 @@ dns_zone_getfile(dns_zone_t *zone) {
        return (zone->masterfile);
 }
 
+static isc_result_t
+default_private(dns_zone_t *zone) {
+       isc_result_t result;
+       char *private;
+
+       REQUIRE(DNS_ZONE_VALID(zone));
+       REQUIRE(LOCKED_ZONE(zone));
+
+       if (zone->masterfile != NULL) {
+               /* Calculate string length including '\0'. */
+               int len = strlen(zone->masterfile) + sizeof(".pvt");
+               private = isc_mem_allocate(zone->mctx, len);
+               if (private == NULL)
+                       return (ISC_R_NOMEMORY);
+               strcpy(private, zone->masterfile);
+               strcat(private, ".pvt");
+       } else {
+               private = NULL;
+       }
+       result = dns_zone_setstring(zone, &zone->privatefile, private);
+       if (private != NULL)
+               isc_mem_free(zone->mctx, private);
+       return (result);
+}
+
 static isc_result_t
 default_journal(dns_zone_t *zone) {
        isc_result_t result;
@@ -1540,6 +1574,7 @@ zone_load(dns_zone_t *zone, unsigned int flags) {
                if (result == ISC_R_SUCCESS) {
                        if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) &&
                            !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE) &&
+                           !isc_time_isepoch( &zone->loadtime) &&
                            isc_time_compare(&filetime, &zone->loadtime) <= 0 &&
                            zone->rpz_zone == dns_rpz_needed()) {
                                dns_zone_log(zone, ISC_LOG_DEBUG(1),
@@ -1779,6 +1814,8 @@ zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
        dns_load_t *load = event->ev_arg;
        isc_result_t result = ISC_R_SUCCESS;
        unsigned int options;
+       const char *masterfile = load->zone->masterfile;
+       dns_masterformat_t masterformat = load->zone->masterformat;
 
        REQUIRE(DNS_LOAD_VALID(load));
 
@@ -1790,7 +1827,17 @@ zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
 
        options = get_master_options(load->zone);
 
-       result = dns_master_loadfileinc3(load->zone->masterfile,
+       LOCK(&load->zone->lock);
+       if (load->zone->db == NULL && load->zone->raw == NULL &&
+           DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
+           load->zone->type == dns_zone_master) {
+               masterfile = load->zone->privatefile;
+               masterformat = dns_masterformat_raw;
+               DNS_ZONE_SETFLAG(load->zone, DNS_ZONEFLG_LOADPRIVATE);
+       }
+       UNLOCK(&load->zone->lock);
+ again:
+       result = dns_master_loadfileinc3(masterfile,
                                         dns_db_origin(load->db),
                                         dns_db_origin(load->db),
                                         load->zone->rdclass, options,
@@ -1798,7 +1845,16 @@ zone_gotreadhandle(isc_task_t *task, isc_event_t *event) {
                                         &load->callbacks, task,
                                         zone_loaddone, load,
                                         &load->zone->lctx, load->zone->mctx,
-                                        load->zone->masterformat);
+                                        masterformat);
+       if (result == ISC_R_FILENOTFOUND &&
+           masterfile == load->zone->privatefile) {
+               LOCK(&load->zone->lock);
+               DNS_ZONE_CLRFLAG(load->zone, DNS_ZONEFLG_LOADPRIVATE);
+               masterfile = load->zone->masterfile;
+               masterformat = load->zone->masterformat;
+               UNLOCK(&load->zone->lock);
+               goto again;
+       }
        if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE &&
            result != DNS_R_SEENINCLUDE)
                goto fail;
@@ -1831,6 +1887,8 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
        isc_result_t result = ISC_R_SUCCESS;
        dns_dbversion_t *version = NULL;
        dns_masterrawheader_t rawdata;
+       dns_masterformat_t masterformat;
+       char *masterfile;
 
        REQUIRE(DNS_ZONE_VALID(zone));
        INSIST(task == zone->task);
@@ -1843,6 +1901,15 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
                goto fail;
 
        LOCK_ZONE(zone);
+       if (zone->type == dns_zone_master && zone->raw == NULL &&
+           DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
+           !dns_zone_isdynamic(zone, ISC_TRUE)) {
+               masterfile = zone->privatefile;
+               masterformat = dns_masterformat_raw;
+       } else {
+               masterfile = zone->masterfile;
+               masterformat = zone->masterformat;
+       }
        ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read);
        dns_db_currentversion(zone->db, &version);
        dns_master_initrawheader(&rawdata);
@@ -1850,9 +1917,8 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {
                get_raw_serial(zone->raw, &rawdata);
        result = dns_master_dumpinc3(zone->mctx, zone->db, version,
                                     &dns_master_style_default,
-                                    zone->masterfile, zone->task, dump_done,
-                                    zone, &zone->dctx, zone->masterformat,
-                                    &rawdata);
+                                    masterfile, zone->task, dump_done,
+                                    zone, &zone->dctx, masterformat, &rawdata);
        dns_db_closeversion(zone->db, &version, ISC_FALSE);
        ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
        UNLOCK_ZONE(zone);
@@ -1933,6 +1999,8 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
                        result = DNS_R_CONTINUE;
        } else {
                dns_rdatacallbacks_t callbacks;
+               char *masterfile = zone->masterfile;
+               dns_masterformat_t masterformat = zone->masterformat;
 
                dns_rdatacallbacks_init(&callbacks);
                callbacks.rawdata = zone_setrawdata;
@@ -1943,12 +2011,28 @@ zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) {
                        zone_idetach(&callbacks.zone);
                        return (result);
                }
-               result = dns_master_loadfile3(zone->masterfile,
+               if (zone->db == NULL && zone->raw == NULL &&
+                   DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
+                   zone->type == dns_zone_master) {
+                       masterfile = zone->privatefile;
+                       masterformat = dns_masterformat_raw;
+                       DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADPRIVATE);
+               }
+ again:
+               result = dns_master_loadfile3(masterfile,
                                              &zone->origin, &zone->origin,
                                              zone->rdclass, options,
                                              zone->sigresigninginterval,
                                              &callbacks, zone->mctx,
-                                             zone->masterformat);
+                                             masterformat);
+               if (result == ISC_R_FILENOTFOUND &&
+                   masterfile == zone->privatefile) {
+                       DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPRIVATE);
+                       masterfile = zone->masterfile;
+                       masterformat = zone->masterformat;
+                       goto again;
+               }
+               
                tresult = dns_db_endload(db, &callbacks.add_private);
                if (result == ISC_R_SUCCESS)
                        result = tresult;
@@ -3537,6 +3621,7 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
        isc_boolean_t hasinclude = DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HASINCLUDE);
        isc_boolean_t nomaster = ISC_FALSE;
        unsigned int options;
+       isc_boolean_t reload = ISC_FALSE;
 
        TIME_NOW(&now);
 
@@ -3623,19 +3708,23 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
                                     "journal rollforward failed: %s",
                                     dns_result_totext(result));
                        goto cleanup;
-
-
                }
-               if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
+               if (result == ISC_R_RANGE && zone->type == dns_zone_master &&
+                   !dns_zone_isdynamic(zone, ISC_TRUE) &&
+                   DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS)) {
+                       dns_zone_log(zone, ISC_LOG_DEBUG(1),
+                                    "updated while shut down");
+                       reload = ISC_TRUE;
+               } else if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
                        dns_zone_log(zone, ISC_LOG_ERROR,
                                     "journal rollforward failed: "
                                     "journal out of sync with zone");
                        goto cleanup;
-               }
-               dns_zone_log(zone, ISC_LOG_DEBUG(1),
-                            "journal rollforward completed "
-                            "successfully: %s",
-                            dns_result_totext(result));
+               } else
+                       dns_zone_log(zone, ISC_LOG_DEBUG(1),
+                                    "journal rollforward completed "
+                                    "successfully: %s",
+                                    dns_result_totext(result));
                if (result == ISC_R_SUCCESS)
                        needdump = ISC_TRUE;
        }
@@ -3690,7 +3779,8 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
                }
        }
 
-       zone->loadtime = loadtime;
+       if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPRIVATE))
+               zone->loadtime = loadtime;
 
        dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded");
 
@@ -3877,6 +3967,15 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
                        zone_send_securedb(zone, db);
        }
 
+       if (zone->type == dns_zone_master &&
+           DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
+           !dns_zone_isdynamic(zone, ISC_TRUE) &&
+           !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADPRIVATE)) {
+               dns_zone_log(zone, ISC_LOG_INFO,
+                            "set 'needdump' for private file");
+               needdump = ISC_TRUE;
+       }
+
        result = ISC_R_SUCCESS;
 
        if (needdump) {
@@ -3934,9 +4033,11 @@ zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime,
                             dns_db_issecure(db) ? " (DNSSEC signed)" : "");
 
        DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPENDING);
+       DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPRIVATE);
        return (result);
 
  cleanup:
+       DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADPRIVATE);
        if (zone->type == dns_zone_slave ||
            zone->type == dns_zone_stub ||
            zone->type == dns_zone_key ||
@@ -8765,8 +8866,17 @@ zone_dump(dns_zone_t *zone, isc_boolean_t compact) {
        ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);
        LOCK_ZONE(zone);
        if (zone->masterfile != NULL) {
-               masterfile = isc_mem_strdup(zone->mctx, zone->masterfile);
-               masterformat = zone->masterformat;
+               if (zone->type == dns_zone_master && zone->raw == NULL &&
+                   DNS_ZONE_OPTION(zone, DNS_ZONEOPT_IXFRFROMDIFFS) &&
+                   !dns_zone_isdynamic(zone, ISC_TRUE)) {
+                       masterfile = isc_mem_strdup(zone->mctx,
+                                                   zone->privatefile);
+                       masterformat = dns_masterformat_raw;
+               } else {
+                       masterfile = isc_mem_strdup(zone->mctx,
+                                                   zone->masterfile);
+                       masterformat = zone->masterformat;
+               }
        }
        UNLOCK_ZONE(zone);
        if (db == NULL) {