1999-08-20 05:26:49 +00:00
|
|
|
/*
|
2011-03-12 04:59:49 +00:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
1999-08-20 05:26:49 +00:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
2021-06-03 08:37:05 +02:00
|
|
|
*
|
1999-08-20 05:26:49 +00:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
1999-08-20 05:26:49 +00:00
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
2005-04-27 04:57:32 +00:00
|
|
|
* information regarding copyright ownership.
|
1999-08-20 05:26:49 +00:00
|
|
|
*/
|
|
|
|
|
2007-08-30 05:08:42 +00:00
|
|
|
#include <errno.h>
|
2018-03-28 14:19:37 +02:00
|
|
|
#include <inttypes.h>
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
1999-08-20 05:26:49 +00:00
|
|
|
#include <stdlib.h>
|
2005-06-08 02:09:18 +00:00
|
|
|
#include <unistd.h>
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2021-06-10 08:14:57 +02:00
|
|
|
#include <isc/dir.h>
|
2000-05-09 23:19:32 +00:00
|
|
|
#include <isc/file.h>
|
1999-08-20 05:26:49 +00:00
|
|
|
#include <isc/mem.h>
|
2023-08-23 10:00:12 +02:00
|
|
|
#include <isc/overflow.h>
|
2021-10-04 17:14:53 +02:00
|
|
|
#include <isc/result.h>
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
#include <isc/serial.h>
|
2000-05-11 16:14:05 +00:00
|
|
|
#include <isc/stdio.h>
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/string.h>
|
2000-04-28 01:12:23 +00:00
|
|
|
#include <isc/util.h>
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <dns/compress.h>
|
1999-10-27 00:32:50 +00:00
|
|
|
#include <dns/db.h>
|
|
|
|
#include <dns/dbiterator.h>
|
2000-12-09 02:17:12 +00:00
|
|
|
#include <dns/diff.h>
|
1999-08-20 05:26:49 +00:00
|
|
|
#include <dns/fixedname.h>
|
1999-10-27 00:32:50 +00:00
|
|
|
#include <dns/journal.h>
|
|
|
|
#include <dns/log.h>
|
1999-08-20 05:26:49 +00:00
|
|
|
#include <dns/rdataset.h>
|
|
|
|
#include <dns/rdatasetiter.h>
|
2001-05-21 23:56:34 +00:00
|
|
|
#include <dns/soa.h>
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2008-04-01 23:47:10 +00:00
|
|
|
/*! \file
|
2009-01-17 14:45:17 +00:00
|
|
|
* \brief Journaling.
|
2005-04-27 04:57:32 +00:00
|
|
|
*
|
|
|
|
* A journal file consists of
|
|
|
|
*
|
|
|
|
* \li A fixed-size header of type journal_rawheader_t.
|
|
|
|
*
|
|
|
|
* \li The index. This is an unordered array of index entries
|
|
|
|
* of type journal_rawpos_t giving the locations
|
|
|
|
* of some arbitrary subset of the journal's addressable
|
|
|
|
* transactions. The index entries are used as hints to
|
|
|
|
* speed up the process of locating a transaction with a given
|
|
|
|
* serial number. Unused index entries have an "offset"
|
|
|
|
* field of zero. The size of the index can vary between
|
|
|
|
* journal files, but does not change during the lifetime
|
|
|
|
* of a file. The size can be zero.
|
|
|
|
*
|
|
|
|
* \li The journal data. This consists of one or more transactions.
|
|
|
|
* Each transaction begins with a transaction header of type
|
|
|
|
* journal_rawxhdr_t. The transaction header is followed by a
|
|
|
|
* sequence of RRs, similar in structure to an IXFR difference
|
|
|
|
* sequence (RFC1995). That is, the pre-transaction SOA,
|
|
|
|
* zero or more other deleted RRs, the post-transaction SOA,
|
|
|
|
* and zero or more other added RRs. Unlike in IXFR, each RR
|
|
|
|
* is prefixed with a 32-bit length.
|
|
|
|
*
|
|
|
|
* The journal data part grows as new transactions are
|
|
|
|
* appended to the file. Only those transactions
|
|
|
|
* whose serial number is current-(2^31-1) to current
|
|
|
|
* are considered "addressable" and may be pointed
|
|
|
|
* to from the header or index. They may be preceded
|
|
|
|
* by old transactions that are no longer addressable,
|
|
|
|
* and they may be followed by transactions that were
|
|
|
|
* appended to the journal but never committed by updating
|
|
|
|
* the "end" position in the header. The latter will
|
|
|
|
* be overwritten when new transactions are added.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
/**************************************************************************/
|
|
|
|
/*
|
|
|
|
* Miscellaneous utilities.
|
|
|
|
*/
|
|
|
|
|
1999-10-27 00:32:50 +00:00
|
|
|
#define JOURNAL_COMMON_LOGARGS \
|
|
|
|
dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_JOURNAL
|
|
|
|
|
|
|
|
#define JOURNAL_DEBUG_LOGARGS(n) JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(n)
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
2000-05-10 03:33:57 +00:00
|
|
|
* It would be non-sensical (or at least obtuse) to use FAIL() with an
|
|
|
|
* ISC_R_SUCCESS code, but the test is there to keep the Solaris compiler
|
|
|
|
* from complaining about "end-of-loop code not reached".
|
|
|
|
*/
|
|
|
|
#define FAIL(code) \
|
|
|
|
do { \
|
|
|
|
result = (code); \
|
|
|
|
if (result != ISC_R_SUCCESS) \
|
|
|
|
goto failure; \
|
|
|
|
} while (0)
|
1999-10-27 00:32:50 +00:00
|
|
|
|
|
|
|
#define CHECK(op) \
|
2008-04-01 23:47:10 +00:00
|
|
|
do { \
|
|
|
|
result = (op); \
|
1999-10-27 00:32:50 +00:00
|
|
|
if (result != ISC_R_SUCCESS) \
|
|
|
|
goto failure; \
|
|
|
|
} while (0)
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2011-12-22 07:32:41 +00:00
|
|
|
#define JOURNAL_SERIALSET 0x01U
|
|
|
|
|
2001-09-15 07:16:39 +00:00
|
|
|
static isc_result_t
|
|
|
|
index_to_disk(dns_journal_t *);
|
|
|
|
|
2021-10-11 13:43:12 +02:00
|
|
|
static uint32_t
|
1999-08-20 05:26:49 +00:00
|
|
|
decode_uint32(unsigned char *p) {
|
2022-02-28 13:43:20 +11:00
|
|
|
return (((uint32_t)p[0] << 24) + ((uint32_t)p[1] << 16) +
|
|
|
|
((uint32_t)p[2] << 8) + ((uint32_t)p[3] << 0));
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
2021-10-11 13:43:12 +02:00
|
|
|
static void
|
2018-03-28 14:19:37 +02:00
|
|
|
encode_uint32(uint32_t val, unsigned char *p) {
|
|
|
|
p[0] = (uint8_t)(val >> 24);
|
|
|
|
p[1] = (uint8_t)(val >> 16);
|
|
|
|
p[2] = (uint8_t)(val >> 8);
|
|
|
|
p[3] = (uint8_t)(val >> 0);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_db_createsoatuple(dns_db_t *db, dns_dbversion_t *ver, isc_mem_t *mctx,
|
|
|
|
dns_diffop_t op, dns_difftuple_t **tp) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_dbnode_t *node;
|
|
|
|
dns_rdataset_t rdataset;
|
2000-10-25 04:26:57 +00:00
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2015-02-27 15:08:38 +11:00
|
|
|
dns_fixedname_t fixed;
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_name_t *zonename;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2018-03-28 14:38:09 +02:00
|
|
|
zonename = dns_fixedname_initname(&fixed);
|
2021-05-21 17:20:44 -07:00
|
|
|
dns_name_copy(dns_db_origin(db), zonename);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
node = NULL;
|
2018-04-17 08:29:14 -07:00
|
|
|
result = dns_db_findnode(db, zonename, false, &node);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-01-11 21:21:07 +00:00
|
|
|
goto nonode;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_rdataset_init(&rdataset);
|
1999-08-31 22:14:06 +00:00
|
|
|
result = dns_db_findrdataset(db, node, ver, dns_rdatatype_soa, 0,
|
2000-05-13 20:21:45 +00:00
|
|
|
(isc_stdtime_t)0, &rdataset, NULL);
|
2008-04-01 23:47:10 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-08-20 05:26:49 +00:00
|
|
|
goto freenode;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
result = dns_rdataset_first(&rdataset);
|
2008-04-01 23:47:10 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-08-20 05:26:49 +00:00
|
|
|
goto freenode;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
dns_rdataset_current(&rdataset, &rdata);
|
2015-02-27 15:08:38 +11:00
|
|
|
dns_rdataset_getownercase(&rdataset, zonename);
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
result = dns_difftuple_create(mctx, op, zonename, rdataset.ttl, &rdata,
|
|
|
|
tp);
|
|
|
|
|
|
|
|
dns_rdataset_disassociate(&rdataset);
|
2000-01-12 00:59:08 +00:00
|
|
|
dns_db_detachnode(db, &node);
|
2011-03-11 06:11:27 +00:00
|
|
|
return (result);
|
2000-01-11 21:21:07 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
freenode:
|
|
|
|
dns_db_detachnode(db, &node);
|
2000-01-11 21:21:07 +00:00
|
|
|
nonode:
|
2022-10-14 16:07:07 +01:00
|
|
|
UNEXPECTED_ERROR("missing SOA");
|
1999-08-20 05:26:49 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2009-01-17 14:45:17 +00:00
|
|
|
/* Journaling */
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
1999-08-20 05:26:49 +00:00
|
|
|
* On-disk representation of a "pointer" to a journal entry.
|
|
|
|
* These are used in the journal header to locate the beginning
|
|
|
|
* and end of the journal, and in the journal index to locate
|
|
|
|
* other transactions.
|
|
|
|
*/
|
|
|
|
typedef struct {
|
2005-04-27 04:57:32 +00:00
|
|
|
unsigned char serial[4]; /*%< SOA serial before update. */
|
1999-08-20 05:26:49 +00:00
|
|
|
/*
|
|
|
|
* XXXRTH Should offset be 8 bytes?
|
2022-12-16 11:47:40 +00:00
|
|
|
* XXXDCL ... probably, since off_t is 8 bytes on many OSs.
|
2000-06-02 23:43:17 +00:00
|
|
|
* XXXAG ... but we will not be able to seek >2G anyway on many
|
|
|
|
* platforms as long as we are using fseek() rather
|
|
|
|
* than lseek().
|
1999-08-20 05:26:49 +00:00
|
|
|
*/
|
2005-04-27 04:57:32 +00:00
|
|
|
unsigned char offset[4]; /*%< Offset from beginning of file. */
|
1999-08-20 05:26:49 +00:00
|
|
|
} journal_rawpos_t;
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
1999-08-20 05:26:49 +00:00
|
|
|
* The header is of a fixed size, with some spare room for future
|
|
|
|
* extensions.
|
|
|
|
*/
|
|
|
|
#define JOURNAL_HEADER_SIZE 64 /* Bytes. */
|
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
typedef enum {
|
|
|
|
XHDR_VERSION1 = 1,
|
|
|
|
XHDR_VERSION2 = 2,
|
|
|
|
} xhdr_version_t;
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
|
|
|
* The on-disk representation of the journal header.
|
|
|
|
* All numbers are stored in big-endian order.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
typedef union {
|
|
|
|
struct {
|
2005-04-27 04:57:32 +00:00
|
|
|
/*% File format version ID. */
|
1999-08-20 05:26:49 +00:00
|
|
|
unsigned char format[16];
|
2005-04-27 04:57:32 +00:00
|
|
|
/*% Position of the first addressable transaction */
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_rawpos_t begin;
|
2005-04-27 04:57:32 +00:00
|
|
|
/*% Position of the next (yet nonexistent) transaction. */
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_rawpos_t end;
|
2005-04-27 04:57:32 +00:00
|
|
|
/*% Number of index entries following the header. */
|
1999-08-20 05:26:49 +00:00
|
|
|
unsigned char index_size[4];
|
2011-11-28 03:14:59 +00:00
|
|
|
/*% Source serial number. */
|
|
|
|
unsigned char sourceserial[4];
|
2011-12-22 07:32:41 +00:00
|
|
|
unsigned char flags;
|
1999-08-20 05:26:49 +00:00
|
|
|
} h;
|
|
|
|
/* Pad the header to a fixed size. */
|
|
|
|
unsigned char pad[JOURNAL_HEADER_SIZE];
|
|
|
|
} journal_rawheader_t;
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
* The on-disk representation of the transaction header, version 2.
|
1999-08-20 05:26:49 +00:00
|
|
|
* There is one of these at the beginning of each transaction.
|
|
|
|
*/
|
|
|
|
typedef struct {
|
2005-04-27 04:57:32 +00:00
|
|
|
unsigned char size[4]; /*%< In bytes, excluding header. */
|
2020-02-21 17:05:04 -08:00
|
|
|
unsigned char count[4]; /*%< Number of records in transaction */
|
2005-04-27 04:57:32 +00:00
|
|
|
unsigned char serial0[4]; /*%< SOA serial before update. */
|
|
|
|
unsigned char serial1[4]; /*%< SOA serial after update. */
|
1999-08-20 05:26:49 +00:00
|
|
|
} journal_rawxhdr_t;
|
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
/*%
|
|
|
|
* Old-style raw transaction header, version 1, used for backward
|
|
|
|
* compatibility mode.
|
|
|
|
*/
|
|
|
|
typedef struct {
|
|
|
|
unsigned char size[4];
|
|
|
|
unsigned char serial0[4];
|
|
|
|
unsigned char serial1[4];
|
|
|
|
} journal_rawxhdr_ver1_t;
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
1999-08-20 05:26:49 +00:00
|
|
|
* The on-disk representation of the RR header.
|
|
|
|
* There is one of these at the beginning of each RR.
|
|
|
|
*/
|
|
|
|
typedef struct {
|
2005-04-27 04:57:32 +00:00
|
|
|
unsigned char size[4]; /*%< In bytes, excluding header. */
|
1999-08-20 05:26:49 +00:00
|
|
|
} journal_rawrrhdr_t;
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
2000-05-25 03:41:12 +00:00
|
|
|
* The in-core representation of the journal header.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
typedef struct {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t serial;
|
2022-12-16 11:47:40 +00:00
|
|
|
off_t offset;
|
1999-08-20 05:26:49 +00:00
|
|
|
} journal_pos_t;
|
|
|
|
|
|
|
|
#define POS_VALID(pos) ((pos).offset != 0)
|
|
|
|
#define POS_INVALIDATE(pos) ((pos).offset = 0, (pos).serial = 0)
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
unsigned char format[16];
|
|
|
|
journal_pos_t begin;
|
|
|
|
journal_pos_t end;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t index_size;
|
|
|
|
uint32_t sourceserial;
|
2018-04-17 08:29:14 -07:00
|
|
|
bool serialset;
|
1999-08-20 05:26:49 +00:00
|
|
|
} journal_header_t;
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
2000-05-25 03:41:12 +00:00
|
|
|
* The in-core representation of the transaction header.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
typedef struct {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t size;
|
2020-02-21 17:05:04 -08:00
|
|
|
uint32_t count;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t serial0;
|
|
|
|
uint32_t serial1;
|
1999-08-20 05:26:49 +00:00
|
|
|
} journal_xhdr_t;
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
2000-05-25 03:41:12 +00:00
|
|
|
* The in-core representation of the RR header.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
typedef struct {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t size;
|
1999-08-20 05:26:49 +00:00
|
|
|
} journal_rrhdr_t;
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*%
|
1999-08-20 05:26:49 +00:00
|
|
|
* Initial contents to store in the header of a newly created
|
|
|
|
* journal file.
|
|
|
|
*
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
* The header starts with the magic string ";BIND LOG V9.2\n"
|
1999-08-20 05:26:49 +00:00
|
|
|
* to identify the file as a BIND 9 journal file. An ASCII
|
|
|
|
* identification string is used rather than a binary magic
|
|
|
|
* number to be consistent with BIND 8 (BIND 8 journal files
|
|
|
|
* are ASCII text files).
|
|
|
|
*/
|
2000-08-01 01:33:37 +00:00
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
static journal_header_t journal_header_ver1 = {
|
2011-12-22 07:32:41 +00:00
|
|
|
";BIND LOG V9\n", { 0, 0 }, { 0, 0 }, 0, 0, 0
|
|
|
|
};
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
static journal_header_t initial_journal_header = {
|
|
|
|
";BIND LOG V9.2\n", { 0, 0 }, { 0, 0 }, 0, 0, 0
|
|
|
|
};
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
#define JOURNAL_EMPTY(h) ((h)->begin.offset == (h)->end.offset)
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
JOURNAL_STATE_INVALID,
|
|
|
|
JOURNAL_STATE_READ,
|
|
|
|
JOURNAL_STATE_WRITE,
|
2011-08-30 05:16:15 +00:00
|
|
|
JOURNAL_STATE_TRANSACTION,
|
2011-11-28 03:14:59 +00:00
|
|
|
JOURNAL_STATE_INLINE
|
1999-08-20 05:26:49 +00:00
|
|
|
} journal_state_t;
|
|
|
|
|
|
|
|
struct dns_journal {
|
2005-04-27 04:57:32 +00:00
|
|
|
unsigned int magic; /*%< JOUR */
|
|
|
|
isc_mem_t *mctx; /*%< Memory context */
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_state_t state;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
xhdr_version_t xhdr_version; /*%< Expected transaction header version */
|
|
|
|
bool header_ver1; /*%< Transaction header compatibility
|
|
|
|
* mode is allowed */
|
|
|
|
bool recovered; /*%< A recoverable error was found
|
|
|
|
* while reading the journal */
|
|
|
|
char *filename; /*%< Journal file name */
|
|
|
|
FILE *fp; /*%< File handle */
|
2022-12-16 11:47:40 +00:00
|
|
|
off_t offset; /*%< Current file offset */
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
journal_xhdr_t curxhdr; /*%< Current transaction header */
|
|
|
|
journal_header_t header; /*%< In-core journal header */
|
|
|
|
unsigned char *rawindex; /*%< In-core buffer for journal index
|
|
|
|
* in on-disk format */
|
|
|
|
journal_pos_t *index; /*%< In-core journal index */
|
2005-04-27 04:57:32 +00:00
|
|
|
|
|
|
|
/*% Current transaction state (when writing). */
|
1999-08-20 05:26:49 +00:00
|
|
|
struct {
|
2005-04-27 04:57:32 +00:00
|
|
|
unsigned int n_soa; /*%< Number of SOAs seen */
|
2020-02-21 17:05:04 -08:00
|
|
|
unsigned int n_rr; /*%< Number of RRs to write */
|
2005-04-27 04:57:32 +00:00
|
|
|
journal_pos_t pos[2]; /*%< Begin/end position */
|
1999-08-20 05:26:49 +00:00
|
|
|
} x;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*% Iteration state (when reading). */
|
1999-08-20 05:26:49 +00:00
|
|
|
struct {
|
|
|
|
/* These define the part of the journal we iterate over. */
|
2005-04-27 04:57:32 +00:00
|
|
|
journal_pos_t bpos; /*%< Position before first, */
|
2021-03-03 14:59:30 -08:00
|
|
|
journal_pos_t cpos; /*%< before current, */
|
2005-04-27 04:57:32 +00:00
|
|
|
journal_pos_t epos; /*%< and after last transaction */
|
1999-08-20 05:26:49 +00:00
|
|
|
/* The rest is iterator state. */
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
uint32_t current_serial; /*%< Current SOA serial */
|
2005-04-27 04:57:32 +00:00
|
|
|
isc_buffer_t source; /*%< Data from disk */
|
2020-02-21 17:05:04 -08:00
|
|
|
isc_buffer_t target; /*%< Data from _fromwire check */
|
2005-04-27 04:57:32 +00:00
|
|
|
dns_decompress_t dctx; /*%< Dummy decompression ctx */
|
|
|
|
dns_name_t name; /*%< Current domain name */
|
|
|
|
dns_rdata_t rdata; /*%< Current rdata */
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t ttl; /*%< Current TTL */
|
2005-04-27 04:57:32 +00:00
|
|
|
unsigned int xsize; /*%< Size of transaction data */
|
|
|
|
unsigned int xpos; /*%< Current position in it */
|
|
|
|
isc_result_t result; /*%< Result of last call */
|
1999-08-20 05:26:49 +00:00
|
|
|
} it;
|
|
|
|
};
|
|
|
|
|
2001-06-04 19:33:39 +00:00
|
|
|
#define DNS_JOURNAL_MAGIC ISC_MAGIC('J', 'O', 'U', 'R')
|
2000-05-08 14:38:29 +00:00
|
|
|
#define DNS_JOURNAL_VALID(t) ISC_MAGIC_VALID(t, DNS_JOURNAL_MAGIC)
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
journal_pos_decode(journal_rawpos_t *raw, journal_pos_t *cooked) {
|
1999-08-20 05:26:49 +00:00
|
|
|
cooked->serial = decode_uint32(raw->serial);
|
|
|
|
cooked->offset = decode_uint32(raw->offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
journal_pos_encode(journal_rawpos_t *raw, journal_pos_t *cooked) {
|
1999-08-20 05:26:49 +00:00
|
|
|
encode_uint32(cooked->serial, raw->serial);
|
|
|
|
encode_uint32(cooked->offset, raw->offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
journal_header_decode(journal_rawheader_t *raw, journal_header_t *cooked) {
|
1999-08-20 05:26:49 +00:00
|
|
|
INSIST(sizeof(cooked->format) == sizeof(raw->h.format));
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(cooked->format, raw->h.format, sizeof(cooked->format));
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_pos_decode(&raw->h.begin, &cooked->begin);
|
|
|
|
journal_pos_decode(&raw->h.end, &cooked->end);
|
|
|
|
cooked->index_size = decode_uint32(raw->h.index_size);
|
2011-11-28 03:14:59 +00:00
|
|
|
cooked->sourceserial = decode_uint32(raw->h.sourceserial);
|
2018-10-11 11:57:57 +02:00
|
|
|
cooked->serialset = ((raw->h.flags & JOURNAL_SERIALSET) != 0);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2000-05-08 14:38:29 +00:00
|
|
|
journal_header_encode(journal_header_t *cooked, journal_rawheader_t *raw) {
|
2011-12-22 07:32:41 +00:00
|
|
|
unsigned char flags = 0;
|
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
INSIST(sizeof(cooked->format) == sizeof(raw->h.format));
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
memset(raw->pad, 0, sizeof(raw->pad));
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(raw->h.format, cooked->format, sizeof(raw->h.format));
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_pos_encode(&raw->h.begin, &cooked->begin);
|
|
|
|
journal_pos_encode(&raw->h.end, &cooked->end);
|
|
|
|
encode_uint32(cooked->index_size, raw->h.index_size);
|
2011-11-28 03:14:59 +00:00
|
|
|
encode_uint32(cooked->sourceserial, raw->h.sourceserial);
|
2018-10-11 11:57:57 +02:00
|
|
|
if (cooked->serialset) {
|
2011-12-22 07:32:41 +00:00
|
|
|
flags |= JOURNAL_SERIALSET;
|
2018-10-11 11:57:57 +02:00
|
|
|
}
|
2011-12-22 07:32:41 +00:00
|
|
|
raw->h.flags = flags;
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
2000-05-25 03:41:12 +00:00
|
|
|
/*
|
|
|
|
* Journal file I/O subroutines, with error checking and reporting.
|
|
|
|
*/
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
2018-03-28 14:19:37 +02:00
|
|
|
journal_seek(dns_journal_t *j, uint32_t offset) {
|
2000-05-09 23:19:32 +00:00
|
|
|
isc_result_t result;
|
2013-06-17 09:09:43 -07:00
|
|
|
|
|
|
|
result = isc_stdio_seek(j->fp, (off_t)offset, SEEK_SET);
|
2000-05-09 23:19:32 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2000-05-09 23:19:32 +00:00
|
|
|
"%s: seek: %s", j->filename,
|
|
|
|
isc_result_totext(result));
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
j->offset = offset;
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_read(dns_journal_t *j, void *mem, size_t nbytes) {
|
2000-05-09 23:19:32 +00:00
|
|
|
isc_result_t result;
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2000-05-11 16:14:05 +00:00
|
|
|
result = isc_stdio_read(mem, 1, nbytes, j->fp, NULL);
|
2000-05-09 23:19:32 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
if (result == ISC_R_EOF) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMORE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2000-05-09 23:19:32 +00:00
|
|
|
"%s: read: %s", j->filename,
|
|
|
|
isc_result_totext(result));
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2022-12-16 11:47:40 +00:00
|
|
|
j->offset += (off_t)nbytes;
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_write(dns_journal_t *j, void *mem, size_t nbytes) {
|
2000-05-09 23:19:32 +00:00
|
|
|
isc_result_t result;
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2000-05-11 16:14:05 +00:00
|
|
|
result = isc_stdio_write(mem, 1, nbytes, j->fp, NULL);
|
2000-05-09 23:19:32 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2000-05-09 23:19:32 +00:00
|
|
|
"%s: write: %s", j->filename,
|
|
|
|
isc_result_totext(result));
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2022-12-16 11:47:40 +00:00
|
|
|
j->offset += (off_t)nbytes;
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_fsync(dns_journal_t *j) {
|
2000-05-09 23:19:32 +00:00
|
|
|
isc_result_t result;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
2000-05-11 16:14:05 +00:00
|
|
|
result = isc_stdio_flush(j->fp);
|
2000-05-09 23:19:32 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2000-05-09 23:19:32 +00:00
|
|
|
"%s: flush: %s", j->filename,
|
|
|
|
isc_result_totext(result));
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2000-05-11 16:14:05 +00:00
|
|
|
result = isc_stdio_sync(j->fp);
|
2000-05-09 23:19:32 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2000-05-09 23:19:32 +00:00
|
|
|
"%s: fsync: %s", j->filename,
|
|
|
|
isc_result_totext(result));
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Read/write a transaction header at the current file position.
|
|
|
|
*/
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_read_xhdr(dns_journal_t *j, journal_xhdr_t *xhdr) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
2021-03-03 14:59:30 -08:00
|
|
|
j->it.cpos.offset = j->offset;
|
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
switch (j->xhdr_version) {
|
|
|
|
case XHDR_VERSION1: {
|
|
|
|
journal_rawxhdr_ver1_t raw;
|
|
|
|
result = journal_read(j, &raw, sizeof(raw));
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
xhdr->size = decode_uint32(raw.size);
|
|
|
|
xhdr->count = 0;
|
|
|
|
xhdr->serial0 = decode_uint32(raw.serial0);
|
|
|
|
xhdr->serial1 = decode_uint32(raw.serial1);
|
|
|
|
j->curxhdr = *xhdr;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
case XHDR_VERSION2: {
|
|
|
|
journal_rawxhdr_t raw;
|
|
|
|
result = journal_read(j, &raw, sizeof(raw));
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
xhdr->size = decode_uint32(raw.size);
|
|
|
|
xhdr->count = decode_uint32(raw.count);
|
|
|
|
xhdr->serial0 = decode_uint32(raw.serial0);
|
|
|
|
xhdr->serial1 = decode_uint32(raw.serial1);
|
|
|
|
j->curxhdr = *xhdr;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return (ISC_R_NOTIMPLEMENTED);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
2020-02-21 17:05:04 -08:00
|
|
|
journal_write_xhdr(dns_journal_t *j, uint32_t size, uint32_t count,
|
|
|
|
uint32_t serial0, uint32_t serial1) {
|
2021-03-03 17:07:15 +11:00
|
|
|
if (j->header_ver1) {
|
|
|
|
journal_rawxhdr_ver1_t raw;
|
|
|
|
encode_uint32(size, raw.size);
|
|
|
|
encode_uint32(serial0, raw.serial0);
|
|
|
|
encode_uint32(serial1, raw.serial1);
|
|
|
|
return (journal_write(j, &raw, sizeof(raw)));
|
|
|
|
} else {
|
|
|
|
journal_rawxhdr_t raw;
|
|
|
|
encode_uint32(size, raw.size);
|
|
|
|
encode_uint32(count, raw.count);
|
|
|
|
encode_uint32(serial0, raw.serial0);
|
|
|
|
encode_uint32(serial1, raw.serial1);
|
|
|
|
return (journal_write(j, &raw, sizeof(raw)));
|
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Read an RR header at the current file position.
|
|
|
|
*/
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_read_rrhdr(dns_journal_t *j, journal_rrhdr_t *rrhdr) {
|
|
|
|
journal_rawrrhdr_t raw;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
result = journal_read(j, &raw, sizeof(raw));
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-08-20 05:26:49 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
rrhdr->size = decode_uint32(raw.size);
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
2021-03-03 17:07:15 +11:00
|
|
|
journal_file_create(isc_mem_t *mctx, bool downgrade, const char *filename) {
|
2000-05-09 23:19:32 +00:00
|
|
|
FILE *fp = NULL;
|
|
|
|
isc_result_t result;
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_header_t header;
|
|
|
|
journal_rawheader_t rawheader;
|
|
|
|
int index_size = 56; /* XXX configurable */
|
|
|
|
int size;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
void *mem = NULL; /* Memory for temporary index image. */
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
INSIST(sizeof(journal_rawheader_t) == JOURNAL_HEADER_SIZE);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2001-10-15 04:47:55 +00:00
|
|
|
result = isc_stdio_open(filename, "wb", &fp);
|
2000-05-09 23:19:32 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2000-05-09 23:19:32 +00:00
|
|
|
"%s: create: %s", filename,
|
|
|
|
isc_result_totext(result));
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
2021-03-03 17:07:15 +11:00
|
|
|
if (downgrade) {
|
|
|
|
header = journal_header_ver1;
|
|
|
|
} else {
|
|
|
|
header = initial_journal_header;
|
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
header.index_size = index_size;
|
|
|
|
journal_header_encode(&header, &rawheader);
|
|
|
|
|
|
|
|
size = sizeof(journal_rawheader_t) +
|
2023-08-23 10:00:12 +02:00
|
|
|
ISC_CHECKED_MUL(index_size, sizeof(journal_rawpos_t));
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2023-08-23 11:05:14 +02:00
|
|
|
mem = isc_mem_cget(mctx, 1, size);
|
2014-01-08 16:27:10 -08:00
|
|
|
memmove(mem, &rawheader, sizeof(rawheader));
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2000-05-11 16:14:05 +00:00
|
|
|
result = isc_stdio_write(mem, 1, (size_t)size, fp, NULL);
|
2000-05-09 23:19:32 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
1999-08-20 05:26:49 +00:00
|
|
|
"%s: write: %s", filename,
|
2000-05-09 23:19:32 +00:00
|
|
|
isc_result_totext(result));
|
2000-05-11 16:14:05 +00:00
|
|
|
(void)isc_stdio_close(fp);
|
2000-05-09 23:19:32 +00:00
|
|
|
(void)isc_file_remove(filename);
|
1999-08-20 05:26:49 +00:00
|
|
|
isc_mem_put(mctx, mem, size);
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
isc_mem_put(mctx, mem, size);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-05-11 16:14:05 +00:00
|
|
|
result = isc_stdio_close(fp);
|
2000-05-09 23:19:32 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-05-24 05:10:00 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
1999-08-20 05:26:49 +00:00
|
|
|
"%s: close: %s", filename,
|
2000-05-09 23:19:32 +00:00
|
|
|
isc_result_totext(result));
|
|
|
|
(void)isc_file_remove(filename);
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2001-08-30 05:04:18 +00:00
|
|
|
static isc_result_t
|
2018-04-17 08:29:14 -07:00
|
|
|
journal_open(isc_mem_t *mctx, const char *filename, bool writable, bool create,
|
2021-03-03 17:07:15 +11:00
|
|
|
bool downgrade, dns_journal_t **journalp) {
|
2000-05-09 23:19:32 +00:00
|
|
|
FILE *fp = NULL;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_rawheader_t rawheader;
|
|
|
|
dns_journal_t *j;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
REQUIRE(journalp != NULL && *journalp == NULL);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
j = isc_mem_get(mctx, sizeof(*j));
|
|
|
|
*j = (dns_journal_t){ .state = JOURNAL_STATE_INVALID,
|
|
|
|
.filename = isc_mem_strdup(mctx, filename),
|
|
|
|
.xhdr_version = XHDR_VERSION2 };
|
2013-02-20 21:39:05 -08:00
|
|
|
isc_mem_attach(mctx, &j->mctx);
|
2013-09-09 22:12:47 -07:00
|
|
|
|
2015-02-27 10:55:55 +11:00
|
|
|
result = isc_stdio_open(j->filename, writable ? "rb+" : "rb", &fp);
|
2000-05-09 23:19:32 +00:00
|
|
|
if (result == ISC_R_FILENOTFOUND) {
|
2001-08-30 05:04:18 +00:00
|
|
|
if (create) {
|
2009-08-25 07:41:28 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(1),
|
1999-10-27 00:32:50 +00:00
|
|
|
"journal file %s does not exist, "
|
2009-08-25 07:41:28 +00:00
|
|
|
"creating it",
|
|
|
|
j->filename);
|
2021-03-03 17:07:15 +11:00
|
|
|
CHECK(journal_file_create(mctx, downgrade, filename));
|
2000-05-11 16:14:05 +00:00
|
|
|
/*
|
|
|
|
* Retry.
|
|
|
|
*/
|
|
|
|
result = isc_stdio_open(j->filename, "rb+", &fp);
|
1999-08-20 05:26:49 +00:00
|
|
|
} else {
|
|
|
|
FAIL(ISC_R_NOTFOUND);
|
|
|
|
}
|
|
|
|
}
|
2000-05-09 23:19:32 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"%s: open: %s", j->filename,
|
2000-05-09 23:19:32 +00:00
|
|
|
isc_result_totext(result));
|
2000-04-06 22:03:35 +00:00
|
|
|
FAIL(ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
j->fp = fp;
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Set magic early so that seek/read can succeed.
|
|
|
|
*/
|
1999-09-21 22:45:24 +00:00
|
|
|
j->magic = DNS_JOURNAL_MAGIC;
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
CHECK(journal_seek(j, 0));
|
|
|
|
CHECK(journal_read(j, &rawheader, sizeof(rawheader)));
|
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
if (memcmp(rawheader.h.format, journal_header_ver1.format,
|
|
|
|
sizeof(journal_header_ver1.format)) == 0)
|
1999-08-20 05:26:49 +00:00
|
|
|
{
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
/*
|
|
|
|
* The file header says it's the old format, but it
|
|
|
|
* still might have the new xhdr format because we
|
|
|
|
* forgot to change the format string when we introduced
|
|
|
|
* the new xhdr. When we first try to read it, we assume
|
|
|
|
* it uses the new xhdr format. If that fails, we'll be
|
|
|
|
* called a second time with compat set to true, in which
|
|
|
|
* case we can lower xhdr_version to 1 if we find a
|
|
|
|
* corrupt transaction.
|
|
|
|
*/
|
|
|
|
j->header_ver1 = true;
|
|
|
|
} else if (memcmp(rawheader.h.format, initial_journal_header.format,
|
|
|
|
sizeof(initial_journal_header.format)) == 0)
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* File header says this is format version 2; all
|
|
|
|
* transactions have to match.
|
|
|
|
*/
|
|
|
|
j->header_ver1 = false;
|
|
|
|
} else {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
1999-12-14 01:26:03 +00:00
|
|
|
"%s: journal format not recognized", j->filename);
|
2000-04-06 22:03:35 +00:00
|
|
|
FAIL(ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
journal_header_decode(&rawheader, &j->header);
|
|
|
|
|
|
|
|
/*
|
2000-06-02 23:43:17 +00:00
|
|
|
* If there is an index, read the raw index into a dynamically
|
|
|
|
* allocated buffer and then convert it into a cooked index.
|
1999-08-20 05:26:49 +00:00
|
|
|
*/
|
|
|
|
if (j->header.index_size != 0) {
|
|
|
|
unsigned int i;
|
2000-06-02 23:43:17 +00:00
|
|
|
unsigned int rawbytes;
|
|
|
|
unsigned char *p;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2023-08-23 10:00:12 +02:00
|
|
|
rawbytes = ISC_CHECKED_MUL(j->header.index_size,
|
|
|
|
sizeof(journal_rawpos_t));
|
2000-06-02 23:43:17 +00:00
|
|
|
j->rawindex = isc_mem_get(mctx, rawbytes);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-06-02 23:43:17 +00:00
|
|
|
CHECK(journal_read(j, j->rawindex, rawbytes));
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2023-08-23 08:56:31 +02:00
|
|
|
j->index = isc_mem_cget(mctx, j->header.index_size,
|
|
|
|
sizeof(journal_pos_t));
|
2000-06-02 23:43:17 +00:00
|
|
|
|
|
|
|
p = j->rawindex;
|
1999-08-20 05:26:49 +00:00
|
|
|
for (i = 0; i < j->header.index_size; i++) {
|
2000-06-02 23:43:17 +00:00
|
|
|
j->index[i].serial = decode_uint32(p);
|
|
|
|
p += 4;
|
|
|
|
j->index[i].offset = decode_uint32(p);
|
|
|
|
p += 4;
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2000-06-02 23:43:17 +00:00
|
|
|
INSIST(p == j->rawindex + rawbytes);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
j->offset = -1; /* Invalid, must seek explicitly. */
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Initialize the iterator.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_name_init(&j->it.name, NULL);
|
|
|
|
dns_rdata_init(&j->it.rdata);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
/*
|
2009-01-17 14:45:17 +00:00
|
|
|
* Set up empty initial buffers for unchecked and checked
|
1999-08-20 05:26:49 +00:00
|
|
|
* wire format RR data. They will be reallocated
|
|
|
|
* later.
|
|
|
|
*/
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&j->it.source, NULL, 0);
|
|
|
|
isc_buffer_init(&j->it.target, NULL, 0);
|
2022-05-05 16:36:52 +01:00
|
|
|
j->it.dctx = DNS_DECOMPRESS_NEVER;
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2015-02-27 10:55:55 +11:00
|
|
|
j->state = writable ? JOURNAL_STATE_WRITE : JOURNAL_STATE_READ;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
*journalp = j;
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
failure:
|
|
|
|
j->magic = 0;
|
2015-11-19 11:20:22 +05:30
|
|
|
if (j->rawindex != NULL) {
|
2023-08-23 08:56:31 +02:00
|
|
|
isc_mem_cput(j->mctx, j->rawindex, j->header.index_size,
|
|
|
|
sizeof(journal_rawpos_t));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2015-11-19 11:20:22 +05:30
|
|
|
if (j->index != NULL) {
|
2023-08-23 08:56:31 +02:00
|
|
|
isc_mem_cput(j->mctx, j->index, j->header.index_size,
|
|
|
|
sizeof(journal_pos_t));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2021-03-08 07:06:57 +11:00
|
|
|
isc_mem_free(j->mctx, j->filename);
|
1999-08-20 05:26:49 +00:00
|
|
|
if (j->fp != NULL) {
|
2000-05-11 16:14:05 +00:00
|
|
|
(void)isc_stdio_close(j->fp);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2013-02-20 21:39:05 -08:00
|
|
|
isc_mem_putanddetach(&j->mctx, j, sizeof(*j));
|
1999-08-20 05:26:49 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2001-08-30 05:04:18 +00:00
|
|
|
isc_result_t
|
2011-08-30 05:16:15 +00:00
|
|
|
dns_journal_open(isc_mem_t *mctx, const char *filename, unsigned int mode,
|
2011-12-22 07:32:41 +00:00
|
|
|
dns_journal_t **journalp) {
|
2007-08-30 05:08:42 +00:00
|
|
|
isc_result_t result;
|
2013-12-04 12:47:23 +11:00
|
|
|
size_t namelen;
|
2007-08-30 05:08:42 +00:00
|
|
|
char backup[1024];
|
2018-04-17 08:29:14 -07:00
|
|
|
bool writable, create;
|
2008-04-01 23:47:10 +00:00
|
|
|
|
2018-10-11 11:57:57 +02:00
|
|
|
create = ((mode & DNS_JOURNAL_CREATE) != 0);
|
|
|
|
writable = ((mode & (DNS_JOURNAL_WRITE | DNS_JOURNAL_CREATE)) != 0);
|
2011-08-30 05:16:15 +00:00
|
|
|
|
2021-03-03 17:07:15 +11:00
|
|
|
result = journal_open(mctx, filename, writable, create, false,
|
|
|
|
journalp);
|
2007-08-30 05:08:42 +00:00
|
|
|
if (result == ISC_R_NOTFOUND) {
|
2007-09-02 23:02:53 +00:00
|
|
|
namelen = strlen(filename);
|
2013-12-06 17:38:25 +11:00
|
|
|
if (namelen > 4U && strcmp(filename + namelen - 4, ".jnl") == 0)
|
|
|
|
{
|
2007-09-02 23:02:53 +00:00
|
|
|
namelen -= 4;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-08-30 05:08:42 +00:00
|
|
|
|
2018-03-21 16:38:29 +00:00
|
|
|
result = snprintf(backup, sizeof(backup), "%.*s.jbk",
|
|
|
|
(int)namelen, filename);
|
|
|
|
if (result >= sizeof(backup)) {
|
|
|
|
return (ISC_R_NOSPACE);
|
|
|
|
}
|
2021-03-03 17:07:15 +11:00
|
|
|
result = journal_open(mctx, backup, writable, writable, false,
|
2015-02-27 10:55:55 +11:00
|
|
|
journalp);
|
2007-08-30 05:08:42 +00:00
|
|
|
}
|
|
|
|
return (result);
|
2001-08-30 05:04:18 +00:00
|
|
|
}
|
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
/*
|
|
|
|
* A comparison function defining the sorting order for
|
|
|
|
* entries in the IXFR-style journal file.
|
|
|
|
*
|
|
|
|
* The IXFR format requires that deletions are sorted before
|
|
|
|
* additions, and within either one, SOA records are sorted
|
|
|
|
* before others.
|
|
|
|
*
|
|
|
|
* Also sort the non-SOA records by type as a courtesy to the
|
|
|
|
* server receiving the IXFR - it may help reduce the amount of
|
|
|
|
* rdataset merging it has to do.
|
|
|
|
*/
|
|
|
|
static int
|
2000-05-08 14:38:29 +00:00
|
|
|
ixfr_order(const void *av, const void *bv) {
|
2001-01-24 07:12:56 +00:00
|
|
|
dns_difftuple_t const *const *ap = av;
|
|
|
|
dns_difftuple_t const *const *bp = bv;
|
|
|
|
dns_difftuple_t const *a = *ap;
|
|
|
|
dns_difftuple_t const *b = *bp;
|
1999-08-20 05:26:49 +00:00
|
|
|
int r;
|
2008-04-01 01:37:25 +00:00
|
|
|
int bop = 0, aop = 0;
|
|
|
|
|
|
|
|
switch (a->op) {
|
|
|
|
case DNS_DIFFOP_DEL:
|
|
|
|
case DNS_DIFFOP_DELRESIGN:
|
|
|
|
aop = 1;
|
|
|
|
break;
|
|
|
|
case DNS_DIFFOP_ADD:
|
|
|
|
case DNS_DIFFOP_ADDRESIGN:
|
|
|
|
aop = 0;
|
|
|
|
break;
|
|
|
|
default:
|
2021-10-11 12:50:17 +02:00
|
|
|
UNREACHABLE();
|
2008-04-01 01:37:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (b->op) {
|
|
|
|
case DNS_DIFFOP_DEL:
|
|
|
|
case DNS_DIFFOP_DELRESIGN:
|
|
|
|
bop = 1;
|
|
|
|
break;
|
|
|
|
case DNS_DIFFOP_ADD:
|
|
|
|
case DNS_DIFFOP_ADDRESIGN:
|
|
|
|
bop = 0;
|
|
|
|
break;
|
|
|
|
default:
|
2021-10-11 12:50:17 +02:00
|
|
|
UNREACHABLE();
|
2008-04-01 01:37:25 +00:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2008-04-01 01:37:25 +00:00
|
|
|
r = bop - aop;
|
1999-08-20 05:26:49 +00:00
|
|
|
if (r != 0) {
|
|
|
|
return (r);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
r = (b->rdata.type == dns_rdatatype_soa) -
|
|
|
|
(a->rdata.type == dns_rdatatype_soa);
|
|
|
|
if (r != 0) {
|
|
|
|
return (r);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
r = (a->rdata.type - b->rdata.type);
|
|
|
|
return (r);
|
|
|
|
}
|
|
|
|
|
2021-05-13 15:44:02 +10:00
|
|
|
static isc_result_t
|
|
|
|
maybe_fixup_xhdr(dns_journal_t *j, journal_xhdr_t *xhdr, uint32_t serial,
|
2022-12-16 11:47:40 +00:00
|
|
|
off_t offset) {
|
2021-05-13 15:44:02 +10:00
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle mixture of version 1 and version 2
|
|
|
|
* transaction headers in a version 1 journal.
|
|
|
|
*/
|
|
|
|
if ((xhdr->serial0 != serial ||
|
2022-11-02 19:33:14 +01:00
|
|
|
isc_serial_le(xhdr->serial1, xhdr->serial0)))
|
|
|
|
{
|
2021-05-13 15:44:02 +10:00
|
|
|
if (j->xhdr_version == XHDR_VERSION1 && xhdr->serial1 == serial)
|
|
|
|
{
|
|
|
|
isc_log_write(
|
|
|
|
JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(3),
|
|
|
|
"%s: XHDR_VERSION1 -> XHDR_VERSION2 at %u",
|
|
|
|
j->filename, serial);
|
|
|
|
j->xhdr_version = XHDR_VERSION2;
|
|
|
|
CHECK(journal_seek(j, offset));
|
|
|
|
CHECK(journal_read_xhdr(j, xhdr));
|
|
|
|
j->recovered = true;
|
|
|
|
} else if (j->xhdr_version == XHDR_VERSION2 &&
|
2022-11-02 19:33:14 +01:00
|
|
|
xhdr->count == serial)
|
|
|
|
{
|
2021-05-13 15:44:02 +10:00
|
|
|
isc_log_write(
|
|
|
|
JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(3),
|
|
|
|
"%s: XHDR_VERSION2 -> XHDR_VERSION1 at %u",
|
|
|
|
j->filename, serial);
|
|
|
|
j->xhdr_version = XHDR_VERSION1;
|
|
|
|
CHECK(journal_seek(j, offset));
|
|
|
|
CHECK(journal_read_xhdr(j, xhdr));
|
|
|
|
j->recovered = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Handle <size, serial0, serial1, 0> transaction header.
|
|
|
|
*/
|
|
|
|
if (j->xhdr_version == XHDR_VERSION1) {
|
|
|
|
uint32_t value;
|
|
|
|
|
|
|
|
CHECK(journal_read(j, &value, sizeof(value)));
|
|
|
|
if (value != 0L) {
|
|
|
|
CHECK(journal_seek(j, offset + 12));
|
|
|
|
} else {
|
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(3),
|
|
|
|
"%s: XHDR_VERSION1 count zero at %u",
|
|
|
|
j->filename, serial);
|
|
|
|
j->xhdr_version = XHDR_VERSION2;
|
|
|
|
j->recovered = true;
|
|
|
|
}
|
|
|
|
} else if (j->xhdr_version == XHDR_VERSION2 && xhdr->count == serial &&
|
|
|
|
xhdr->serial1 == 0U &&
|
|
|
|
isc_serial_gt(xhdr->serial0, xhdr->count))
|
|
|
|
{
|
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_DEBUG(3),
|
|
|
|
"%s: XHDR_VERSION2 count zero at %u", j->filename,
|
|
|
|
serial);
|
|
|
|
xhdr->serial1 = xhdr->serial0;
|
|
|
|
xhdr->serial0 = xhdr->count;
|
|
|
|
xhdr->count = 0;
|
|
|
|
j->recovered = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
failure:
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
/*
|
|
|
|
* Advance '*pos' to the next journal transaction.
|
|
|
|
*
|
|
|
|
* Requires:
|
|
|
|
* *pos refers to a valid journal transaction.
|
|
|
|
*
|
|
|
|
* Ensures:
|
2000-04-06 22:03:35 +00:00
|
|
|
* When ISC_R_SUCCESS is returned,
|
1999-08-20 05:26:49 +00:00
|
|
|
* *pos refers to the next journal transaction.
|
|
|
|
*
|
|
|
|
* Returns one of:
|
|
|
|
*
|
2000-04-06 22:03:35 +00:00
|
|
|
* ISC_R_SUCCESS
|
|
|
|
* ISC_R_NOMORE *pos pointed at the last transaction
|
1999-08-20 05:26:49 +00:00
|
|
|
* Other results due to file errors are possible.
|
|
|
|
*/
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
2021-05-13 15:44:02 +10:00
|
|
|
journal_next(dns_journal_t *j, journal_pos_t *pos) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_xhdr_t xhdr;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
size_t hdrsize;
|
|
|
|
|
1999-09-21 22:45:24 +00:00
|
|
|
REQUIRE(DNS_JOURNAL_VALID(j));
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
result = journal_seek(j, pos->offset);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-08-20 05:26:49 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2001-08-30 05:04:18 +00:00
|
|
|
if (pos->serial == j->header.end.serial) {
|
|
|
|
return (ISC_R_NOMORE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
/*
|
|
|
|
* Read the header of the current transaction.
|
2000-04-06 22:03:35 +00:00
|
|
|
* This will return ISC_R_NOMORE if we are at EOF.
|
1999-08-20 05:26:49 +00:00
|
|
|
*/
|
|
|
|
result = journal_read_xhdr(j, &xhdr);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-08-20 05:26:49 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2021-05-13 15:44:02 +10:00
|
|
|
if (j->header_ver1) {
|
|
|
|
CHECK(maybe_fixup_xhdr(j, &xhdr, pos->serial, pos->offset));
|
|
|
|
}
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Check serial number consistency.
|
|
|
|
*/
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
if (xhdr.serial0 != pos->serial ||
|
2022-11-02 19:33:14 +01:00
|
|
|
isc_serial_le(xhdr.serial1, xhdr.serial0))
|
|
|
|
{
|
2021-05-13 15:44:02 +10:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"%s: journal file corrupt: "
|
|
|
|
"expected serial %u, got %u",
|
|
|
|
j->filename, pos->serial, xhdr.serial0);
|
|
|
|
return (ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Check for offset wraparound.
|
|
|
|
*/
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
hdrsize = (j->xhdr_version == XHDR_VERSION2)
|
|
|
|
? sizeof(journal_rawxhdr_t)
|
|
|
|
: sizeof(journal_rawxhdr_ver1_t);
|
|
|
|
|
2022-12-16 11:47:40 +00:00
|
|
|
if ((off_t)(pos->offset + hdrsize + xhdr.size) < pos->offset) {
|
2000-05-24 05:10:00 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2000-05-25 03:41:12 +00:00
|
|
|
"%s: offset too large", j->filename);
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
pos->offset += hdrsize + xhdr.size;
|
1999-08-20 05:26:49 +00:00
|
|
|
pos->serial = xhdr.serial1;
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
2021-03-31 15:03:33 +11:00
|
|
|
|
|
|
|
failure:
|
|
|
|
return (result);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the index of the journal 'j' contains an entry "better"
|
|
|
|
* than '*best_guess', replace '*best_guess' with it.
|
|
|
|
*
|
|
|
|
* "Better" means having a serial number closer to 'serial'
|
|
|
|
* but not greater than 'serial'.
|
|
|
|
*/
|
|
|
|
static void
|
2018-03-28 14:19:37 +02:00
|
|
|
index_find(dns_journal_t *j, uint32_t serial, journal_pos_t *best_guess) {
|
1999-08-20 05:26:49 +00:00
|
|
|
unsigned int i;
|
|
|
|
if (j->index == NULL) {
|
|
|
|
return;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
for (i = 0; i < j->header.index_size; i++) {
|
|
|
|
if (POS_VALID(j->index[i]) &&
|
|
|
|
DNS_SERIAL_GE(serial, j->index[i].serial) &&
|
|
|
|
DNS_SERIAL_GT(j->index[i].serial, best_guess->serial))
|
|
|
|
{
|
|
|
|
*best_guess = j->index[i];
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Add a new index entry. If there is no room, make room by removing
|
|
|
|
* the odd-numbered entries and compacting the others into the first
|
|
|
|
* half of the index. This decimates old index entries exponentially
|
|
|
|
* over time, so that the index always contains a much larger fraction
|
|
|
|
* of recent serial numbers than of old ones. This is deliberate -
|
|
|
|
* most index searches are for outgoing IXFR, and IXFR tends to request
|
|
|
|
* recent versions more often than old ones.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
index_add(dns_journal_t *j, journal_pos_t *pos) {
|
|
|
|
unsigned int i;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
if (j->index == NULL) {
|
|
|
|
return;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Search for a vacant position.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
for (i = 0; i < j->header.index_size; i++) {
|
|
|
|
if (!POS_VALID(j->index[i])) {
|
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
if (i == j->header.index_size) {
|
|
|
|
unsigned int k = 0;
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Found no vacant position. Make some room.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
for (i = 0; i < j->header.index_size; i += 2) {
|
|
|
|
j->index[k++] = j->index[i];
|
|
|
|
}
|
|
|
|
i = k; /* 'i' identifies the first vacant position. */
|
|
|
|
while (k < j->header.index_size) {
|
|
|
|
POS_INVALIDATE(j->index[k]);
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
INSIST(i < j->header.index_size);
|
|
|
|
INSIST(!POS_VALID(j->index[i]));
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Store the new index entry.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
j->index[i] = *pos;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Invalidate any existing index entries that could become
|
|
|
|
* ambiguous when a new transaction with number 'serial' is added.
|
|
|
|
*/
|
|
|
|
static void
|
2018-03-28 14:19:37 +02:00
|
|
|
index_invalidate(dns_journal_t *j, uint32_t serial) {
|
1999-08-20 05:26:49 +00:00
|
|
|
unsigned int i;
|
|
|
|
if (j->index == NULL) {
|
|
|
|
return;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
for (i = 0; i < j->header.index_size; i++) {
|
|
|
|
if (!DNS_SERIAL_GT(serial, j->index[i].serial)) {
|
|
|
|
POS_INVALIDATE(j->index[i]);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Try to find a transaction with initial serial number 'serial'
|
|
|
|
* in the journal 'j'.
|
|
|
|
*
|
2000-04-06 22:03:35 +00:00
|
|
|
* If found, store its position at '*pos' and return ISC_R_SUCCESS.
|
1999-08-20 05:26:49 +00:00
|
|
|
*
|
|
|
|
* If 'serial' is current (= the ending serial number of the
|
|
|
|
* last transaction in the journal), set '*pos' to
|
|
|
|
* the position immediately following the last transaction and
|
2000-04-06 22:03:35 +00:00
|
|
|
* return ISC_R_SUCCESS.
|
1999-08-20 05:26:49 +00:00
|
|
|
*
|
|
|
|
* If 'serial' is within the range of addressable serial numbers
|
|
|
|
* covered by the journal but that particular serial number is missing
|
2000-04-06 22:03:35 +00:00
|
|
|
* (from the journal, not just from the index), return ISC_R_NOTFOUND.
|
1999-08-20 05:26:49 +00:00
|
|
|
*
|
|
|
|
* If 'serial' is outside the range of addressable serial numbers
|
2000-05-15 21:14:38 +00:00
|
|
|
* covered by the journal, return ISC_R_RANGE.
|
1999-08-20 05:26:49 +00:00
|
|
|
*
|
|
|
|
*/
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
2018-03-28 14:19:37 +02:00
|
|
|
journal_find(dns_journal_t *j, uint32_t serial, journal_pos_t *pos) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_pos_t current_pos;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
1999-09-21 22:45:24 +00:00
|
|
|
REQUIRE(DNS_JOURNAL_VALID(j));
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
if (DNS_SERIAL_GT(j->header.begin.serial, serial)) {
|
2000-05-15 21:14:38 +00:00
|
|
|
return (ISC_R_RANGE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
if (DNS_SERIAL_GT(serial, j->header.end.serial)) {
|
2000-05-15 21:14:38 +00:00
|
|
|
return (ISC_R_RANGE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
if (serial == j->header.end.serial) {
|
|
|
|
*pos = j->header.end;
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
current_pos = j->header.begin;
|
|
|
|
index_find(j, serial, ¤t_pos);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
while (current_pos.serial != serial) {
|
|
|
|
if (DNS_SERIAL_GT(current_pos.serial, serial)) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOTFOUND);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2021-05-13 15:44:02 +10:00
|
|
|
result = journal_next(j, ¤t_pos);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-08-20 05:26:49 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
*pos = current_pos;
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_journal_begin_transaction(dns_journal_t *j) {
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t offset;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-09-21 22:45:24 +00:00
|
|
|
REQUIRE(DNS_JOURNAL_VALID(j));
|
2011-08-30 05:16:15 +00:00
|
|
|
REQUIRE(j->state == JOURNAL_STATE_WRITE ||
|
2011-11-28 03:14:59 +00:00
|
|
|
j->state == JOURNAL_STATE_INLINE);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
/*
|
|
|
|
* Find the file offset where the new transaction should
|
|
|
|
* be written, and seek there.
|
|
|
|
*/
|
|
|
|
if (JOURNAL_EMPTY(&j->header)) {
|
|
|
|
offset = sizeof(journal_rawheader_t) +
|
2023-08-23 10:00:12 +02:00
|
|
|
ISC_CHECKED_MUL(j->header.index_size,
|
|
|
|
sizeof(journal_rawpos_t));
|
1999-08-20 05:26:49 +00:00
|
|
|
} else {
|
|
|
|
offset = j->header.end.offset;
|
|
|
|
}
|
|
|
|
j->x.pos[0].offset = offset;
|
|
|
|
j->x.pos[1].offset = offset; /* Initial value, will be incremented. */
|
|
|
|
j->x.n_soa = 0;
|
|
|
|
|
|
|
|
CHECK(journal_seek(j, offset));
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
/*
|
|
|
|
* Write a dummy transaction header of all zeroes to reserve
|
|
|
|
* space. It will be filled in when the transaction is
|
|
|
|
* finished.
|
|
|
|
*/
|
2021-03-31 13:29:13 +11:00
|
|
|
CHECK(journal_write_xhdr(j, 0, 0, 0, 0));
|
1999-08-20 05:26:49 +00:00
|
|
|
j->x.pos[1].offset = j->offset;
|
|
|
|
|
|
|
|
j->state = JOURNAL_STATE_TRANSACTION;
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
1999-08-20 05:26:49 +00:00
|
|
|
failure:
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_journal_writediff(dns_journal_t *j, dns_diff_t *diff) {
|
|
|
|
dns_difftuple_t *t;
|
|
|
|
isc_buffer_t buffer;
|
|
|
|
void *mem = NULL;
|
2020-02-21 17:05:04 -08:00
|
|
|
uint64_t size = 0;
|
|
|
|
uint32_t rrcount = 0;
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-08-20 05:26:49 +00:00
|
|
|
isc_region_t used;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-09-21 22:45:24 +00:00
|
|
|
REQUIRE(DNS_DIFF_VALID(diff));
|
1999-08-20 05:26:49 +00:00
|
|
|
REQUIRE(j->state == JOURNAL_STATE_TRANSACTION);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-10-27 00:32:50 +00:00
|
|
|
isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "writing to journal");
|
2001-11-30 01:59:49 +00:00
|
|
|
(void)dns_diff_print(diff, NULL);
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Pass 1: determine the buffer size needed, and
|
|
|
|
* keep track of SOA serial numbers.
|
|
|
|
*/
|
|
|
|
for (t = ISC_LIST_HEAD(diff->tuples); t != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
t = ISC_LIST_NEXT(t, link))
|
|
|
|
{
|
1999-08-20 05:26:49 +00:00
|
|
|
if (t->rdata.type == dns_rdatatype_soa) {
|
|
|
|
if (j->x.n_soa < 2) {
|
|
|
|
j->x.pos[j->x.n_soa].serial =
|
|
|
|
dns_soa_getserial(&t->rdata);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
j->x.n_soa++;
|
|
|
|
}
|
|
|
|
size += sizeof(journal_rawrrhdr_t);
|
|
|
|
size += t->name.length; /* XXX should have access macro? */
|
|
|
|
size += 10;
|
|
|
|
size += t->rdata.length;
|
|
|
|
}
|
|
|
|
|
2018-06-26 21:06:55 +02:00
|
|
|
if (size >= DNS_JOURNAL_SIZE_MAX) {
|
2018-06-27 14:10:04 +02:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"dns_journal_writediff: %s: journal entry "
|
2018-03-28 14:19:37 +02:00
|
|
|
"too big to be stored: %" PRIu64 " bytes",
|
|
|
|
j->filename, size);
|
2018-06-27 14:10:04 +02:00
|
|
|
return (ISC_R_NOSPACE);
|
2018-06-26 21:06:55 +02:00
|
|
|
}
|
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
mem = isc_mem_get(j->mctx, size);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&buffer, mem, size);
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Pass 2. Write RRs to buffer.
|
|
|
|
*/
|
|
|
|
for (t = ISC_LIST_HEAD(diff->tuples); t != NULL;
|
2022-11-02 19:33:14 +01:00
|
|
|
t = ISC_LIST_NEXT(t, link))
|
|
|
|
{
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Write the RR header.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
isc_buffer_putuint32(&buffer,
|
|
|
|
t->name.length + 10 + t->rdata.length);
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Write the owner name, RR header, and RR data.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
isc_buffer_putmem(&buffer, t->name.ndata, t->name.length);
|
|
|
|
isc_buffer_putuint16(&buffer, t->rdata.type);
|
|
|
|
isc_buffer_putuint16(&buffer, t->rdata.rdclass);
|
|
|
|
isc_buffer_putuint32(&buffer, t->ttl);
|
1999-10-17 22:18:45 +00:00
|
|
|
INSIST(t->rdata.length < 65536);
|
2018-03-28 14:19:37 +02:00
|
|
|
isc_buffer_putuint16(&buffer, (uint16_t)t->rdata.length);
|
2000-05-04 22:16:00 +00:00
|
|
|
INSIST(isc_buffer_availablelength(&buffer) >= t->rdata.length);
|
|
|
|
isc_buffer_putmem(&buffer, t->rdata.data, t->rdata.length);
|
2020-02-21 17:05:04 -08:00
|
|
|
|
|
|
|
rrcount++;
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_usedregion(&buffer, &used);
|
1999-08-20 05:26:49 +00:00
|
|
|
INSIST(used.length == size);
|
|
|
|
|
|
|
|
j->x.pos[1].offset += used.length;
|
2020-02-21 17:05:04 -08:00
|
|
|
j->x.n_rr = rrcount;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Write the buffer contents to the journal file.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(journal_write(j, used.base, used.length));
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
failure:
|
|
|
|
if (mem != NULL) {
|
|
|
|
isc_mem_put(j->mctx, mem, size);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_journal_commit(dns_journal_t *j) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_rawheader_t rawheader;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint64_t total;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-09-21 22:45:24 +00:00
|
|
|
REQUIRE(DNS_JOURNAL_VALID(j));
|
2011-08-30 05:16:15 +00:00
|
|
|
REQUIRE(j->state == JOURNAL_STATE_TRANSACTION ||
|
2011-11-28 03:14:59 +00:00
|
|
|
j->state == JOURNAL_STATE_INLINE);
|
2011-08-30 05:16:15 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Just write out a updated header.
|
|
|
|
*/
|
2011-11-28 03:14:59 +00:00
|
|
|
if (j->state == JOURNAL_STATE_INLINE) {
|
2011-08-30 05:16:15 +00:00
|
|
|
CHECK(journal_fsync(j));
|
|
|
|
journal_header_encode(&j->header, &rawheader);
|
|
|
|
CHECK(journal_seek(j, 0));
|
|
|
|
CHECK(journal_write(j, &rawheader, sizeof(rawheader)));
|
|
|
|
CHECK(journal_fsync(j));
|
|
|
|
j->state = JOURNAL_STATE_WRITE;
|
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Perform some basic consistency checks.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
if (j->x.n_soa != 2) {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2004-09-16 04:54:03 +00:00
|
|
|
"%s: malformed transaction: %d SOAs", j->filename,
|
|
|
|
j->x.n_soa);
|
1999-08-20 05:26:49 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
|
|
|
}
|
2018-06-28 12:21:43 +10:00
|
|
|
if (!DNS_SERIAL_GT(j->x.pos[1].serial, j->x.pos[0].serial)) {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2004-09-16 04:54:03 +00:00
|
|
|
"%s: malformed transaction: serial number "
|
2018-06-28 12:21:43 +10:00
|
|
|
"did not increase",
|
|
|
|
j->filename);
|
1999-08-20 05:26:49 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
|
|
|
}
|
|
|
|
if (!JOURNAL_EMPTY(&j->header)) {
|
|
|
|
if (j->x.pos[0].serial != j->header.end.serial) {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
1999-08-20 05:26:49 +00:00
|
|
|
"malformed transaction: "
|
|
|
|
"%s last serial %u != "
|
|
|
|
"transaction first serial %u",
|
|
|
|
j->filename, j->header.end.serial,
|
|
|
|
j->x.pos[0].serial);
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2018-06-26 21:06:55 +02:00
|
|
|
/*
|
|
|
|
* We currently don't support huge journal entries.
|
|
|
|
*/
|
2018-06-27 14:10:04 +02:00
|
|
|
total = j->x.pos[1].offset - j->x.pos[0].offset;
|
2018-06-26 21:06:55 +02:00
|
|
|
if (total >= DNS_JOURNAL_SIZE_MAX) {
|
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2018-06-27 14:10:04 +02:00
|
|
|
"transaction too big to be stored in journal: "
|
2018-03-28 14:19:37 +02:00
|
|
|
"%" PRIu64 "b (max is %" PRIu64 "b)",
|
|
|
|
total, (uint64_t)DNS_JOURNAL_SIZE_MAX);
|
2018-06-26 21:06:55 +02:00
|
|
|
return (ISC_R_UNEXPECTED);
|
|
|
|
}
|
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
/*
|
|
|
|
* Some old journal entries may become non-addressable
|
|
|
|
* when we increment the current serial number. Purge them
|
|
|
|
* by stepping header.begin forward to the first addressable
|
|
|
|
* transaction. Also purge them from the index.
|
|
|
|
*/
|
|
|
|
if (!JOURNAL_EMPTY(&j->header)) {
|
|
|
|
while (!DNS_SERIAL_GT(j->x.pos[1].serial,
|
2022-11-02 19:33:14 +01:00
|
|
|
j->header.begin.serial))
|
|
|
|
{
|
2021-05-13 15:44:02 +10:00
|
|
|
CHECK(journal_next(j, &j->header.begin));
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
index_invalidate(j, j->x.pos[1].serial);
|
|
|
|
}
|
|
|
|
#ifdef notyet
|
|
|
|
if (DNS_SERIAL_GT(last_dumped_serial, j->x.pos[1].serial)) {
|
|
|
|
force_dump(...);
|
|
|
|
}
|
|
|
|
#endif /* ifdef notyet */
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Commit the transaction data to stable storage.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(journal_fsync(j));
|
|
|
|
|
2011-08-30 05:16:15 +00:00
|
|
|
if (j->state == JOURNAL_STATE_TRANSACTION) {
|
2022-12-16 11:47:40 +00:00
|
|
|
off_t offset;
|
2011-08-30 05:16:15 +00:00
|
|
|
offset = (j->x.pos[1].offset - j->x.pos[0].offset) -
|
2021-04-01 15:30:42 +11:00
|
|
|
(j->header_ver1 ? sizeof(journal_rawxhdr_ver1_t)
|
|
|
|
: sizeof(journal_rawxhdr_t));
|
2011-08-30 05:16:15 +00:00
|
|
|
/*
|
|
|
|
* Update the transaction header.
|
|
|
|
*/
|
|
|
|
CHECK(journal_seek(j, j->x.pos[0].offset));
|
2020-02-21 17:05:04 -08:00
|
|
|
CHECK(journal_write_xhdr(j, offset, j->x.n_rr,
|
|
|
|
j->x.pos[0].serial,
|
2011-08-30 05:16:15 +00:00
|
|
|
j->x.pos[1].serial));
|
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Update the journal header.
|
|
|
|
*/
|
2011-12-22 07:32:41 +00:00
|
|
|
if (JOURNAL_EMPTY(&j->header)) {
|
1999-08-20 05:26:49 +00:00
|
|
|
j->header.begin = j->x.pos[0];
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
j->header.end = j->x.pos[1];
|
|
|
|
journal_header_encode(&j->header, &rawheader);
|
|
|
|
CHECK(journal_seek(j, 0));
|
|
|
|
CHECK(journal_write(j, &rawheader, sizeof(rawheader)));
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
2000-06-02 23:43:17 +00:00
|
|
|
* Update the index.
|
2000-05-08 14:38:29 +00:00
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
index_add(j, &j->x.pos[0]);
|
2000-06-02 23:43:17 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Convert the index into on-disk format and write
|
|
|
|
* it to disk.
|
|
|
|
*/
|
2001-09-15 07:16:39 +00:00
|
|
|
CHECK(index_to_disk(j));
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Commit the header to stable storage.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(journal_fsync(j));
|
1999-10-29 18:04:07 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* We no longer have a transaction open.
|
|
|
|
*/
|
1999-10-29 18:04:07 +00:00
|
|
|
j->state = JOURNAL_STATE_WRITE;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
failure:
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_journal_write_transaction(dns_journal_t *j, dns_diff_t *diff) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(dns_diff_sort(diff, ixfr_order));
|
|
|
|
CHECK(dns_journal_begin_transaction(j));
|
|
|
|
CHECK(dns_journal_writediff(j, diff));
|
|
|
|
CHECK(dns_journal_commit(j));
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
1999-08-20 05:26:49 +00:00
|
|
|
failure:
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_journal_destroy(dns_journal_t **journalp) {
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
dns_journal_t *j = NULL;
|
|
|
|
|
|
|
|
REQUIRE(journalp != NULL);
|
|
|
|
REQUIRE(DNS_JOURNAL_VALID(*journalp));
|
|
|
|
|
|
|
|
j = *journalp;
|
2020-02-08 04:37:54 -08:00
|
|
|
*journalp = NULL;
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
j->it.result = ISC_R_FAILURE;
|
|
|
|
dns_name_invalidate(&j->it.name);
|
2000-06-02 23:43:17 +00:00
|
|
|
if (j->rawindex != NULL) {
|
2023-08-23 08:56:31 +02:00
|
|
|
isc_mem_cput(j->mctx, j->rawindex, j->header.index_size,
|
|
|
|
sizeof(journal_rawpos_t));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
if (j->index != NULL) {
|
2023-08-23 08:56:31 +02:00
|
|
|
isc_mem_cput(j->mctx, j->index, j->header.index_size,
|
|
|
|
sizeof(journal_pos_t));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
if (j->it.target.base != NULL) {
|
|
|
|
isc_mem_put(j->mctx, j->it.target.base, j->it.target.length);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
if (j->it.source.base != NULL) {
|
|
|
|
isc_mem_put(j->mctx, j->it.source.base, j->it.source.length);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2013-09-09 22:12:47 -07:00
|
|
|
if (j->filename != NULL) {
|
|
|
|
isc_mem_free(j->mctx, j->filename);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
if (j->fp != NULL) {
|
2000-05-11 16:14:05 +00:00
|
|
|
(void)isc_stdio_close(j->fp);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
j->magic = 0;
|
2013-02-20 21:39:05 -08:00
|
|
|
isc_mem_putanddetach(&j->mctx, j, sizeof(*j));
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
/*
|
|
|
|
* Roll the open journal 'j' into the database 'db'.
|
|
|
|
* A new database version will be created.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* XXX Share code with incoming IXFR? */
|
|
|
|
|
2021-04-13 13:26:09 +02:00
|
|
|
isc_result_t
|
|
|
|
dns_journal_rollforward(dns_journal_t *j, dns_db_t *db, unsigned int options) {
|
1999-08-20 05:26:49 +00:00
|
|
|
isc_buffer_t source; /* Transaction data from disk */
|
|
|
|
isc_buffer_t target; /* Ditto after _fromwire check */
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t db_serial; /* Database SOA serial */
|
|
|
|
uint32_t end_serial; /* Last journal SOA serial */
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_dbversion_t *ver = NULL;
|
|
|
|
journal_pos_t pos;
|
|
|
|
dns_diff_t diff;
|
|
|
|
unsigned int n_soa = 0;
|
|
|
|
unsigned int n_put = 0;
|
2008-04-01 01:37:25 +00:00
|
|
|
dns_diffop_t op;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-09-21 22:45:24 +00:00
|
|
|
REQUIRE(DNS_JOURNAL_VALID(j));
|
1999-08-20 05:26:49 +00:00
|
|
|
REQUIRE(DNS_DB_VALID(db));
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_diff_init(j->mctx, &diff);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
/*
|
2009-01-17 14:45:17 +00:00
|
|
|
* Set up empty initial buffers for unchecked and checked
|
1999-08-20 05:26:49 +00:00
|
|
|
* wire format transaction data. They will be reallocated
|
|
|
|
* later.
|
|
|
|
*/
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&source, NULL, 0);
|
|
|
|
isc_buffer_init(&target, NULL, 0);
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Create the new database version.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(dns_db_newversion(db, &ver));
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Get the current database SOA serial number.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(dns_db_getsoaserial(db, ver, &db_serial));
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Locate a journal entry for the current database serial.
|
|
|
|
*/
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(journal_find(j, db_serial, &pos));
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
|
|
|
end_serial = dns_journal_last_serial(j);
|
|
|
|
|
2000-12-11 19:24:30 +00:00
|
|
|
/*
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
* If we're reading a version 1 file, scan all the transactions
|
|
|
|
* to see if the journal needs rewriting: if any outdated
|
|
|
|
* transaction headers are found, j->recovered will be set.
|
1999-08-20 05:26:49 +00:00
|
|
|
*/
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
if (j->header_ver1) {
|
|
|
|
uint32_t start_serial = dns_journal_first_serial(j);
|
|
|
|
|
|
|
|
CHECK(dns_journal_iter_init(j, start_serial, db_serial, NULL));
|
|
|
|
for (result = dns_journal_first_rr(j); result == ISC_R_SUCCESS;
|
|
|
|
result = dns_journal_next_rr(j))
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
|
1999-10-13 22:47:12 +00:00
|
|
|
if (db_serial == end_serial) {
|
|
|
|
CHECK(DNS_R_UPTODATE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-13 22:47:12 +00:00
|
|
|
|
2020-02-21 17:05:04 -08:00
|
|
|
CHECK(dns_journal_iter_init(j, db_serial, end_serial, NULL));
|
1999-08-20 05:26:49 +00:00
|
|
|
for (result = dns_journal_first_rr(j); result == ISC_R_SUCCESS;
|
|
|
|
result = dns_journal_next_rr(j))
|
|
|
|
{
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
dns_name_t *name = NULL;
|
|
|
|
dns_rdata_t *rdata = NULL;
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_difftuple_t *tuple = NULL;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
uint32_t ttl;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_journal_current_rr(j, &name, &ttl, &rdata);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2002-07-22 02:06:04 +00:00
|
|
|
if (rdata->type == dns_rdatatype_soa) {
|
1999-08-20 05:26:49 +00:00
|
|
|
n_soa++;
|
2002-07-22 02:06:04 +00:00
|
|
|
if (n_soa == 2) {
|
|
|
|
db_serial = j->it.current_serial;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2002-07-22 02:06:04 +00:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
if (n_soa == 3) {
|
|
|
|
n_soa = 1;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
if (n_soa == 0) {
|
2000-05-24 05:10:00 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2000-02-14 19:26:23 +00:00
|
|
|
"%s: journal file corrupt: missing "
|
|
|
|
"initial SOA",
|
|
|
|
j->filename);
|
2000-04-06 22:03:35 +00:00
|
|
|
FAIL(ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2008-04-01 01:37:25 +00:00
|
|
|
if ((options & DNS_JOURNALOPT_RESIGN) != 0) {
|
|
|
|
op = (n_soa == 1) ? DNS_DIFFOP_DELRESIGN
|
|
|
|
: DNS_DIFFOP_ADDRESIGN;
|
|
|
|
} else {
|
|
|
|
op = (n_soa == 1) ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2008-04-01 23:47:10 +00:00
|
|
|
|
2008-04-01 01:37:25 +00:00
|
|
|
CHECK(dns_difftuple_create(diff.mctx, op, name, ttl, rdata,
|
|
|
|
&tuple));
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_diff_append(&diff, &tuple);
|
|
|
|
|
|
|
|
if (++n_put > 100) {
|
1999-10-27 00:32:50 +00:00
|
|
|
isc_log_write(JOURNAL_DEBUG_LOGARGS(3),
|
2004-09-16 04:54:03 +00:00
|
|
|
"%s: applying diff to database (%u)",
|
|
|
|
j->filename, db_serial);
|
2001-11-30 01:59:49 +00:00
|
|
|
(void)dns_diff_print(&diff, NULL);
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(dns_diff_apply(&diff, db, ver));
|
|
|
|
dns_diff_clear(&diff);
|
|
|
|
n_put = 0;
|
|
|
|
}
|
|
|
|
}
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result == ISC_R_NOMORE) {
|
|
|
|
result = ISC_R_SUCCESS;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(result);
|
|
|
|
|
|
|
|
if (n_put != 0) {
|
1999-10-27 00:32:50 +00:00
|
|
|
isc_log_write(JOURNAL_DEBUG_LOGARGS(3),
|
2004-09-16 04:54:03 +00:00
|
|
|
"%s: applying final diff to database (%u)",
|
|
|
|
j->filename, db_serial);
|
2001-11-30 01:59:49 +00:00
|
|
|
(void)dns_diff_print(&diff, NULL);
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(dns_diff_apply(&diff, db, ver));
|
|
|
|
dns_diff_clear(&diff);
|
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
failure:
|
|
|
|
if (ver != NULL) {
|
2000-04-06 22:03:35 +00:00
|
|
|
dns_db_closeversion(db, &ver,
|
|
|
|
result == ISC_R_SUCCESS ? true : false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
if (source.base != NULL) {
|
|
|
|
isc_mem_put(j->mctx, source.base, source.length);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
if (target.base != NULL) {
|
|
|
|
isc_mem_put(j->mctx, target.base, target.length);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
dns_diff_clear(&diff);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2014-10-03 07:50:09 +10:00
|
|
|
INSIST(ver == NULL);
|
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
dns_journal_print(isc_mem_t *mctx, uint32_t flags, const char *filename,
|
|
|
|
FILE *file) {
|
|
|
|
dns_journal_t *j = NULL;
|
1999-10-13 22:47:12 +00:00
|
|
|
isc_buffer_t source; /* Transaction data from disk */
|
|
|
|
isc_buffer_t target; /* Ditto after _fromwire check */
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t start_serial; /* Database SOA serial */
|
|
|
|
uint32_t end_serial; /* Last journal SOA serial */
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-10-13 22:47:12 +00:00
|
|
|
dns_diff_t diff;
|
|
|
|
unsigned int n_soa = 0;
|
|
|
|
unsigned int n_put = 0;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
bool printxhdr = ((flags & DNS_JOURNAL_PRINTXHDR) != 0);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-10-13 22:47:12 +00:00
|
|
|
REQUIRE(filename != NULL);
|
|
|
|
|
2011-12-22 07:32:41 +00:00
|
|
|
result = dns_journal_open(mctx, filename, DNS_JOURNAL_READ, &j);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result == ISC_R_NOTFOUND) {
|
1999-10-27 00:32:50 +00:00
|
|
|
isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no journal file");
|
1999-12-13 02:58:06 +00:00
|
|
|
return (DNS_R_NOJOURNAL);
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
} else if (result != ISC_R_SUCCESS) {
|
1999-10-27 00:32:50 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2004-09-16 04:54:03 +00:00
|
|
|
"journal open failure: %s: %s",
|
2008-09-25 02:01:45 +00:00
|
|
|
isc_result_totext(result), filename);
|
1999-10-27 05:53:59 +00:00
|
|
|
return (result);
|
1999-10-13 22:47:12 +00:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2021-03-03 17:07:15 +11:00
|
|
|
if (printxhdr) {
|
|
|
|
fprintf(file, "Journal format = %sHeader version = %d\n",
|
|
|
|
j->header.format + 1, j->header_ver1 ? 1 : 2);
|
2021-03-07 20:50:56 -08:00
|
|
|
fprintf(file, "Start serial = %u\n", j->header.begin.serial);
|
|
|
|
fprintf(file, "End serial = %u\n", j->header.end.serial);
|
2021-03-03 14:59:30 -08:00
|
|
|
fprintf(file, "Index (size = %u):\n", j->header.index_size);
|
|
|
|
for (uint32_t i = 0; i < j->header.index_size; i++) {
|
|
|
|
if (j->index[i].offset == 0) {
|
|
|
|
fputc('\n', file);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fprintf(file, "%lld", (long long)j->index[i].offset);
|
|
|
|
fputc((i + 1) % 8 == 0 ? '\n' : ' ', file);
|
|
|
|
}
|
2021-03-03 17:07:15 +11:00
|
|
|
}
|
2011-12-22 07:32:41 +00:00
|
|
|
if (j->header.serialset) {
|
|
|
|
fprintf(file, "Source serial = %u\n", j->header.sourceserial);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-13 22:47:12 +00:00
|
|
|
dns_diff_init(j->mctx, &diff);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-10-13 22:47:12 +00:00
|
|
|
/*
|
2009-01-17 14:45:17 +00:00
|
|
|
* Set up empty initial buffers for unchecked and checked
|
1999-10-13 22:47:12 +00:00
|
|
|
* wire format transaction data. They will be reallocated
|
|
|
|
* later.
|
|
|
|
*/
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&source, NULL, 0);
|
|
|
|
isc_buffer_init(&target, NULL, 0);
|
1999-10-13 22:47:12 +00:00
|
|
|
|
|
|
|
start_serial = dns_journal_first_serial(j);
|
|
|
|
end_serial = dns_journal_last_serial(j);
|
|
|
|
|
2020-02-21 17:05:04 -08:00
|
|
|
CHECK(dns_journal_iter_init(j, start_serial, end_serial, NULL));
|
1999-10-13 22:47:12 +00:00
|
|
|
|
|
|
|
for (result = dns_journal_first_rr(j); result == ISC_R_SUCCESS;
|
|
|
|
result = dns_journal_next_rr(j))
|
|
|
|
{
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
dns_name_t *name = NULL;
|
|
|
|
dns_rdata_t *rdata = NULL;
|
1999-10-13 22:47:12 +00:00
|
|
|
dns_difftuple_t *tuple = NULL;
|
2021-03-03 14:59:30 -08:00
|
|
|
static uint32_t i = 0;
|
|
|
|
bool print = false;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
uint32_t ttl;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-10-13 22:47:12 +00:00
|
|
|
dns_journal_current_rr(j, &name, &ttl, &rdata);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-10-13 22:47:12 +00:00
|
|
|
if (rdata->type == dns_rdatatype_soa) {
|
|
|
|
n_soa++;
|
2021-03-03 14:59:30 -08:00
|
|
|
if (n_soa == 3) {
|
|
|
|
n_soa = 1;
|
|
|
|
}
|
|
|
|
if (n_soa == 1) {
|
|
|
|
print = printxhdr;
|
|
|
|
}
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-13 22:47:12 +00:00
|
|
|
if (n_soa == 0) {
|
2008-09-25 02:01:45 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"%s: journal file corrupt: missing "
|
|
|
|
"initial SOA",
|
|
|
|
j->filename);
|
2000-04-06 22:03:35 +00:00
|
|
|
FAIL(ISC_R_UNEXPECTED);
|
1999-10-13 22:47:12 +00:00
|
|
|
}
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
2021-03-03 14:59:30 -08:00
|
|
|
if (print) {
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
fprintf(file,
|
2021-03-03 14:59:30 -08:00
|
|
|
"Transaction: version %d offset %lld size %u "
|
|
|
|
"rrcount %u start %u end %u\n",
|
|
|
|
j->xhdr_version, (long long)j->it.cpos.offset,
|
|
|
|
j->curxhdr.size, j->curxhdr.count,
|
|
|
|
j->curxhdr.serial0, j->curxhdr.serial1);
|
|
|
|
if (j->it.cpos.offset > j->index[i].offset) {
|
|
|
|
fprintf(file,
|
|
|
|
"ERROR: Offset mismatch, "
|
|
|
|
"expected %lld\n",
|
|
|
|
(long long)j->index[i].offset);
|
|
|
|
} else if (j->it.cpos.offset == j->index[i].offset) {
|
|
|
|
i++;
|
|
|
|
}
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
}
|
1999-10-13 22:47:12 +00:00
|
|
|
CHECK(dns_difftuple_create(
|
|
|
|
diff.mctx, n_soa == 1 ? DNS_DIFFOP_DEL : DNS_DIFFOP_ADD,
|
|
|
|
name, ttl, rdata, &tuple));
|
|
|
|
dns_diff_append(&diff, &tuple);
|
|
|
|
|
2021-03-08 06:53:30 +11:00
|
|
|
if (++n_put > 100 || printxhdr) {
|
1999-10-27 05:53:59 +00:00
|
|
|
result = dns_diff_print(&diff, file);
|
1999-10-13 22:47:12 +00:00
|
|
|
dns_diff_clear(&diff);
|
|
|
|
n_put = 0;
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-10-27 05:53:59 +00:00
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-13 22:47:12 +00:00
|
|
|
}
|
|
|
|
}
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result == ISC_R_NOMORE) {
|
|
|
|
result = ISC_R_SUCCESS;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-13 22:47:12 +00:00
|
|
|
CHECK(result);
|
|
|
|
|
2021-03-08 06:53:30 +11:00
|
|
|
if (n_put != 0) {
|
1999-10-27 05:53:59 +00:00
|
|
|
result = dns_diff_print(&diff, file);
|
1999-10-13 22:47:12 +00:00
|
|
|
dns_diff_clear(&diff);
|
|
|
|
}
|
|
|
|
goto cleanup;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-10-13 22:47:12 +00:00
|
|
|
failure:
|
1999-10-27 00:32:50 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2000-02-14 19:26:23 +00:00
|
|
|
"%s: cannot print: journal file corrupt", j->filename);
|
1999-10-13 22:47:12 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (source.base != NULL) {
|
|
|
|
isc_mem_put(j->mctx, source.base, source.length);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-13 22:47:12 +00:00
|
|
|
if (target.base != NULL) {
|
|
|
|
isc_mem_put(j->mctx, target.base, target.length);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-10-13 22:47:12 +00:00
|
|
|
|
|
|
|
dns_diff_clear(&diff);
|
|
|
|
dns_journal_destroy(&j);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-10-27 05:53:59 +00:00
|
|
|
return (result);
|
1999-10-13 22:47:12 +00:00
|
|
|
}
|
1999-10-27 05:53:59 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
/**************************************************************************/
|
|
|
|
/*
|
|
|
|
* Miscellaneous accessors.
|
|
|
|
*/
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2017-05-02 13:23:08 -07:00
|
|
|
dns_journal_empty(dns_journal_t *j) {
|
|
|
|
return (JOURNAL_EMPTY(&j->header));
|
|
|
|
}
|
|
|
|
|
2021-04-13 13:26:09 +02:00
|
|
|
bool
|
|
|
|
dns_journal_recovered(dns_journal_t *j) {
|
|
|
|
return (j->recovered);
|
|
|
|
}
|
|
|
|
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t
|
2011-08-30 05:16:15 +00:00
|
|
|
dns_journal_first_serial(dns_journal_t *j) {
|
1999-08-20 05:26:49 +00:00
|
|
|
return (j->header.begin.serial);
|
|
|
|
}
|
|
|
|
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t
|
2011-08-30 05:16:15 +00:00
|
|
|
dns_journal_last_serial(dns_journal_t *j) {
|
1999-08-20 05:26:49 +00:00
|
|
|
return (j->header.end.serial);
|
|
|
|
}
|
|
|
|
|
2011-08-30 05:16:15 +00:00
|
|
|
void
|
2018-03-28 14:19:37 +02:00
|
|
|
dns_journal_set_sourceserial(dns_journal_t *j, uint32_t sourceserial) {
|
2011-08-30 05:16:15 +00:00
|
|
|
REQUIRE(j->state == JOURNAL_STATE_WRITE ||
|
2011-11-28 03:14:59 +00:00
|
|
|
j->state == JOURNAL_STATE_INLINE ||
|
2011-08-30 05:16:15 +00:00
|
|
|
j->state == JOURNAL_STATE_TRANSACTION);
|
|
|
|
|
2011-11-28 03:14:59 +00:00
|
|
|
j->header.sourceserial = sourceserial;
|
2018-04-17 08:29:14 -07:00
|
|
|
j->header.serialset = true;
|
2011-08-30 05:16:15 +00:00
|
|
|
if (j->state == JOURNAL_STATE_WRITE) {
|
2011-11-28 03:14:59 +00:00
|
|
|
j->state = JOURNAL_STATE_INLINE;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-08-30 05:16:15 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
bool
|
2018-03-28 14:19:37 +02:00
|
|
|
dns_journal_get_sourceserial(dns_journal_t *j, uint32_t *sourceserial) {
|
2011-12-22 07:32:41 +00:00
|
|
|
REQUIRE(sourceserial != NULL);
|
|
|
|
|
|
|
|
if (!j->header.serialset) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return (false);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-12-22 07:32:41 +00:00
|
|
|
*sourceserial = j->header.sourceserial;
|
2018-04-17 08:29:14 -07:00
|
|
|
return (true);
|
2011-08-30 05:16:15 +00:00
|
|
|
}
|
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
/**************************************************************************/
|
|
|
|
/*
|
|
|
|
* Iteration support.
|
|
|
|
*
|
|
|
|
* When serving an outgoing IXFR, we transmit a part the journal starting
|
|
|
|
* at the serial number in the IXFR request and ending at the serial
|
|
|
|
* number that is current when the IXFR request arrives. The ending
|
|
|
|
* serial number is not necessarily at the end of the journal:
|
|
|
|
* the journal may grow while the IXFR is in progress, but we stop
|
|
|
|
* when we reach the serial number that was current when the IXFR started.
|
|
|
|
*/
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
2021-05-13 15:44:02 +10:00
|
|
|
read_one_rr(dns_journal_t *j);
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure the buffer 'b' is has at least 'size' bytes
|
|
|
|
* allocated, and clear it.
|
|
|
|
*
|
|
|
|
* Requires:
|
|
|
|
* Either b->base is NULL, or it points to b->length bytes of memory
|
|
|
|
* previously allocated by isc_mem_get().
|
|
|
|
*/
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
2022-09-07 17:22:47 +02:00
|
|
|
size_buffer(isc_mem_t *mctx, isc_buffer_t *b, unsigned int size) {
|
1999-08-20 05:26:49 +00:00
|
|
|
if (b->length < size) {
|
|
|
|
void *mem = isc_mem_get(mctx, size);
|
|
|
|
if (mem == NULL) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMEMORY);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
if (b->base != NULL) {
|
|
|
|
isc_mem_put(mctx, b->base, b->length);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
b->base = mem;
|
|
|
|
b->length = size;
|
|
|
|
}
|
|
|
|
isc_buffer_clear(b);
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_journal_iter_init(dns_journal_t *j, uint32_t begin_serial,
|
2020-02-21 17:05:04 -08:00
|
|
|
uint32_t end_serial, size_t *xfrsizep) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(journal_find(j, begin_serial, &j->it.bpos));
|
|
|
|
INSIST(j->it.bpos.serial == begin_serial);
|
|
|
|
|
|
|
|
CHECK(journal_find(j, end_serial, &j->it.epos));
|
|
|
|
INSIST(j->it.epos.serial == end_serial);
|
|
|
|
|
2020-02-21 17:05:04 -08:00
|
|
|
if (xfrsizep != NULL) {
|
|
|
|
journal_pos_t pos = j->it.bpos;
|
|
|
|
journal_xhdr_t xhdr;
|
|
|
|
uint64_t size = 0;
|
|
|
|
uint32_t count = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We already know the beginning and ending serial
|
|
|
|
* numbers are in the journal. Scan through them,
|
|
|
|
* adding up sizes and RR counts so we can calculate
|
|
|
|
* the IXFR size.
|
|
|
|
*/
|
|
|
|
do {
|
2021-05-11 16:39:41 +10:00
|
|
|
CHECK(journal_seek(j, pos.offset));
|
2020-02-21 17:05:04 -08:00
|
|
|
CHECK(journal_read_xhdr(j, &xhdr));
|
2021-05-11 16:39:41 +10:00
|
|
|
|
2021-05-13 15:44:02 +10:00
|
|
|
if (j->header_ver1) {
|
|
|
|
CHECK(maybe_fixup_xhdr(j, &xhdr, pos.serial,
|
|
|
|
pos.offset));
|
2021-05-11 16:39:41 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Check that xhdr is consistent.
|
|
|
|
*/
|
|
|
|
if (xhdr.serial0 != pos.serial ||
|
2022-11-02 19:33:14 +01:00
|
|
|
isc_serial_le(xhdr.serial1, xhdr.serial0))
|
|
|
|
{
|
2021-05-11 16:39:41 +10:00
|
|
|
CHECK(ISC_R_UNEXPECTED);
|
|
|
|
}
|
2020-02-21 17:05:04 -08:00
|
|
|
|
|
|
|
size += xhdr.size;
|
|
|
|
count += xhdr.count;
|
|
|
|
|
2021-05-13 15:44:02 +10:00
|
|
|
result = journal_next(j, &pos);
|
2020-02-21 17:05:04 -08:00
|
|
|
if (result == ISC_R_NOMORE) {
|
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
}
|
|
|
|
CHECK(result);
|
|
|
|
} while (pos.serial != end_serial);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* For each RR, subtract the length of the RR header,
|
|
|
|
* as this would not be present in IXFR messages.
|
|
|
|
* (We don't need to worry about the transaction header
|
|
|
|
* because that was already excluded from xdr.size.)
|
|
|
|
*/
|
2023-08-23 10:00:12 +02:00
|
|
|
*xfrsizep = size - (ISC_CHECKED_MUL(
|
|
|
|
count, sizeof(journal_rawrrhdr_t)));
|
2020-02-21 17:05:04 -08:00
|
|
|
}
|
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
1999-08-20 05:26:49 +00:00
|
|
|
failure:
|
|
|
|
j->it.result = result;
|
|
|
|
return (j->it.result);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_journal_first_rr(dns_journal_t *j) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Seek to the beginning of the first transaction we are
|
|
|
|
* interested in.
|
|
|
|
*/
|
|
|
|
CHECK(journal_seek(j, j->it.bpos.offset));
|
|
|
|
j->it.current_serial = j->it.bpos.serial;
|
|
|
|
|
|
|
|
j->it.xsize = 0; /* We have no transaction data yet... */
|
|
|
|
j->it.xpos = 0; /* ...and haven't used any of it. */
|
|
|
|
|
2021-05-13 15:44:02 +10:00
|
|
|
return (read_one_rr(j));
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
failure:
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
2021-05-13 15:44:02 +10:00
|
|
|
read_one_rr(dns_journal_t *j) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_rdatatype_t rdtype;
|
|
|
|
dns_rdataclass_t rdclass;
|
|
|
|
unsigned int rdlen;
|
2018-03-28 14:19:37 +02:00
|
|
|
uint32_t ttl;
|
1999-08-20 05:26:49 +00:00
|
|
|
journal_xhdr_t xhdr;
|
|
|
|
journal_rrhdr_t rrhdr;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
dns_journal_t save = *j;
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2018-06-26 21:06:55 +02:00
|
|
|
if (j->offset > j->it.epos.offset) {
|
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"%s: journal corrupt: possible integer overflow",
|
|
|
|
j->filename);
|
|
|
|
return (ISC_R_UNEXPECTED);
|
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
if (j->offset == j->it.epos.offset) {
|
2000-04-06 22:03:35 +00:00
|
|
|
return (ISC_R_NOMORE);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
if (j->it.xpos == j->it.xsize) {
|
|
|
|
/*
|
|
|
|
* We are at a transaction boundary.
|
|
|
|
* Read another transaction header.
|
|
|
|
*/
|
|
|
|
CHECK(journal_read_xhdr(j, &xhdr));
|
|
|
|
if (xhdr.size == 0) {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
2004-09-16 04:54:03 +00:00
|
|
|
"%s: journal corrupt: empty transaction",
|
|
|
|
j->filename);
|
2000-04-06 22:03:35 +00:00
|
|
|
FAIL(ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2021-05-13 15:44:02 +10:00
|
|
|
|
|
|
|
if (j->header_ver1) {
|
|
|
|
CHECK(maybe_fixup_xhdr(j, &xhdr, j->it.current_serial,
|
|
|
|
save.offset));
|
|
|
|
}
|
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
if (xhdr.serial0 != j->it.current_serial ||
|
|
|
|
isc_serial_le(xhdr.serial1, xhdr.serial0))
|
|
|
|
{
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"%s: journal file corrupt: "
|
1999-08-20 05:26:49 +00:00
|
|
|
"expected serial %u, got %u",
|
|
|
|
j->filename, j->it.current_serial,
|
|
|
|
xhdr.serial0);
|
2000-04-06 22:03:35 +00:00
|
|
|
FAIL(ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2021-03-31 15:03:33 +11:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
j->it.xsize = xhdr.size;
|
|
|
|
j->it.xpos = 0;
|
|
|
|
}
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Read an RR.
|
|
|
|
*/
|
2005-11-03 22:59:53 +00:00
|
|
|
CHECK(journal_read_rrhdr(j, &rrhdr));
|
1999-08-20 12:31:27 +00:00
|
|
|
/*
|
|
|
|
* Perform a sanity check on the journal RR size.
|
|
|
|
* The smallest possible RR has a 1-byte owner name
|
|
|
|
* and a 10-byte header. The largest possible
|
|
|
|
* RR has 65535 bytes of data, a header, and a maximum-
|
|
|
|
* size owner name, well below 70 k total.
|
|
|
|
*/
|
|
|
|
if (rrhdr.size < 1 + 10 || rrhdr.size > 70000) {
|
2000-02-14 19:26:23 +00:00
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"%s: journal corrupt: impossible RR size "
|
|
|
|
"(%d bytes)",
|
|
|
|
j->filename, rrhdr.size);
|
2000-04-06 22:03:35 +00:00
|
|
|
FAIL(ISC_R_UNEXPECTED);
|
1999-08-20 05:26:49 +00:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(size_buffer(j->mctx, &j->it.source, rrhdr.size));
|
|
|
|
CHECK(journal_read(j, j->it.source.base, rrhdr.size));
|
|
|
|
isc_buffer_add(&j->it.source, rrhdr.size);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The target buffer is made the same size
|
|
|
|
* as the source buffer, with the assumption that when
|
|
|
|
* no compression in present, the output of dns_*_fromwire()
|
|
|
|
* is no larger than the input.
|
|
|
|
*/
|
|
|
|
CHECK(size_buffer(j->mctx, &j->it.target, rrhdr.size));
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
/*
|
|
|
|
* Parse the owner name. We don't know where it
|
|
|
|
* ends yet, so we make the entire "remaining"
|
|
|
|
* part of the buffer "active".
|
|
|
|
*/
|
|
|
|
isc_buffer_setactive(&j->it.source,
|
|
|
|
j->it.source.used - j->it.source.current);
|
2022-11-09 17:10:59 +00:00
|
|
|
CHECK(dns_name_fromwire(&j->it.name, &j->it.source, j->it.dctx,
|
2004-02-27 20:41:51 +00:00
|
|
|
&j->it.target));
|
1999-08-20 05:26:49 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Check that the RR header is there, and parse it.
|
|
|
|
*/
|
2000-04-27 00:24:21 +00:00
|
|
|
if (isc_buffer_remaininglength(&j->it.source) < 10) {
|
1999-08-20 05:26:49 +00:00
|
|
|
FAIL(DNS_R_FORMERR);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-08-20 05:26:49 +00:00
|
|
|
rdtype = isc_buffer_getuint16(&j->it.source);
|
|
|
|
rdclass = isc_buffer_getuint16(&j->it.source);
|
|
|
|
ttl = isc_buffer_getuint32(&j->it.source);
|
|
|
|
rdlen = isc_buffer_getuint16(&j->it.source);
|
|
|
|
|
Silence tainted scalar on rdlen
2042 ttl = isc_buffer_getuint32(&j->it.source);
13. tainted_data_transitive: Call to function isc_buffer_getuint16 with tainted argument *j->it.source.base returns tainted data. [show details]
14. var_assign: Assigning: rdlen = isc_buffer_getuint16(&j->it.source), which taints rdlen.
2043 rdlen = isc_buffer_getuint16(&j->it.source);
2044
2045 /*
2046 * Parse the rdata.
2047 */
15. Condition j->it.source.used - j->it.source.current != rdlen, taking false branch.
2048 if (isc_buffer_remaininglength(&j->it.source) != rdlen) {
2049 FAIL(DNS_R_FORMERR);
2050 }
16. var_assign_var: Assigning: j->it.source.active = j->it.source.current + rdlen. Both are now tainted.
2051 isc_buffer_setactive(&j->it.source, rdlen);
2052 dns_rdata_reset(&j->it.rdata);
17. lower_bounds: Checking lower bounds of unsigned scalar j->it.source.active by taking the true branch of j->it.source.active > j->it.source.current.
CID 316506 (#1 of 1): Untrusted loop bound (TAINTED_SCALAR)
18. tainted_data: Passing tainted expression j->it.source.active to dns_rdata_fromwire, which uses it as a loop boundary. [show details]
Ensure that tainted values are properly sanitized, by checking that their values are within a permissible range.
2053 CHECK(dns_rdata_fromwire(&j->it.rdata, rdclass, rdtype, &j->it.source,
2054 &j->it.dctx, 0, &j->it.target));
2021-07-07 14:08:04 +10:00
|
|
|
if (rdlen > DNS_RDATA_MAXLENGTH) {
|
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS, ISC_LOG_ERROR,
|
|
|
|
"%s: journal corrupt: impossible rdlen "
|
|
|
|
"(%u bytes)",
|
|
|
|
j->filename, rdlen);
|
|
|
|
FAIL(ISC_R_FAILURE);
|
|
|
|
}
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
/*
|
|
|
|
* Parse the rdata.
|
|
|
|
*/
|
2007-09-07 05:14:33 +00:00
|
|
|
if (isc_buffer_remaininglength(&j->it.source) != rdlen) {
|
|
|
|
FAIL(DNS_R_FORMERR);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-08-20 05:26:49 +00:00
|
|
|
isc_buffer_setactive(&j->it.source, rdlen);
|
2000-10-31 03:22:05 +00:00
|
|
|
dns_rdata_reset(&j->it.rdata);
|
1999-08-20 05:26:49 +00:00
|
|
|
CHECK(dns_rdata_fromwire(&j->it.rdata, rdclass, rdtype, &j->it.source,
|
2022-11-09 17:10:59 +00:00
|
|
|
j->it.dctx, &j->it.target));
|
1999-08-20 05:26:49 +00:00
|
|
|
j->it.ttl = ttl;
|
|
|
|
|
|
|
|
j->it.xpos += sizeof(journal_rawrrhdr_t) + rrhdr.size;
|
|
|
|
if (rdtype == dns_rdatatype_soa) {
|
|
|
|
/* XXX could do additional consistency checks here */
|
|
|
|
j->it.current_serial = dns_soa_getserial(&j->it.rdata);
|
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
1999-08-20 05:26:49 +00:00
|
|
|
|
|
|
|
failure:
|
|
|
|
j->it.result = result;
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_journal_next_rr(dns_journal_t *j) {
|
2021-05-13 15:44:02 +10:00
|
|
|
j->it.result = read_one_rr(j);
|
1999-08-20 05:26:49 +00:00
|
|
|
return (j->it.result);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2018-03-28 14:19:37 +02:00
|
|
|
dns_journal_current_rr(dns_journal_t *j, dns_name_t **name, uint32_t *ttl,
|
1999-08-20 05:26:49 +00:00
|
|
|
dns_rdata_t **rdata) {
|
2000-04-06 22:03:35 +00:00
|
|
|
REQUIRE(j->it.result == ISC_R_SUCCESS);
|
1999-08-20 05:26:49 +00:00
|
|
|
*name = &j->it.name;
|
|
|
|
*ttl = j->it.ttl;
|
|
|
|
*rdata = &j->it.rdata;
|
|
|
|
}
|
1999-09-27 06:30:15 +00:00
|
|
|
|
|
|
|
/**************************************************************************/
|
|
|
|
/*
|
|
|
|
* Generating diffs from databases
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Construct a diff containing all the RRs at the current name of the
|
|
|
|
* database iterator 'dbit' in database 'db', version 'ver'.
|
|
|
|
* Set '*name' to the current name, and append the diff to 'diff'.
|
|
|
|
* All new tuples will have the operation 'op'.
|
|
|
|
*
|
|
|
|
* Requires: 'name' must have buffer large enough to hold the name.
|
|
|
|
* Typically, a dns_fixedname_t would be used.
|
|
|
|
*/
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
1999-09-27 06:30:15 +00:00
|
|
|
get_name_diff(dns_db_t *db, dns_dbversion_t *ver, isc_stdtime_t now,
|
|
|
|
dns_dbiterator_t *dbit, dns_name_t *name, dns_diffop_t op,
|
|
|
|
dns_diff_t *diff) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-09-27 06:30:15 +00:00
|
|
|
dns_dbnode_t *node = NULL;
|
|
|
|
dns_rdatasetiter_t *rdsiter = NULL;
|
|
|
|
dns_difftuple_t *tuple = NULL;
|
|
|
|
|
|
|
|
result = dns_dbiterator_current(dbit, &node, name);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-09-27 06:30:15 +00:00
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2022-11-16 10:47:40 +11:00
|
|
|
result = dns_db_allrdatasets(db, node, ver, 0, now, &rdsiter);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-09-27 06:30:15 +00:00
|
|
|
goto cleanup_node;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-27 06:30:15 +00:00
|
|
|
|
|
|
|
for (result = dns_rdatasetiter_first(rdsiter); result == ISC_R_SUCCESS;
|
|
|
|
result = dns_rdatasetiter_next(rdsiter))
|
|
|
|
{
|
|
|
|
dns_rdataset_t rdataset;
|
|
|
|
|
|
|
|
dns_rdataset_init(&rdataset);
|
|
|
|
dns_rdatasetiter_current(rdsiter, &rdataset);
|
|
|
|
|
|
|
|
for (result = dns_rdataset_first(&rdataset);
|
2000-04-06 22:03:35 +00:00
|
|
|
result == ISC_R_SUCCESS;
|
1999-09-27 06:30:15 +00:00
|
|
|
result = dns_rdataset_next(&rdataset))
|
|
|
|
{
|
2000-10-25 04:26:57 +00:00
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
1999-09-27 06:30:15 +00:00
|
|
|
dns_rdataset_current(&rdataset, &rdata);
|
|
|
|
result = dns_difftuple_create(diff->mctx, op, name,
|
|
|
|
rdataset.ttl, &rdata,
|
|
|
|
&tuple);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
1999-09-27 06:30:15 +00:00
|
|
|
dns_rdataset_disassociate(&rdataset);
|
|
|
|
goto cleanup_iterator;
|
|
|
|
}
|
|
|
|
dns_diff_append(diff, &tuple);
|
|
|
|
}
|
|
|
|
dns_rdataset_disassociate(&rdataset);
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_NOMORE) {
|
1999-09-27 06:30:15 +00:00
|
|
|
goto cleanup_iterator;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-27 06:30:15 +00:00
|
|
|
}
|
2000-04-06 22:03:35 +00:00
|
|
|
if (result != ISC_R_NOMORE) {
|
1999-09-27 06:30:15 +00:00
|
|
|
goto cleanup_iterator;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
1999-09-27 06:30:15 +00:00
|
|
|
|
|
|
|
cleanup_iterator:
|
|
|
|
dns_rdatasetiter_destroy(&rdsiter);
|
|
|
|
|
|
|
|
cleanup_node:
|
|
|
|
dns_db_detachnode(db, &node);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Comparison function for use by dns_diff_subtract when sorting
|
|
|
|
* the diffs to be subtracted. The sort keys are the rdata type
|
|
|
|
* and the rdata itself. The owner name is ignored, because
|
|
|
|
* it is known to be the same for all tuples.
|
|
|
|
*/
|
|
|
|
static int
|
2000-05-08 14:38:29 +00:00
|
|
|
rdata_order(const void *av, const void *bv) {
|
2001-01-24 07:12:56 +00:00
|
|
|
dns_difftuple_t const *const *ap = av;
|
|
|
|
dns_difftuple_t const *const *bp = bv;
|
|
|
|
dns_difftuple_t const *a = *ap;
|
|
|
|
dns_difftuple_t const *b = *bp;
|
1999-09-27 06:30:15 +00:00
|
|
|
int r;
|
|
|
|
r = (b->rdata.type - a->rdata.type);
|
|
|
|
if (r != 0) {
|
|
|
|
return (r);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-27 06:30:15 +00:00
|
|
|
r = dns_rdata_compare(&a->rdata, &b->rdata);
|
|
|
|
return (r);
|
|
|
|
}
|
|
|
|
|
1999-12-23 00:09:04 +00:00
|
|
|
static isc_result_t
|
2000-05-08 14:38:29 +00:00
|
|
|
dns_diff_subtract(dns_diff_t diff[2], dns_diff_t *r) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result;
|
1999-09-27 06:30:15 +00:00
|
|
|
dns_difftuple_t *p[2];
|
|
|
|
int i, t;
|
2018-04-17 08:29:14 -07:00
|
|
|
bool append;
|
2021-07-20 08:46:32 +10:00
|
|
|
dns_difftuplelist_t add, del;
|
2005-06-07 02:02:05 +00:00
|
|
|
|
1999-09-27 06:30:15 +00:00
|
|
|
CHECK(dns_diff_sort(&diff[0], rdata_order));
|
|
|
|
CHECK(dns_diff_sort(&diff[1], rdata_order));
|
2021-07-20 08:46:32 +10:00
|
|
|
ISC_LIST_INIT(add);
|
|
|
|
ISC_LIST_INIT(del);
|
1999-09-27 06:30:15 +00:00
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
p[0] = ISC_LIST_HEAD(diff[0].tuples);
|
|
|
|
p[1] = ISC_LIST_HEAD(diff[1].tuples);
|
|
|
|
if (p[0] == NULL && p[1] == NULL) {
|
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2020-02-13 18:16:57 +01:00
|
|
|
for (i = 0; i < 2; i++) {
|
1999-09-27 06:30:15 +00:00
|
|
|
if (p[!i] == NULL) {
|
2021-07-20 08:46:32 +10:00
|
|
|
dns_difftuplelist_t *l = (i == 0) ? &add : &del;
|
|
|
|
ISC_LIST_UNLINK(diff[i].tuples, p[i], link);
|
|
|
|
ISC_LIST_APPEND(*l, p[i], link);
|
|
|
|
goto next;
|
1999-09-27 06:30:15 +00:00
|
|
|
}
|
2020-02-13 18:16:57 +01:00
|
|
|
}
|
1999-09-27 06:30:15 +00:00
|
|
|
t = rdata_order(&p[0], &p[1]);
|
|
|
|
if (t < 0) {
|
|
|
|
ISC_LIST_UNLINK(diff[0].tuples, p[0], link);
|
2021-07-20 08:46:32 +10:00
|
|
|
ISC_LIST_APPEND(add, p[0], link);
|
1999-09-27 06:30:15 +00:00
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
if (t > 0) {
|
|
|
|
ISC_LIST_UNLINK(diff[1].tuples, p[1], link);
|
2021-07-20 08:46:32 +10:00
|
|
|
ISC_LIST_APPEND(del, p[1], link);
|
1999-09-27 06:30:15 +00:00
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
INSIST(t == 0);
|
2000-05-25 03:41:12 +00:00
|
|
|
/*
|
2005-06-07 02:02:05 +00:00
|
|
|
* Identical RRs in both databases; skip them both
|
|
|
|
* if the ttl differs.
|
2000-05-25 03:41:12 +00:00
|
|
|
*/
|
2018-04-17 08:29:14 -07:00
|
|
|
append = (p[0]->ttl != p[1]->ttl);
|
1999-09-27 06:30:15 +00:00
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
ISC_LIST_UNLINK(diff[i].tuples, p[i], link);
|
2005-06-07 02:02:05 +00:00
|
|
|
if (append) {
|
2021-07-20 08:46:32 +10:00
|
|
|
dns_difftuplelist_t *l = (i == 0) ? &add : &del;
|
|
|
|
ISC_LIST_APPEND(*l, p[i], link);
|
2005-06-07 02:02:05 +00:00
|
|
|
} else {
|
|
|
|
dns_difftuple_free(&p[i]);
|
|
|
|
}
|
1999-09-27 06:30:15 +00:00
|
|
|
}
|
|
|
|
next:;
|
|
|
|
}
|
2021-07-20 08:46:32 +10:00
|
|
|
ISC_LIST_APPENDLIST(r->tuples, del, link);
|
|
|
|
ISC_LIST_APPENDLIST(r->tuples, add, link);
|
1999-09-27 06:30:15 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
failure:
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
2009-11-04 03:46:44 +00:00
|
|
|
static isc_result_t
|
2011-12-04 23:48:12 +00:00
|
|
|
diff_namespace(dns_db_t *dba, dns_dbversion_t *dbvera, dns_db_t *dbb,
|
2009-11-04 03:46:44 +00:00
|
|
|
dns_dbversion_t *dbverb, unsigned int options,
|
|
|
|
dns_diff_t *resultdiff) {
|
1999-09-27 06:30:15 +00:00
|
|
|
dns_db_t *db[2];
|
|
|
|
dns_dbversion_t *ver[2];
|
|
|
|
dns_dbiterator_t *dbit[2] = { NULL, NULL };
|
2018-04-17 08:29:14 -07:00
|
|
|
bool have[2] = { false, false };
|
1999-09-27 06:30:15 +00:00
|
|
|
dns_fixedname_t fixname[2];
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result, itresult[2];
|
2009-11-04 03:46:44 +00:00
|
|
|
dns_diff_t diff[2];
|
1999-09-27 06:30:15 +00:00
|
|
|
int i, t;
|
|
|
|
|
|
|
|
db[0] = dba, db[1] = dbb;
|
|
|
|
ver[0] = dbvera, ver[1] = dbverb;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2011-12-04 23:48:12 +00:00
|
|
|
dns_diff_init(resultdiff->mctx, &diff[0]);
|
|
|
|
dns_diff_init(resultdiff->mctx, &diff[1]);
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-09-27 06:30:15 +00:00
|
|
|
dns_fixedname_init(&fixname[0]);
|
|
|
|
dns_fixedname_init(&fixname[1]);
|
|
|
|
|
2009-11-04 03:46:44 +00:00
|
|
|
result = dns_db_createiterator(db[0], options, &dbit[0]);
|
2004-05-14 05:08:00 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2009-11-04 03:46:44 +00:00
|
|
|
result = dns_db_createiterator(db[1], options, &dbit[1]);
|
2004-05-14 05:08:00 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2009-11-04 04:22:16 +00:00
|
|
|
goto cleanup_iterator;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-27 06:30:15 +00:00
|
|
|
|
|
|
|
itresult[0] = dns_dbiterator_first(dbit[0]);
|
|
|
|
itresult[1] = dns_dbiterator_first(dbit[1]);
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
for (i = 0; i < 2; i++) {
|
2000-04-06 22:03:35 +00:00
|
|
|
if (!have[i] && itresult[i] == ISC_R_SUCCESS) {
|
1999-09-27 06:30:15 +00:00
|
|
|
CHECK(get_name_diff(
|
|
|
|
db[i], ver[i], 0, dbit[i],
|
|
|
|
dns_fixedname_name(&fixname[i]),
|
|
|
|
i == 0 ? DNS_DIFFOP_ADD
|
|
|
|
: DNS_DIFFOP_DEL,
|
|
|
|
&diff[i]));
|
|
|
|
itresult[i] = dns_dbiterator_next(dbit[i]);
|
2018-04-17 08:29:14 -07:00
|
|
|
have[i] = true;
|
1999-09-27 06:30:15 +00:00
|
|
|
}
|
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-09-27 06:30:15 +00:00
|
|
|
if (!have[0] && !have[1]) {
|
|
|
|
INSIST(ISC_LIST_EMPTY(diff[0].tuples));
|
|
|
|
INSIST(ISC_LIST_EMPTY(diff[1].tuples));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; i < 2; i++) {
|
|
|
|
if (!have[!i]) {
|
2009-11-04 03:46:44 +00:00
|
|
|
ISC_LIST_APPENDLIST(resultdiff->tuples,
|
1999-09-27 06:30:15 +00:00
|
|
|
diff[i].tuples, link);
|
|
|
|
INSIST(ISC_LIST_EMPTY(diff[i].tuples));
|
2018-04-17 08:29:14 -07:00
|
|
|
have[i] = false;
|
1999-09-27 06:30:15 +00:00
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
}
|
2000-08-01 01:33:37 +00:00
|
|
|
|
1999-09-27 06:30:15 +00:00
|
|
|
t = dns_name_compare(dns_fixedname_name(&fixname[0]),
|
|
|
|
dns_fixedname_name(&fixname[1]));
|
|
|
|
if (t < 0) {
|
2009-11-04 03:46:44 +00:00
|
|
|
ISC_LIST_APPENDLIST(resultdiff->tuples, diff[0].tuples,
|
1999-09-27 06:30:15 +00:00
|
|
|
link);
|
|
|
|
INSIST(ISC_LIST_EMPTY(diff[0].tuples));
|
2018-04-17 08:29:14 -07:00
|
|
|
have[0] = false;
|
1999-09-27 06:30:15 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (t > 0) {
|
2009-11-04 03:46:44 +00:00
|
|
|
ISC_LIST_APPENDLIST(resultdiff->tuples, diff[1].tuples,
|
1999-09-27 06:30:15 +00:00
|
|
|
link);
|
|
|
|
INSIST(ISC_LIST_EMPTY(diff[1].tuples));
|
2018-04-17 08:29:14 -07:00
|
|
|
have[1] = false;
|
1999-09-27 06:30:15 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
INSIST(t == 0);
|
2009-11-04 03:46:44 +00:00
|
|
|
CHECK(dns_diff_subtract(diff, resultdiff));
|
1999-09-27 06:30:15 +00:00
|
|
|
INSIST(ISC_LIST_EMPTY(diff[0].tuples));
|
|
|
|
INSIST(ISC_LIST_EMPTY(diff[1].tuples));
|
2018-04-17 08:29:14 -07:00
|
|
|
have[0] = have[1] = false;
|
1999-09-27 06:30:15 +00:00
|
|
|
next:;
|
|
|
|
}
|
2000-04-06 22:03:35 +00:00
|
|
|
if (itresult[0] != ISC_R_NOMORE) {
|
1999-09-27 06:30:15 +00:00
|
|
|
FAIL(itresult[0]);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-04-06 22:03:35 +00:00
|
|
|
if (itresult[1] != ISC_R_NOMORE) {
|
1999-09-27 06:30:15 +00:00
|
|
|
FAIL(itresult[1]);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-27 06:30:15 +00:00
|
|
|
|
2009-11-04 03:46:44 +00:00
|
|
|
INSIST(ISC_LIST_EMPTY(diff[0].tuples));
|
|
|
|
INSIST(ISC_LIST_EMPTY(diff[1].tuples));
|
|
|
|
|
|
|
|
failure:
|
|
|
|
dns_dbiterator_destroy(&dbit[1]);
|
2011-12-04 23:48:12 +00:00
|
|
|
|
2009-11-04 04:22:16 +00:00
|
|
|
cleanup_iterator:
|
2009-11-04 03:46:44 +00:00
|
|
|
dns_dbiterator_destroy(&dbit[0]);
|
2011-12-04 23:48:12 +00:00
|
|
|
dns_diff_clear(&diff[0]);
|
|
|
|
dns_diff_clear(&diff[1]);
|
2009-11-04 03:46:44 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Compare the databases 'dba' and 'dbb' and generate a journal
|
|
|
|
* entry containing the changes to make 'dba' from 'dbb' (note
|
|
|
|
* the order). This journal entry will consist of a single,
|
|
|
|
* possibly very large transaction.
|
|
|
|
*/
|
|
|
|
isc_result_t
|
2011-12-04 23:48:12 +00:00
|
|
|
dns_db_diff(isc_mem_t *mctx, dns_db_t *dba, dns_dbversion_t *dbvera,
|
|
|
|
dns_db_t *dbb, dns_dbversion_t *dbverb, const char *filename) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_diff_t diff;
|
2011-12-05 23:46:35 +00:00
|
|
|
|
2011-12-04 23:48:12 +00:00
|
|
|
dns_diff_init(mctx, &diff);
|
|
|
|
|
|
|
|
result = dns_db_diffx(&diff, dba, dbvera, dbb, dbverb, filename);
|
|
|
|
|
|
|
|
dns_diff_clear(&diff);
|
|
|
|
|
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
isc_result_t
|
|
|
|
dns_db_diffx(dns_diff_t *diff, dns_db_t *dba, dns_dbversion_t *dbvera,
|
|
|
|
dns_db_t *dbb, dns_dbversion_t *dbverb, const char *filename) {
|
2009-11-04 03:46:44 +00:00
|
|
|
isc_result_t result;
|
|
|
|
dns_journal_t *journal = NULL;
|
|
|
|
|
2011-12-04 23:48:12 +00:00
|
|
|
if (filename != NULL) {
|
2011-12-22 07:32:41 +00:00
|
|
|
result = dns_journal_open(diff->mctx, filename,
|
|
|
|
DNS_JOURNAL_CREATE, &journal);
|
2011-12-04 23:48:12 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2011-12-04 23:48:12 +00:00
|
|
|
}
|
2009-11-04 03:46:44 +00:00
|
|
|
|
2011-12-04 23:48:12 +00:00
|
|
|
CHECK(diff_namespace(dba, dbvera, dbb, dbverb, DNS_DB_NONSEC3, diff));
|
|
|
|
CHECK(diff_namespace(dba, dbvera, dbb, dbverb, DNS_DB_NSEC3ONLY, diff));
|
2009-11-04 03:46:44 +00:00
|
|
|
|
2011-12-04 23:48:12 +00:00
|
|
|
if (journal != NULL) {
|
|
|
|
if (ISC_LIST_EMPTY(diff->tuples)) {
|
|
|
|
isc_log_write(JOURNAL_DEBUG_LOGARGS(3), "no changes");
|
|
|
|
} else {
|
|
|
|
CHECK(dns_journal_write_transaction(journal, diff));
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-27 06:30:15 +00:00
|
|
|
}
|
2011-12-04 23:48:12 +00:00
|
|
|
|
1999-09-27 06:30:15 +00:00
|
|
|
failure:
|
2011-12-04 23:48:12 +00:00
|
|
|
if (journal != NULL) {
|
|
|
|
dns_journal_destroy(&journal);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-27 06:30:15 +00:00
|
|
|
return (result);
|
|
|
|
}
|
2001-08-30 05:04:18 +00:00
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
static uint32_t
|
2021-03-31 15:03:33 +11:00
|
|
|
rrcount(unsigned char *buf, unsigned int size) {
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
isc_buffer_t b;
|
|
|
|
uint32_t rrsize, count = 0;
|
|
|
|
|
|
|
|
isc_buffer_init(&b, buf, size);
|
|
|
|
isc_buffer_add(&b, size);
|
|
|
|
while (isc_buffer_remaininglength(&b) > 0) {
|
|
|
|
rrsize = isc_buffer_getuint32(&b);
|
|
|
|
INSIST(isc_buffer_remaininglength(&b) >= rrsize);
|
|
|
|
isc_buffer_forward(&b, rrsize);
|
|
|
|
count++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (count);
|
|
|
|
}
|
|
|
|
|
2021-03-31 15:03:33 +11:00
|
|
|
static bool
|
|
|
|
check_delta(unsigned char *buf, size_t size) {
|
|
|
|
isc_buffer_t b;
|
|
|
|
uint32_t rrsize;
|
|
|
|
|
|
|
|
isc_buffer_init(&b, buf, size);
|
|
|
|
isc_buffer_add(&b, size);
|
|
|
|
while (isc_buffer_remaininglength(&b) > 0) {
|
|
|
|
if (isc_buffer_remaininglength(&b) < 4) {
|
|
|
|
return (false);
|
|
|
|
}
|
|
|
|
rrsize = isc_buffer_getuint32(&b);
|
|
|
|
/* "." + type + class + ttl + rdlen => 11U */
|
|
|
|
if (rrsize < 11U || isc_buffer_remaininglength(&b) < rrsize) {
|
|
|
|
return (false);
|
|
|
|
}
|
|
|
|
isc_buffer_forward(&b, rrsize);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (true);
|
|
|
|
}
|
|
|
|
|
2001-08-30 05:04:18 +00:00
|
|
|
isc_result_t
|
2018-03-28 14:19:37 +02:00
|
|
|
dns_journal_compact(isc_mem_t *mctx, char *filename, uint32_t serial,
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
uint32_t flags, uint32_t target_size) {
|
2001-08-30 05:04:18 +00:00
|
|
|
unsigned int i;
|
|
|
|
journal_pos_t best_guess;
|
|
|
|
journal_pos_t current_pos;
|
2017-07-21 11:52:24 +10:00
|
|
|
dns_journal_t *j1 = NULL;
|
|
|
|
dns_journal_t *j2 = NULL;
|
2001-08-30 05:04:18 +00:00
|
|
|
journal_rawheader_t rawheader;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
unsigned int len;
|
2013-12-04 12:47:23 +11:00
|
|
|
size_t namelen;
|
2021-03-31 15:03:33 +11:00
|
|
|
unsigned char *buf = NULL;
|
2001-08-30 05:04:18 +00:00
|
|
|
unsigned int size = 0;
|
|
|
|
isc_result_t result;
|
|
|
|
unsigned int indexend;
|
2018-03-21 16:38:29 +00:00
|
|
|
char newname[PATH_MAX];
|
|
|
|
char backup[PATH_MAX];
|
2018-04-17 08:29:14 -07:00
|
|
|
bool is_backup = false;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
bool rewrite = false;
|
2021-03-03 17:07:15 +11:00
|
|
|
bool downgrade = false;
|
2007-08-30 05:08:42 +00:00
|
|
|
|
2015-05-28 13:17:07 +10:00
|
|
|
REQUIRE(filename != NULL);
|
|
|
|
|
2007-09-02 23:02:53 +00:00
|
|
|
namelen = strlen(filename);
|
2018-03-21 16:38:29 +00:00
|
|
|
if (namelen > 4U && strcmp(filename + namelen - 4, ".jnl") == 0) {
|
2007-09-02 23:02:53 +00:00
|
|
|
namelen -= 4;
|
2018-03-21 16:38:29 +00:00
|
|
|
}
|
2007-08-30 05:08:42 +00:00
|
|
|
|
2018-03-21 16:38:29 +00:00
|
|
|
result = snprintf(newname, sizeof(newname), "%.*s.jnw", (int)namelen,
|
|
|
|
filename);
|
|
|
|
RUNTIME_CHECK(result < sizeof(newname));
|
2007-08-30 05:08:42 +00:00
|
|
|
|
2018-03-21 16:38:29 +00:00
|
|
|
result = snprintf(backup, sizeof(backup), "%.*s.jbk", (int)namelen,
|
|
|
|
filename);
|
|
|
|
RUNTIME_CHECK(result < sizeof(backup));
|
2001-08-30 05:04:18 +00:00
|
|
|
|
2021-03-03 17:07:15 +11:00
|
|
|
result = journal_open(mctx, filename, false, false, false, &j1);
|
2007-08-30 05:08:42 +00:00
|
|
|
if (result == ISC_R_NOTFOUND) {
|
2018-04-17 08:29:14 -07:00
|
|
|
is_backup = true;
|
2021-03-03 17:07:15 +11:00
|
|
|
result = journal_open(mctx, backup, false, false, false, &j1);
|
2007-08-30 05:08:42 +00:00
|
|
|
}
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return (result);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-30 05:04:18 +00:00
|
|
|
|
2021-05-04 17:22:56 +10:00
|
|
|
/*
|
|
|
|
* Always perform a re-write when processing a version 1 journal.
|
|
|
|
*/
|
|
|
|
rewrite = j1->header_ver1;
|
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
/*
|
|
|
|
* Check whether we need to rewrite the whole journal
|
|
|
|
* file (for example, to upversion it).
|
|
|
|
*/
|
|
|
|
if ((flags & DNS_JOURNAL_COMPACTALL) != 0) {
|
2021-03-03 17:07:15 +11:00
|
|
|
if ((flags & DNS_JOURNAL_VERSION1) != 0) {
|
|
|
|
downgrade = true;
|
|
|
|
}
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
rewrite = true;
|
|
|
|
serial = dns_journal_first_serial(j1);
|
|
|
|
} else if (JOURNAL_EMPTY(&j1->header)) {
|
2017-07-21 11:52:24 +10:00
|
|
|
dns_journal_destroy(&j1);
|
2001-08-30 05:04:18 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
2008-04-01 23:47:10 +00:00
|
|
|
|
2017-07-21 11:52:24 +10:00
|
|
|
if (DNS_SERIAL_GT(j1->header.begin.serial, serial) ||
|
|
|
|
DNS_SERIAL_GT(serial, j1->header.end.serial))
|
|
|
|
{
|
|
|
|
dns_journal_destroy(&j1);
|
2001-08-30 05:04:18 +00:00
|
|
|
return (ISC_R_RANGE);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Cope with very small target sizes.
|
|
|
|
*/
|
|
|
|
indexend = sizeof(journal_rawheader_t) +
|
2023-08-23 10:00:12 +02:00
|
|
|
ISC_CHECKED_MUL(j1->header.index_size,
|
|
|
|
sizeof(journal_rawpos_t));
|
2017-05-02 13:23:08 -07:00
|
|
|
if (target_size < DNS_JOURNAL_SIZE_MIN) {
|
|
|
|
target_size = DNS_JOURNAL_SIZE_MIN;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-30 05:04:18 +00:00
|
|
|
if (target_size < indexend * 2) {
|
|
|
|
target_size = target_size / 2 + indexend;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-30 05:04:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* See if there is any work to do.
|
|
|
|
*/
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
if (!rewrite && (uint32_t)j1->header.end.offset < target_size) {
|
2017-07-21 11:52:24 +10:00
|
|
|
dns_journal_destroy(&j1);
|
2001-08-30 05:04:18 +00:00
|
|
|
return (ISC_R_SUCCESS);
|
|
|
|
}
|
2007-08-30 05:08:42 +00:00
|
|
|
|
2021-03-03 17:07:15 +11:00
|
|
|
CHECK(journal_open(mctx, newname, true, true, downgrade, &j2));
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
CHECK(journal_seek(j2, indexend));
|
2008-04-01 23:47:10 +00:00
|
|
|
|
2001-08-30 05:04:18 +00:00
|
|
|
/*
|
|
|
|
* Remove overhead so space test below can succeed.
|
|
|
|
*/
|
|
|
|
if (target_size >= indexend) {
|
|
|
|
target_size -= indexend;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-30 05:04:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Find if we can create enough free space.
|
|
|
|
*/
|
2017-07-21 11:52:24 +10:00
|
|
|
best_guess = j1->header.begin;
|
|
|
|
for (i = 0; i < j1->header.index_size; i++) {
|
|
|
|
if (POS_VALID(j1->index[i]) &&
|
|
|
|
DNS_SERIAL_GE(serial, j1->index[i].serial) &&
|
2018-03-28 14:19:37 +02:00
|
|
|
((uint32_t)(j1->header.end.offset - j1->index[i].offset) >=
|
2001-09-04 04:14:31 +00:00
|
|
|
target_size / 2) &&
|
2017-07-21 11:52:24 +10:00
|
|
|
j1->index[i].offset > best_guess.offset)
|
|
|
|
{
|
|
|
|
best_guess = j1->index[i];
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-30 05:04:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
current_pos = best_guess;
|
|
|
|
while (current_pos.serial != serial) {
|
2021-05-13 15:44:02 +10:00
|
|
|
CHECK(journal_next(j1, ¤t_pos));
|
2017-07-21 11:52:24 +10:00
|
|
|
if (current_pos.serial == j1->header.end.serial) {
|
2001-08-30 05:04:18 +00:00
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-30 05:04:18 +00:00
|
|
|
|
|
|
|
if (DNS_SERIAL_GE(serial, current_pos.serial) &&
|
2018-03-28 14:19:37 +02:00
|
|
|
((uint32_t)(j1->header.end.offset - current_pos.offset) >=
|
2001-09-04 04:14:31 +00:00
|
|
|
(target_size / 2)) &&
|
2001-08-30 05:04:18 +00:00
|
|
|
current_pos.offset > best_guess.offset)
|
|
|
|
{
|
|
|
|
best_guess = current_pos;
|
|
|
|
} else {
|
|
|
|
break;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-30 05:04:18 +00:00
|
|
|
}
|
|
|
|
|
2017-07-21 11:52:24 +10:00
|
|
|
INSIST(best_guess.serial != j1->header.end.serial);
|
2001-08-30 05:04:18 +00:00
|
|
|
if (best_guess.serial != serial) {
|
2021-05-13 15:44:02 +10:00
|
|
|
CHECK(journal_next(j1, &best_guess));
|
2021-05-04 17:22:56 +10:00
|
|
|
serial = best_guess.serial;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-30 05:04:18 +00:00
|
|
|
|
|
|
|
/*
|
2007-08-30 05:08:42 +00:00
|
|
|
* We should now be roughly half target_size provided
|
|
|
|
* we did not reach 'serial'. If not we will just copy
|
|
|
|
* all uncommitted deltas regardless of the size.
|
2001-08-30 05:04:18 +00:00
|
|
|
*/
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
len = j1->header.end.offset - best_guess.offset;
|
|
|
|
if (len != 0) {
|
|
|
|
CHECK(journal_seek(j1, best_guess.offset));
|
|
|
|
|
|
|
|
/* Prepare new header */
|
|
|
|
j2->header.begin.serial = best_guess.serial;
|
|
|
|
j2->header.begin.offset = indexend;
|
|
|
|
j2->header.sourceserial = j1->header.sourceserial;
|
|
|
|
j2->header.serialset = j1->header.serialset;
|
|
|
|
j2->header.end.serial = j1->header.end.serial;
|
2001-08-30 05:04:18 +00:00
|
|
|
|
|
|
|
/*
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
* Only use this method if we're rewriting the
|
|
|
|
* journal to fix outdated transaction headers;
|
|
|
|
* otherwise we'll copy the whole journal without
|
|
|
|
* parsing individual deltas below.
|
2001-08-30 05:04:18 +00:00
|
|
|
*/
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
while (rewrite && len > 0) {
|
|
|
|
journal_xhdr_t xhdr;
|
2022-12-16 11:47:40 +00:00
|
|
|
off_t offset = j1->offset;
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
uint32_t count;
|
2008-04-01 23:47:10 +00:00
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
result = journal_read_xhdr(j1, &xhdr);
|
|
|
|
if (rewrite && result == ISC_R_NOMORE) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
CHECK(result);
|
2001-08-30 05:04:18 +00:00
|
|
|
|
2021-03-31 15:03:33 +11:00
|
|
|
size = xhdr.size;
|
2021-07-07 12:09:31 +10:00
|
|
|
if (size > len) {
|
|
|
|
isc_log_write(JOURNAL_COMMON_LOGARGS,
|
|
|
|
ISC_LOG_ERROR,
|
|
|
|
"%s: journal file corrupt, "
|
|
|
|
"transaction too large",
|
|
|
|
j1->filename);
|
|
|
|
CHECK(ISC_R_FAILURE);
|
|
|
|
}
|
2021-03-31 15:03:33 +11:00
|
|
|
buf = isc_mem_get(mctx, size);
|
|
|
|
result = journal_read(j1, buf, size);
|
|
|
|
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
/*
|
|
|
|
* If we're repairing an outdated journal, the
|
|
|
|
* xhdr format may be wrong.
|
|
|
|
*/
|
2021-03-31 15:03:33 +11:00
|
|
|
if (rewrite && (result != ISC_R_SUCCESS ||
|
2022-11-02 19:33:14 +01:00
|
|
|
!check_delta(buf, size)))
|
|
|
|
{
|
2021-03-31 15:03:33 +11:00
|
|
|
if (j1->xhdr_version == XHDR_VERSION2) {
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
/* XHDR_VERSION2 -> XHDR_VERSION1 */
|
|
|
|
j1->xhdr_version = XHDR_VERSION1;
|
|
|
|
CHECK(journal_seek(j1, offset));
|
|
|
|
CHECK(journal_read_xhdr(j1, &xhdr));
|
2021-03-31 15:03:33 +11:00
|
|
|
} else if (j1->xhdr_version == XHDR_VERSION1) {
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
/* XHDR_VERSION1 -> XHDR_VERSION2 */
|
|
|
|
j1->xhdr_version = XHDR_VERSION2;
|
|
|
|
CHECK(journal_seek(j1, offset));
|
|
|
|
CHECK(journal_read_xhdr(j1, &xhdr));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check again */
|
2021-03-31 15:03:33 +11:00
|
|
|
isc_mem_put(mctx, buf, size);
|
|
|
|
size = xhdr.size;
|
2021-07-07 12:09:31 +10:00
|
|
|
if (size > len) {
|
|
|
|
isc_log_write(
|
|
|
|
JOURNAL_COMMON_LOGARGS,
|
|
|
|
ISC_LOG_ERROR,
|
|
|
|
"%s: journal file corrupt, "
|
|
|
|
"transaction too large",
|
|
|
|
j1->filename);
|
|
|
|
CHECK(ISC_R_FAILURE);
|
|
|
|
}
|
2021-03-31 15:03:33 +11:00
|
|
|
buf = isc_mem_get(mctx, size);
|
|
|
|
CHECK(journal_read(j1, buf, size));
|
|
|
|
|
|
|
|
if (!check_delta(buf, size)) {
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
CHECK(ISC_R_UNEXPECTED);
|
|
|
|
}
|
2021-03-31 15:03:33 +11:00
|
|
|
} else {
|
|
|
|
CHECK(result);
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
}
|
|
|
|
|
2021-03-31 15:03:33 +11:00
|
|
|
/*
|
|
|
|
* Recover from incorrectly written transaction header.
|
|
|
|
* The incorrect header was written as size, serial0,
|
|
|
|
* serial1, and 0. XHDR_VERSION2 is expecting size,
|
|
|
|
* count, serial0, and serial1.
|
|
|
|
*/
|
|
|
|
if (j1->xhdr_version == XHDR_VERSION2 &&
|
|
|
|
xhdr.count == serial && xhdr.serial1 == 0U &&
|
2021-05-11 16:39:41 +10:00
|
|
|
isc_serial_gt(xhdr.serial0, xhdr.count))
|
2021-03-31 15:03:33 +11:00
|
|
|
{
|
|
|
|
xhdr.serial1 = xhdr.serial0;
|
|
|
|
xhdr.serial0 = xhdr.count;
|
|
|
|
xhdr.count = 0;
|
|
|
|
}
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
|
2021-03-31 15:03:33 +11:00
|
|
|
/*
|
|
|
|
* Check that xhdr is consistent.
|
|
|
|
*/
|
|
|
|
if (xhdr.serial0 != serial ||
|
2022-11-02 19:33:14 +01:00
|
|
|
isc_serial_le(xhdr.serial1, xhdr.serial0))
|
|
|
|
{
|
2021-03-31 15:03:33 +11:00
|
|
|
CHECK(ISC_R_UNEXPECTED);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Extract record count from the transaction. This
|
|
|
|
* is needed when converting from XHDR_VERSION1 to
|
|
|
|
* XHDR_VERSION2, and when recovering from an
|
|
|
|
* incorrectly written XHDR_VERSION2.
|
|
|
|
*/
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
count = rrcount(buf, size);
|
|
|
|
CHECK(journal_write_xhdr(j2, xhdr.size, count,
|
|
|
|
xhdr.serial0, xhdr.serial1));
|
|
|
|
CHECK(journal_write(j2, buf, size));
|
|
|
|
|
|
|
|
j2->header.end.offset = j2->offset;
|
|
|
|
|
|
|
|
serial = xhdr.serial1;
|
|
|
|
|
|
|
|
len = j1->header.end.offset - j1->offset;
|
|
|
|
isc_mem_put(mctx, buf, size);
|
|
|
|
}
|
2001-08-30 05:04:18 +00:00
|
|
|
|
|
|
|
/*
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
* If we're not rewriting transaction headers, we can use
|
|
|
|
* this faster method instead.
|
2001-08-30 05:04:18 +00:00
|
|
|
*/
|
allow dns_journal_rollforward() to read old journal files
when the 'max-ixfr-ratio' option was added, journal transaction
headers were revised to include a count of RR's in each transaction.
this made it impossible to read old journal files after an upgrade.
this branch restores the ability to read version 1 transaction
headers. when rolling forward, printing journal contents, if
the wrong transaction header format is found, we can switch.
when dns_journal_rollforward() detects a version 1 transaction
header, it returns DNS_R_RECOVERABLE. this triggers zone_postload()
to force a rewrite of the journal file in the new format, and
also to schedule a dump of the zone database with minimal delay.
journal repair is done by dns_journal_compact(), which rewrites
the entire journal, ignoring 'max-journal-size'. journal size is
corrected later.
newly created journal files now have "BIND LOG V9.2" in their headers
instead of "BIND LOG V9". files with the new version string cannot be
read using the old transaction header format. note that this means
newly created journal files will be rejected by older versions of named.
named-journalprint now takes a "-x" option, causing it to print
transaction header information before each delta, including its
format version.
2021-02-19 15:04:50 -08:00
|
|
|
if (!rewrite) {
|
|
|
|
size = ISC_MIN(64 * 1024, len);
|
|
|
|
buf = isc_mem_get(mctx, size);
|
|
|
|
for (i = 0; i < len; i += size) {
|
|
|
|
unsigned int blob = ISC_MIN(size, len - i);
|
|
|
|
CHECK(journal_read(j1, buf, blob));
|
|
|
|
CHECK(journal_write(j2, buf, blob));
|
|
|
|
}
|
|
|
|
|
|
|
|
j2->header.end.offset = indexend + len;
|
|
|
|
}
|
|
|
|
|
|
|
|
CHECK(journal_fsync(j2));
|
2007-08-30 05:08:42 +00:00
|
|
|
|
2001-08-30 05:04:18 +00:00
|
|
|
/*
|
|
|
|
* Update the journal header.
|
|
|
|
*/
|
2017-07-21 11:52:24 +10:00
|
|
|
journal_header_encode(&j2->header, &rawheader);
|
|
|
|
CHECK(journal_seek(j2, 0));
|
|
|
|
CHECK(journal_write(j2, &rawheader, sizeof(rawheader)));
|
|
|
|
CHECK(journal_fsync(j2));
|
2001-08-30 05:04:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Build new index.
|
|
|
|
*/
|
2017-07-21 11:52:24 +10:00
|
|
|
current_pos = j2->header.begin;
|
|
|
|
while (current_pos.serial != j2->header.end.serial) {
|
|
|
|
index_add(j2, ¤t_pos);
|
2021-05-13 15:44:02 +10:00
|
|
|
CHECK(journal_next(j2, ¤t_pos));
|
2001-08-30 05:04:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Write index.
|
|
|
|
*/
|
2017-07-21 11:52:24 +10:00
|
|
|
CHECK(index_to_disk(j2));
|
|
|
|
CHECK(journal_fsync(j2));
|
2001-08-30 05:04:18 +00:00
|
|
|
|
2017-07-21 11:52:24 +10:00
|
|
|
indexend = j2->header.end.offset;
|
2011-03-11 06:11:27 +00:00
|
|
|
POST(indexend);
|
2001-08-30 05:04:18 +00:00
|
|
|
}
|
2010-11-17 00:27:54 +00:00
|
|
|
|
|
|
|
/*
|
2021-05-20 15:53:50 +02:00
|
|
|
* Close both journals before trying to rename files.
|
2010-11-17 00:27:54 +00:00
|
|
|
*/
|
2017-07-21 11:52:24 +10:00
|
|
|
dns_journal_destroy(&j1);
|
|
|
|
dns_journal_destroy(&j2);
|
2007-08-30 05:08:42 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* With a UFS file system this should just succeed and be atomic.
|
|
|
|
* Any IXFR outs will just continue and the old journal will be
|
|
|
|
* removed on final close.
|
|
|
|
*
|
2010-11-17 00:27:54 +00:00
|
|
|
* With MSDOS / NTFS we need to do a two stage rename, triggered
|
|
|
|
* by EEXIST. (If any IXFR's are running in other threads, however,
|
|
|
|
* this will fail, and the journal will not be compacted. But
|
|
|
|
* if so, hopefully they'll be finished by the next time we
|
|
|
|
* compact.)
|
2007-08-30 05:08:42 +00:00
|
|
|
*/
|
|
|
|
if (rename(newname, filename) == -1) {
|
2010-11-17 00:27:54 +00:00
|
|
|
if (errno == EEXIST && !is_backup) {
|
2007-08-30 05:08:42 +00:00
|
|
|
result = isc_file_remove(backup);
|
|
|
|
if (result != ISC_R_SUCCESS &&
|
2022-11-02 19:33:14 +01:00
|
|
|
result != ISC_R_FILENOTFOUND)
|
|
|
|
{
|
2007-08-30 05:08:42 +00:00
|
|
|
goto failure;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-08-30 05:08:42 +00:00
|
|
|
if (rename(filename, backup) == -1) {
|
|
|
|
goto maperrno;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-08-30 05:08:42 +00:00
|
|
|
if (rename(newname, filename) == -1) {
|
|
|
|
goto maperrno;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2007-08-30 05:08:42 +00:00
|
|
|
(void)isc_file_remove(backup);
|
|
|
|
} else {
|
|
|
|
maperrno:
|
|
|
|
result = ISC_R_FAILURE;
|
|
|
|
goto failure;
|
|
|
|
}
|
|
|
|
}
|
2008-04-01 23:47:10 +00:00
|
|
|
|
2001-08-30 05:04:18 +00:00
|
|
|
result = ISC_R_SUCCESS;
|
|
|
|
|
|
|
|
failure:
|
2007-08-30 05:08:42 +00:00
|
|
|
(void)isc_file_remove(newname);
|
2001-08-30 05:04:18 +00:00
|
|
|
if (buf != NULL) {
|
|
|
|
isc_mem_put(mctx, buf, size);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-07-21 11:52:24 +10:00
|
|
|
if (j1 != NULL) {
|
|
|
|
dns_journal_destroy(&j1);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2017-07-21 11:52:24 +10:00
|
|
|
if (j2 != NULL) {
|
|
|
|
dns_journal_destroy(&j2);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-30 05:04:18 +00:00
|
|
|
return (result);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
index_to_disk(dns_journal_t *j) {
|
|
|
|
isc_result_t result = ISC_R_SUCCESS;
|
|
|
|
|
|
|
|
if (j->header.index_size != 0) {
|
|
|
|
unsigned int i;
|
|
|
|
unsigned char *p;
|
|
|
|
unsigned int rawbytes;
|
|
|
|
|
2023-08-23 10:00:12 +02:00
|
|
|
rawbytes = ISC_CHECKED_MUL(j->header.index_size,
|
|
|
|
sizeof(journal_rawpos_t));
|
2001-08-30 05:04:18 +00:00
|
|
|
|
|
|
|
p = j->rawindex;
|
|
|
|
for (i = 0; i < j->header.index_size; i++) {
|
|
|
|
encode_uint32(j->index[i].serial, p);
|
|
|
|
p += 4;
|
|
|
|
encode_uint32(j->index[i].offset, p);
|
|
|
|
p += 4;
|
|
|
|
}
|
|
|
|
INSIST(p == j->rawindex + rawbytes);
|
|
|
|
|
2004-05-11 22:20:13 +00:00
|
|
|
CHECK(journal_seek(j, sizeof(journal_rawheader_t)));
|
2001-08-30 05:04:18 +00:00
|
|
|
CHECK(journal_write(j, j->rawindex, rawbytes));
|
|
|
|
}
|
|
|
|
failure:
|
|
|
|
return (result);
|
|
|
|
}
|