NetBSD/external/bsd/nsd/dist/ixfrcreate.c

1144 lines
31 KiB
C
Raw Permalink Normal View History

Import nsd-4.6.0; last import was nsd-4.3.5 23 June 2022: Wouter - Tag for 4.6.0rc1. It became 4.6.0 on 30 June 2022, and it continues with version 4.6.1. 17 June 2022: Wouter - Fix compilation with libev, without event_base_loopbreak. 16 June 2022: Wouter - Fix that the unit test verify_repat cleans up nsd on exit. - Fix to remove ixfrcreate.c asserts about uint16 within limits because of warnings from analyzers. 14 June 2022: Wouter - Fix compilation without libevent and compilation of nsd-mem. - Fix verify handler add of sigchld event for compilation without libevent. 3 June 2022: Wouter - Fix static analyzer reports on ixfrcreate temp file. - Fixup wrong ixfrcreate fread return check. 13 May 2022: Wouter - The code repo continues with version 4.5.1. 6 May 2022: Wouter - Merge PR #209: IXFR out This adds IXFR out functionality to NSD. NSD can copy IXFRs from upstream to downstream clients, or create IXFRs from zonefiles. The options store-ixfr: yes and create-ixfr: yes can be used to turn this on. Default is turned off. The options ixfr-number and ixfr-size can be used to tune the number of IXFR transfers and total data size stored. This is configured per zone, the IXFRs are served to the hosts that are allowed to perform zone transfers. And if TSIG is configured, signed with the same key. The content is stored to file if a zonefile is configured for the zone, in the zonefile.ixfr and zonefile.ixfr.2, .. files. They contain readable text format. The number of IXFRs is num.rixfr in statistics output, also per zone if per zone statistics are enabled. If offline, nsd-checkzone -i can create ixfr files. NSD already supports requesting IXFRs, this addition allows NSD to serve IXFR transfers to clients. NSD stops responding with NOTIMPL to IXFR requests, also for zones that do not have IXFR enabled. The clients gets a full zone reply or a status reply if the serial is up to date. - set version to 4.5.0 for feature change. - Tag for 4.5.0rc1 release. It became the 4.5.0 release on 13 May 2022. 14 April 2022: Wouter - Update cirrus script FreeBSD version. 25 March 2022: Wouter - Fix spelling error in comment in svcbparam_lookup_key. 2 March 2022: Wouter - Fix code analyzer zero divide warning. - Fix code analyzer large value with assertion. - Fix another code analyzer zero divide warning. - Fix code analyzer warning about uninitialized temp storage in loop. 10 February 2022: Wouter - Tag for 4.4.0rc1 release. This became 4.4.0 release on 17 Feb 2022, the code repository continues with version 4.4.1. 9 February 2022: Wouter - Fix unit tests for nds-control-setup exit code and the xfrd-tcp-max default. 7 February 2022: Wouter - Merge #207 Sync nsd-control-setup with unbound-control-setup to generate certificates with SANs. 28 January 2022: Wouter - Fix #206: build with --without-ssl fails. 27 January 2022: Wouter - current code branch continues as version 4.4.0, because of added feature. 26 January 2022: Wouter - Merge #193: Lower memory usage of the XFRD process by default. Instead of preallocating all elements, they are allocated when used. There are options for managing the memory usage, defaults are the same as before. xfrd-tcp-max sets the number of sockets for tcp connections that xfrd can make to download zone contents. And xfrd-tcp-pipeline the number of simultaneous transfers over the same connection. 12 January 2022: Wouter - Fix to document nsd-checkzone -p in the man page for nsd-checkzone. 7 January 2022: Wouter - Fix to change file mode before changing file owner for the nsd-control unix socket file. 3 January 2022: Wouter - Merge #204 from jonathangray: correct some spelling mistakes. 15 December 2021: Wouter - Fix #200: nsd-checkzone succeeds even with incorrect serial in SOA record. 2 December 2021: Wouter - Fix socket_partitioning unit test for FreeBSD. - Fix SVCB test to work around older dig with drill. - Fix unit test to not syslog setlogin failures. 1 December 2021: Wouter - Set up for branch for 4.3.9 release. This became release 4.3.9 on 9 Dec 2021 and included the changes until the SVCB fix on 2 dec 2021, but not the setlogin fix. The main branch continues as 4.3.10. - Fix unit tests for new answer-cookie default. 30 November 2021: Wouter - Fix to remove git tracking and ci information from release tarballs. 3 November 2021: Wouter - Fix #198: nsd-control reconfig core dump. 12 October 2021: Wouter - Tag for 4.3.8 release, from 4.3.8rc2. The main branch continues with version 4.3.9 in development. 7 October 2021: Wouter - Set default for answer-cookie to no. Because in server deployments with mixed server software, a default of yes causes issues. - Tag for 4.3.8rc2, includes the new answer-cookie default. 4 October 2021: Wouter - Tag for 4.3.8rc1. 29 September 2021: Wouter - Fix unit tests for svcb and xot to not touch the default zonelistfile. - Fix unit test for xot tertiary config for zonelistfile default. - Fix unit test for dns-cookies for no unshare, and allow-query for no IPv6 loopback. - Fix unit test allow query to check for IPv6. 22 September 2021: Wouter - Fix #194: Incorrect NSEC3 response for SOA query below delegation point. 13 September 2021: Wouter - Fix compile failure with openssl 1.0.2. 3 September 2021: Wouter - Fix not reachable annotation in radix_find_prefix_node. 31 August 2021: Willem - Fix #191: dname_parse_wire() returns fqdn wireformat length. 26 August 2021: Wouter - Fix #190: NSD returns 3 NSEC3 records for NODATA response. 23 August 2021: Wouter - Fix #189: nsd 4.3.7 crash answer_delegation: Assertion `query->delegation_rrset' failed. 17 August 2021: Wouter - Fix #188: NSD fails to build against openssl 1.1 on CentOS 7. - Fix sed script in ssldir split handling. 13 August 2021: Wouter - Merge #187: Support using system-wide crypto policies. 10 August 2021: Wouter - Merge #185 by cesarkuroiwa: Mutual TLS. - Fixes for #185: Document client-cert, client-key and client-key-pw in the man page. Fix yacc semicolon. Fix unused variable warning. Use strlcpy instead of strncpy. Fix spelling error in error printout. 2 August 2021: Wouter - Quieter tpkg/do-tests shell script with -q flag. - For #184: Note that all zones can be targeted by some nsd-control commands in the man page. 30 July 2021: Wouter - Move acx_nlnetlabs.m4 to version 41, with lib64 openssl dir check. - Fix to compile with OpenSSL 3.0.0beta2. - Fix configure detection of SSL_CTX_set_security_level. - Fix deprecated functions use from openssl 3.0.0beta2. 23 July 2021: Wouter - Fix free on shutdown of XoT SSL context. 22 July 2021: Wouter - tag 4.3.7 release, with the fixes between rc1 and this release. - main branch continues for 4.3.8. 20 July 2021: Wouter - Fix typo in xfrd-tcp.c. 15 July 2021: Wouter - tag for 4.3.7rc1. - Fix compile of cookies on FreeBSD without IPv6. - Fix for loop initial declaration for nonc99 compiler. 14 July 2021: Wouter - Fix truncate test for EDNS COOKIE making one less RR is added. - Attempt to fix gcc11 warning. 13 July 2021: Willem - Fixes for child server processes getting out of sync with the dnstap-collector process 13 July 2021: Willem - Interoperable DNS Cookies support as per RFC7873 and RFC9018 9 July 2021: Willem - Client side DNS Zone Transfer-over-TLS (XoT) support as per draft-ietf-dprive-xfr-over-tls 29 June 2021: Willem - Fix #168: Buffer overflow in the dname_to_string() function 14 June 2021: Wouter - Update configure nonblocking test to use host. 25 May 2021: Wouter - Fix #179: log notice and server-count. 21 May 2021: Wouter - Test code has -q option for quiet output. 17 May 2021: Wouter - Update the ACX_CHECK_NONBLOCKING_BROKEN test for the configure script. 7 May 2021: Wouter - Fix #176: please review Loglevel on missing zonefile. 6 May 2021: Wouter - Fix #174: NS Records below delegation are not ignored (nsd-checkzone also does not raise any issue). 4 May 2021: Wouter - Fix SVCB sort call sizeof to be the size of the elements sorted. 29 April 2021: Tom - Implement Syntax of SVCB and HTTPS RR type as per draft-ietf-dnsop-svcb-https 13 April 2021: Wouter - Fix for #128: Skip over sendmmsg invalid argument when port is zero. - Fix #171: Invalid negative response (NSEC3) after IXFR. - Fix to make nsec3_chain_find_prev return NULL if one nsec3 left. - remove debug settings from unit test. 9 April 2021: Wouter - Fix for #170: Fix build warnings when IPv6 is disabled. - Fix #170: Disabled IPv6 and DNSTAP enabled triggers a build error. 30 March 2021: Wouter - Fix configure failure for enable systemd because of autoconf. - This became release 4.3.6, the repository continues for 4.3.7 in development. 29 March 2021: Wouter - Note unlisted changes in RELNOTES and prepare for 4.3.6rc1 tag. 29 March 2021: Willem - Per zone Access Control List for queries with an allow-query: option. 24 March 2021: Wouter - Update acx_nlnetlabs.m4 to version 38, fix deprecation test. - Fix configure to use header checks with compile. - Fix warning about unused function log_addr. 18 March 2021: Tom - Add Extended DNS Errors RFC8914 15 March 2021: Wouter - Fix double config.h include in configlexer.c - Fix to remove configyyrename from makedist.sh and also update the flex and bison rules there to add the "c_" prefix. 13 March 2021: Willem - Fix #154: TXT with parentheses fails in 4.3.5. - Align parsing of TXT elements with how bind does it. - A -p option to nsd-checkzone to print a successfully read zone. 12 March 2021: Wouter - Fix that wildcard is printed as a star instead of escaped, in logs and in written zone files. - Fix unit test for wildcard printout change. 11 March 2021: Wouter - Fix #163: A TSIG noncompliance with RFC 2845. 9 March 2021: Willem - Enable configuring a control-interface by interface name. 19 February 2021: Wouter - Fix segfault on high verbosity for TLS channels with dnstap log local address. 18 February 2021: Wouter - Fix #146 with #147: DNSTAP log the local address of the server with the dnstap logs. 16 February 2021: Wouter - Man page documentation for dnstap options. 8 February 2021: Wouter - Fix AF_LOCAL compile error for Solaris. - Fix ifaddrs compile error for Solaris. - Fix ifaddrs.h compile error for Solaris. 4 February 2021: Wouter - Merge PR #153 from fobser: Repair -fno-common linker errors automatically. - Fix uninitialized access of log_buf in error printout on apply ixfr. 26 January 2021: Wouter - Prevent a few more yacc clashes.
2022-09-24 20:35:00 +03:00
/*
* ixfrcreate.c -- generating IXFR differences from zone files.
*
* Copyright (c) 2021, NLnet Labs. All rights reserved.
*
* See LICENSE for the license.
*
*/
#include "config.h"
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include "ixfrcreate.h"
#include "namedb.h"
#include "ixfr.h"
#include "options.h"
/* spool a uint16_t to file */
static int spool_u16(FILE* out, uint16_t val)
{
if(!fwrite(&val, sizeof(val), 1, out)) {
return 0;
}
return 1;
}
/* spool a uint32_t to file */
static int spool_u32(FILE* out, uint32_t val)
{
if(!fwrite(&val, sizeof(val), 1, out)) {
return 0;
}
return 1;
}
/* spool dname to file */
static int spool_dname(FILE* out, dname_type* dname)
{
uint16_t namelen = dname->name_size;
if(!fwrite(&namelen, sizeof(namelen), 1, out)) {
return 0;
}
if(!fwrite(dname_name(dname), namelen, 1, out)) {
return 0;
}
return 1;
}
/* calculate the rdatalen of an RR */
static size_t rr_rdatalen_uncompressed(rr_type* rr)
{
int i;
size_t rdlen_uncompressed = 0;
for(i=0; i<rr->rdata_count; i++) {
if(rdata_atom_is_domain(rr->type, i)) {
rdlen_uncompressed += domain_dname(rr->rdatas[i].domain)
->name_size;
} else {
rdlen_uncompressed += rr->rdatas[i].data[0];
}
}
return rdlen_uncompressed;
}
/* spool the data for one rr into the file */
static int spool_rr_data(FILE* out, rr_type* rr)
{
int i;
uint16_t rdlen;
if(!spool_u32(out, rr->ttl))
return 0;
rdlen = rr_rdatalen_uncompressed(rr);
if(!spool_u16(out, rdlen))
return 0;
for(i=0; i<rr->rdata_count; i++) {
if(rdata_atom_is_domain(rr->type, i)) {
if(!fwrite(dname_name(domain_dname(
rr->rdatas[i].domain)), domain_dname(
rr->rdatas[i].domain)->name_size, 1, out))
return 0;
} else {
if(!fwrite(&rr->rdatas[i].data[1],
rr->rdatas[i].data[0], 1, out))
return 0;
}
}
return 1;
}
/* spool one rrset to file */
static int spool_rrset(FILE* out, rrset_type* rrset)
{
int i;
if(rrset->rr_count == 0)
return 1;
if(!spool_u16(out, rrset->rrs[0].type))
return 0;
if(!spool_u16(out, rrset->rrs[0].klass))
return 0;
if(!spool_u16(out, rrset->rr_count))
return 0;
for(i=0; i<rrset->rr_count; i++) {
if(!spool_rr_data(out, &rrset->rrs[i]))
return 0;
}
return 1;
}
/* spool rrsets to file */
static int spool_rrsets(FILE* out, rrset_type* rrsets, struct zone* zone)
{
rrset_type* s;
for(s=rrsets; s; s=s->next) {
if(s->zone != zone)
continue;
if(!spool_rrset(out, s)) {
return 0;
}
}
return 1;
}
/* count number of rrsets for a domain */
static size_t domain_count_rrsets(domain_type* domain, zone_type* zone)
{
rrset_type* s;
size_t count = 0;
for(s=domain->rrsets; s; s=s->next) {
if(s->zone == zone)
count++;
}
return count;
}
/* spool the domain names to file, each one in turn. end with enddelimiter */
static int spool_domains(FILE* out, struct zone* zone)
{
domain_type* domain;
for(domain = zone->apex; domain && domain_is_subdomain(domain,
zone->apex); domain = domain_next(domain)) {
uint32_t count = domain_count_rrsets(domain, zone);
if(count == 0)
continue;
/* write the name */
if(!spool_dname(out, domain_dname(domain)))
return 0;
if(!spool_u32(out, count))
return 0;
/* write the rrsets */
if(!spool_rrsets(out, domain->rrsets, zone))
return 0;
}
/* the end delimiter is a 0 length. domain names are not zero length */
if(!spool_u16(out, 0))
return 0;
return 1;
}
/* spool the namedb zone to the file. print error on failure. */
static int spool_zone_to_file(struct zone* zone, char* file_name,
uint32_t serial)
{
FILE* out;
out = fopen(file_name, "w");
if(!out) {
log_msg(LOG_ERR, "could not open %s for writing: %s",
file_name, strerror(errno));
return 0;
}
if(!spool_dname(out, domain_dname(zone->apex))) {
log_msg(LOG_ERR, "could not write %s: %s",
file_name, strerror(errno));
fclose(out);
return 0;
}
if(!spool_u32(out, serial)) {
log_msg(LOG_ERR, "could not write %s: %s",
file_name, strerror(errno));
fclose(out);
return 0;
}
if(!spool_domains(out, zone)) {
log_msg(LOG_ERR, "could not write %s: %s",
file_name, strerror(errno));
fclose(out);
return 0;
}
fclose(out);
return 1;
}
/* create ixfr spool file name */
static int create_ixfr_spool_name(struct ixfr_create* ixfrcr,
const char* zfile)
{
char buf[1024];
snprintf(buf, sizeof(buf), "%s.spoolzone.%u", zfile,
(unsigned)getpid());
ixfrcr->file_name = strdup(buf);
if(!ixfrcr->file_name)
return 0;
return 1;
}
/* start ixfr creation */
struct ixfr_create* ixfr_create_start(struct zone* zone, const char* zfile,
uint64_t ixfr_size, int errorcmdline)
{
struct ixfr_create* ixfrcr = (struct ixfr_create*)calloc(1,
sizeof(*ixfrcr));
if(!ixfrcr) {
log_msg(LOG_ERR, "malloc failure");
return NULL;
}
ixfrcr->zone_name_len = domain_dname(zone->apex)->name_size;
ixfrcr->zone_name = (uint8_t*)malloc(ixfrcr->zone_name_len);
if(!ixfrcr->zone_name) {
free(ixfrcr);
log_msg(LOG_ERR, "malloc failure");
return NULL;
}
memmove(ixfrcr->zone_name, dname_name(domain_dname(zone->apex)),
ixfrcr->zone_name_len);
if(!create_ixfr_spool_name(ixfrcr, zfile)) {
ixfr_create_free(ixfrcr);
log_msg(LOG_ERR, "malloc failure");
return NULL;
}
ixfrcr->old_serial = zone_get_current_serial(zone);
if(!spool_zone_to_file(zone, ixfrcr->file_name, ixfrcr->old_serial)) {
ixfr_create_free(ixfrcr);
return NULL;
}
if(zone->opts && zone->opts->pattern)
ixfrcr->max_size = (size_t)zone->opts->pattern->ixfr_size;
else ixfrcr->max_size = (size_t)ixfr_size;
ixfrcr->errorcmdline = errorcmdline;
return ixfrcr;
}
/* free ixfr create */
void ixfr_create_free(struct ixfr_create* ixfrcr)
{
if(!ixfrcr)
return;
free(ixfrcr->file_name);
free(ixfrcr->zone_name);
free(ixfrcr);
}
/* read uint16_t from spool */
static int read_spool_u16(FILE* spool, uint16_t* val)
{
if(fread(val, sizeof(*val), 1, spool) < 1)
return 0;
return 1;
}
/* read uint32_t from spool */
static int read_spool_u32(FILE* spool, uint32_t* val)
{
if(fread(val, sizeof(*val), 1, spool) < 1)
return 0;
return 1;
}
/* read dname from spool */
static int read_spool_dname(FILE* spool, uint8_t* buf, size_t buflen,
size_t* dname_len)
{
uint16_t len;
if(fread(&len, sizeof(len), 1, spool) < 1)
return 0;
if(len > buflen) {
log_msg(LOG_ERR, "dname too long");
return 0;
}
if(len > 0) {
if(fread(buf, len, 1, spool) < 1)
return 0;
}
*dname_len = len;
return 1;
}
/* read and check the spool file header */
static int read_spool_header(FILE* spool, struct ixfr_create* ixfrcr)
{
uint8_t dname[MAXDOMAINLEN+1];
size_t dname_len;
uint32_t serial;
/* read apex */
if(!read_spool_dname(spool, dname, sizeof(dname), &dname_len)) {
log_msg(LOG_ERR, "error reading file %s: %s",
ixfrcr->file_name, strerror(errno));
return 0;
}
/* read serial */
if(!read_spool_u32(spool, &serial)) {
log_msg(LOG_ERR, "error reading file %s: %s",
ixfrcr->file_name, strerror(errno));
return 0;
}
/* check */
if(ixfrcr->zone_name_len != dname_len ||
memcmp(ixfrcr->zone_name, dname, ixfrcr->zone_name_len) != 0) {
log_msg(LOG_ERR, "error file %s does not contain the correct zone apex",
ixfrcr->file_name);
return 0;
}
if(ixfrcr->old_serial != serial) {
log_msg(LOG_ERR, "error file %s does not contain the correct zone serial",
ixfrcr->file_name);
return 0;
}
return 1;
}
/* store the old soa record when we encounter it on the spool */
static int process_store_oldsoa(struct ixfr_store* store, uint8_t* dname,
size_t dname_len, uint16_t tp, uint16_t kl, uint32_t ttl, uint8_t* buf,
uint16_t rdlen)
{
if(store->data->oldsoa) {
log_msg(LOG_ERR, "error spool contains multiple SOA records");
return 0;
}
if(!ixfr_store_oldsoa_uncompressed(store, dname, dname_len, tp, kl,
ttl, buf, rdlen)) {
log_msg(LOG_ERR, "out of memory");
return 0;
}
return 1;
}
/* see if rdata matches, true if equal */
static int rdata_match(struct rr* rr, uint8_t* rdata, uint16_t rdlen)
{
size_t rdpos = 0;
int i;
for(i=0; i<rr->rdata_count; i++) {
if(rdata_atom_is_domain(rr->type, i)) {
if(rdpos + domain_dname(rr->rdatas[i].domain)->name_size
> rdlen)
return 0;
if(memcmp(rdata+rdpos,
dname_name(domain_dname(rr->rdatas[i].domain)),
domain_dname(rr->rdatas[i].domain)->name_size)
!= 0)
return 0;
rdpos += domain_dname(rr->rdatas[i].domain)->name_size;
} else {
if(rdpos + rr->rdatas[i].data[0] > rdlen)
return 0;
if(memcmp(rdata+rdpos, &rr->rdatas[i].data[1],
rr->rdatas[i].data[0]) != 0)
return 0;
rdpos += rr->rdatas[i].data[0];
}
}
if(rdpos != rdlen)
return 0;
return 1;
}
/* find an rdata in an rrset, true if found and sets index found */
static int rrset_find_rdata(struct rrset* rrset, uint32_t ttl, uint8_t* rdata,
uint16_t rdlen, uint16_t* index)
{
int i;
for(i=0; i<rrset->rr_count; i++) {
if(rrset->rrs[i].ttl != ttl)
continue;
if(rdata_match(&rrset->rrs[i], rdata, rdlen)) {
*index = i;
return 1;
}
}
return 0;
}
/* sort comparison for uint16 elements */
static int sort_uint16(const void* x, const void* y)
{
const uint16_t* ax = (const uint16_t*)x;
const uint16_t* ay = (const uint16_t*)y;
if(*ax < *ay)
return -1;
if(*ax > *ay)
return 1;
return 0;
}
/* spool read an rrset, it is a deleted RRset */
static int process_diff_rrset(FILE* spool, struct ixfr_create* ixfrcr,
struct ixfr_store* store, struct domain* domain,
uint16_t tp, uint16_t kl, uint16_t rrcount, struct rrset* rrset)
{
/* read RRs from file and see if they are added, deleted or in both */
uint8_t buf[MAX_RDLENGTH];
uint16_t marked[65536];
size_t marked_num = 0, atmarked;
int i;
for(i=0; i<rrcount; i++) {
uint16_t rdlen, index;
uint32_t ttl;
if(!read_spool_u32(spool, &ttl) ||
!read_spool_u16(spool, &rdlen)) {
log_msg(LOG_ERR, "error reading file %s: %s",
ixfrcr->file_name, strerror(errno));
return 0;
}
/* because rdlen is uint16_t always smaller than sizeof(buf)*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
assert(rdlen <= sizeof(buf));
#pragma GCC diagnostic pop
if(fread(buf, rdlen, 1, spool) < 1) {
log_msg(LOG_ERR, "error reading file %s: %s",
ixfrcr->file_name, strerror(errno));
return 0;
}
if(tp == TYPE_SOA) {
if(!process_store_oldsoa(store,
(void*)dname_name(domain_dname(domain)),
domain_dname(domain)->name_size, tp, kl, ttl,
buf, rdlen))
return 0;
}
/* see if the rr is in the RRset */
if(rrset_find_rdata(rrset, ttl, buf, rdlen, &index)) {
/* it is in both, mark it */
marked[marked_num++] = index;
} else {
/* not in new rrset, but only on spool, it is
* a deleted RR */
if(!ixfr_store_delrr_uncompressed(store,
(void*)dname_name(domain_dname(domain)),
domain_dname(domain)->name_size,
tp, kl, ttl, buf, rdlen)) {
log_msg(LOG_ERR, "out of memory");
return 0;
}
}
}
/* now that we are done, see if RRs in the rrset are not marked,
* and thus are new rrs that are added */
qsort(marked, marked_num, sizeof(marked[0]), &sort_uint16);
atmarked = 0;
for(i=0; i<rrset->rr_count; i++) {
if(atmarked < marked_num && marked[atmarked] == i) {
/* the item is in the marked list, skip it */
atmarked++;
continue;
}
/* not in the marked list, the RR is added */
if(!ixfr_store_addrr_rdatas(store, domain_dname(domain),
rrset->rrs[i].type, rrset->rrs[i].klass,
rrset->rrs[i].ttl, rrset->rrs[i].rdatas,
rrset->rrs[i].rdata_count)) {
log_msg(LOG_ERR, "out of memory");
return 0;
}
}
return 1;
}
/* spool read an rrset, it is a deleted RRset */
static int process_spool_delrrset(FILE* spool, struct ixfr_create* ixfrcr,
struct ixfr_store* store, uint8_t* dname, size_t dname_len,
uint16_t tp, uint16_t kl, uint16_t rrcount)
{
/* read the RRs from file and add to del list. */
uint8_t buf[MAX_RDLENGTH];
int i;
for(i=0; i<rrcount; i++) {
uint16_t rdlen;
uint32_t ttl;
if(!read_spool_u32(spool, &ttl) ||
!read_spool_u16(spool, &rdlen)) {
log_msg(LOG_ERR, "error reading file %s: %s",
ixfrcr->file_name, strerror(errno));
return 0;
}
/* because rdlen is uint16_t always smaller than sizeof(buf)*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
assert(rdlen <= sizeof(buf));
#pragma GCC diagnostic pop
if(fread(buf, rdlen, 1, spool) < 1) {
log_msg(LOG_ERR, "error reading file %s: %s",
ixfrcr->file_name, strerror(errno));
return 0;
}
if(tp == TYPE_SOA) {
if(!process_store_oldsoa(store, dname, dname_len,
tp, kl, ttl, buf, rdlen))
return 0;
}
if(!ixfr_store_delrr_uncompressed(store, dname, dname_len, tp,
kl, ttl, buf, rdlen)) {
log_msg(LOG_ERR, "out of memory");
return 0;
}
}
return 1;
}
/* add the rrset to the added list */
static int process_add_rrset(struct ixfr_store* ixfr_store,
struct domain* domain, struct rrset* rrset)
{
int i;
for(i=0; i<rrset->rr_count; i++) {
if(!ixfr_store_addrr_rdatas(ixfr_store, domain_dname(domain),
rrset->rrs[i].type, rrset->rrs[i].klass,
rrset->rrs[i].ttl, rrset->rrs[i].rdatas,
rrset->rrs[i].rdata_count)) {
log_msg(LOG_ERR, "out of memory");
return 0;
}
}
return 1;
}
/* add the RR types that are not in the marktypes list from the new zone */
static int process_marktypes(struct ixfr_store* store, struct zone* zone,
struct domain* domain, uint16_t* marktypes, size_t marktypes_used)
{
/* walk through the rrsets in the zone, if it is not in the
* marktypes list, then it is new and an added RRset */
rrset_type* s;
qsort(marktypes, marktypes_used, sizeof(marktypes[0]), &sort_uint16);
for(s=domain->rrsets; s; s=s->next) {
uint16_t tp;
if(s->zone != zone)
continue;
tp = rrset_rrtype(s);
Import 4.8.0 (previous was 4.6.0) 29 November 2023: Wouter - Tag for 4.8.0rc1. 28 November 2023: Wouter - Set up doc/RELNOTES for upcoming release. - Fix unit test kill_from_pidfile function for nonexistent files because the argument is evaluated before the test expression. - Fix rr-test to also convert the contents of the just written output file. - Fix test set to remove -f nsd.db and rm nsd.db commands. - Fix test set to remove difffile option. 27 November 2023: Jeroen - Fix #14: Set timeout to 3s when servicing remaining TCP connections. - Fix: Always instate write handler after reading queries from TCP. - Answer first query on connections accepted just before reload. 27 November 2023: Wouter - Merge #305: faster stats. Statistics can be gathered while a reload is in progress. 27 November 2023: Willem - Merge #302: Test package fixes. Correct Auxfiles, kill_from_pidfile function and fix drop_updates, rr-test and xfr_update tests. 1 November 2023: Jeroen - Remove on-disk database. 31 October 2023: Wouter - Merge #301: improve the logging of ixfr fallbacks to axfr. 30 October 2023: Jeroen - Fix processing of consolidated IXFRs. 30 October 2023: Wouter - Fix for interprocess communication to set quit sync command from main process explicitly. 3 October 2023: Wouter - Merge #281: Proxy protocol. An implementation of PROXYv2 for NSD. It can be configured with proxy-protocol-port: portnum with the port number of the interface on which proxy traffic is handled. The interface can support proxy traffic for UDP, TCP and TLS. 21 September 2023: Wouter - Merge #295: Update e-mail addresses, add ref to support contracts 31 August 2023: Wouter - Fix autoconf 2.69 warnings in configure. 14 July 2023: Wouter - Merge #287: Update nsd.conf.5.in. 11 July 2023: Wouter - Fix unused variable warning in unit test of udb. 22 June 2023: Wouter - Fix #284: dnstap_collector.c: SOCK_NONBLOCK is not available on Mac/Darwin. 7 June 2023: Wouter - Merge #282: Improve nsd.conf man page. - Fix unused but set variable warning. - Fix #283: Compile failure in remote.c when --disable-bind8-stats and --without-ssl are specified. 31 May 2023: Wouter - Add missing items to doc/RELNOTES. - Tag for 4.7.0rc1. It became release 4.7.0 on 7 june 2023. The code repository continues with 4.7.1. 30 May 2023: Jeroen - Fix #240: Prefix messages originating from verifier. - Fix #275: Drop unnecessary root server checks. 30 May 2023: Wouter - Next version is 4.7.0, instead of 4.6.2, because of the added features, like TLS for DNSTAP. - Fix unused variable warning in unit test, from clang compile. 24 May 2023: Wouter - For #279: Note that autoreconf -fi creates the configure script and also the needed auxiliary files, for autoconf 2.69 and 2.71. 4 May 2023: Wouter - Fix to remove unused whitespace from acx_nlnetlabs.m4 and config.h. 1 May 2023: Wouter - make depend. - Fix for build to run flex and bison before compiling code that needs the headers. 13 April 2023: Wouter - Fix cirrus script for submit to coverity scan to libtoolize the configure script components config.guess and config.sub. - Fix readme status badge links. 28 March 2023: Wouter - Fix #273: Large TXT record breaks AXFR. - Fix ixfr create from adding too many record types. 16 March 2023: Wouter - Fix include brackets for ssl.h include statements, instead of quotes. - Fix static analyzer warning about nsd_event_method initialization. 15 March 2023: Wouter - Dnstap tls code fixes. 14 March 2023: Wouter - Fix dnstap to not check socket path when using IP address. - dnstap over TLS, default enabled. Configured with the options dnstap-tls, dnstap-tls-server-name, dnstap-tls-cert-bundle, dnstap-tls-client-key-file and dnstap-tls-client-cert-file. - Fix to compile without ssl with dnstap-tls code. 9 March 2023: Wouter - Fix #271: DNSTAP over TCP, with dnstap-ip: "127.0.0.1@3333". - Fix to clean more memory on exit of dnstap collector. 23 February 2023: Wouter - Fix #270: reserved identifier violation. 20 February 2023: Wouter - Merge #269 from Fale: Add systemd service unit. 16 February 2023: Wouter - Fix #266: Fix build with --without-ssl. - Fix #267: Allow unencrypted local operation of nsd-control. - Fix for #267: neater variable definitions. 2 February 2023: Wouter - Merge #265: Fix C99 compatibility issue. 30 January 2023: Wouter - Merge #263: Add bash autocompletion script for nsd-control. - Fix for #262: More error logging for SSL read failures for zone transfers. 27 January 2023: Wouter - Fix #262: Zone(s) not synchronizing properly via TLS. - Fix ixfr_and_restart test to wait for processes to come to a stop. 26 January 2023: Wouter - Fix configure for -Wstrict-prototypes. 10 November 2022: Wouter - Tag for NSD 4.6.1, the repository continues with version 4.6.2. - Fix #239: -Wincompatible-pointer-types warning in remote.c. - Fix unit tests to succeed with --disable-bind8-stats. 1 November 2022: Wouter - Fixup for non-trailing newline lexer change warnings. - Update doc/RELNOTES for changes. - Fix ixfr_gone unit test to not use system default zone list file. - Fix credns tests for vm usage, and not use system default zone list file. - Fix verify tests to use more portable bash location in script. - Fix verify_again test to use ipv4 address for test. 1 November 2022: Tom - Add SVCB dohpath support 28 September 2022: Jeroen - Set ALPN "dot" token during connection establishment as per RFC9103 section 7.1 (Thanks Cesar Kuroiwa). 21 September 2022: Tom - Change zone parsing to accept non-trailing newline. 1 September 2022: Wouter - Merge #231 from moritzbuhl: Fix checking if nonblocking sockets work on OpenBSD. 19 August 2022: Wouter - Update cirrus build script for newer Ubuntu image, and FreeBSD build with libtoolize to install auxiliary files. - Update to clang 14 in cirrus build test on Ubuntu Jammy 22.04. 7 July 2022: Tom - Fix #212: Change commandline control actions to always log. 1 July 2022: Wouter - Fix static analyzer reports, fix wrong log print when skipping xfr, fix to print error on pipe read fail, and assert an xfr is in progress during packet checks.
2024-02-17 20:31:21 +03:00
if(bsearch(&tp, marktypes, marktypes_used, sizeof(marktypes[0]), &sort_uint16)) {
Import nsd-4.6.0; last import was nsd-4.3.5 23 June 2022: Wouter - Tag for 4.6.0rc1. It became 4.6.0 on 30 June 2022, and it continues with version 4.6.1. 17 June 2022: Wouter - Fix compilation with libev, without event_base_loopbreak. 16 June 2022: Wouter - Fix that the unit test verify_repat cleans up nsd on exit. - Fix to remove ixfrcreate.c asserts about uint16 within limits because of warnings from analyzers. 14 June 2022: Wouter - Fix compilation without libevent and compilation of nsd-mem. - Fix verify handler add of sigchld event for compilation without libevent. 3 June 2022: Wouter - Fix static analyzer reports on ixfrcreate temp file. - Fixup wrong ixfrcreate fread return check. 13 May 2022: Wouter - The code repo continues with version 4.5.1. 6 May 2022: Wouter - Merge PR #209: IXFR out This adds IXFR out functionality to NSD. NSD can copy IXFRs from upstream to downstream clients, or create IXFRs from zonefiles. The options store-ixfr: yes and create-ixfr: yes can be used to turn this on. Default is turned off. The options ixfr-number and ixfr-size can be used to tune the number of IXFR transfers and total data size stored. This is configured per zone, the IXFRs are served to the hosts that are allowed to perform zone transfers. And if TSIG is configured, signed with the same key. The content is stored to file if a zonefile is configured for the zone, in the zonefile.ixfr and zonefile.ixfr.2, .. files. They contain readable text format. The number of IXFRs is num.rixfr in statistics output, also per zone if per zone statistics are enabled. If offline, nsd-checkzone -i can create ixfr files. NSD already supports requesting IXFRs, this addition allows NSD to serve IXFR transfers to clients. NSD stops responding with NOTIMPL to IXFR requests, also for zones that do not have IXFR enabled. The clients gets a full zone reply or a status reply if the serial is up to date. - set version to 4.5.0 for feature change. - Tag for 4.5.0rc1 release. It became the 4.5.0 release on 13 May 2022. 14 April 2022: Wouter - Update cirrus script FreeBSD version. 25 March 2022: Wouter - Fix spelling error in comment in svcbparam_lookup_key. 2 March 2022: Wouter - Fix code analyzer zero divide warning. - Fix code analyzer large value with assertion. - Fix another code analyzer zero divide warning. - Fix code analyzer warning about uninitialized temp storage in loop. 10 February 2022: Wouter - Tag for 4.4.0rc1 release. This became 4.4.0 release on 17 Feb 2022, the code repository continues with version 4.4.1. 9 February 2022: Wouter - Fix unit tests for nds-control-setup exit code and the xfrd-tcp-max default. 7 February 2022: Wouter - Merge #207 Sync nsd-control-setup with unbound-control-setup to generate certificates with SANs. 28 January 2022: Wouter - Fix #206: build with --without-ssl fails. 27 January 2022: Wouter - current code branch continues as version 4.4.0, because of added feature. 26 January 2022: Wouter - Merge #193: Lower memory usage of the XFRD process by default. Instead of preallocating all elements, they are allocated when used. There are options for managing the memory usage, defaults are the same as before. xfrd-tcp-max sets the number of sockets for tcp connections that xfrd can make to download zone contents. And xfrd-tcp-pipeline the number of simultaneous transfers over the same connection. 12 January 2022: Wouter - Fix to document nsd-checkzone -p in the man page for nsd-checkzone. 7 January 2022: Wouter - Fix to change file mode before changing file owner for the nsd-control unix socket file. 3 January 2022: Wouter - Merge #204 from jonathangray: correct some spelling mistakes. 15 December 2021: Wouter - Fix #200: nsd-checkzone succeeds even with incorrect serial in SOA record. 2 December 2021: Wouter - Fix socket_partitioning unit test for FreeBSD. - Fix SVCB test to work around older dig with drill. - Fix unit test to not syslog setlogin failures. 1 December 2021: Wouter - Set up for branch for 4.3.9 release. This became release 4.3.9 on 9 Dec 2021 and included the changes until the SVCB fix on 2 dec 2021, but not the setlogin fix. The main branch continues as 4.3.10. - Fix unit tests for new answer-cookie default. 30 November 2021: Wouter - Fix to remove git tracking and ci information from release tarballs. 3 November 2021: Wouter - Fix #198: nsd-control reconfig core dump. 12 October 2021: Wouter - Tag for 4.3.8 release, from 4.3.8rc2. The main branch continues with version 4.3.9 in development. 7 October 2021: Wouter - Set default for answer-cookie to no. Because in server deployments with mixed server software, a default of yes causes issues. - Tag for 4.3.8rc2, includes the new answer-cookie default. 4 October 2021: Wouter - Tag for 4.3.8rc1. 29 September 2021: Wouter - Fix unit tests for svcb and xot to not touch the default zonelistfile. - Fix unit test for xot tertiary config for zonelistfile default. - Fix unit test for dns-cookies for no unshare, and allow-query for no IPv6 loopback. - Fix unit test allow query to check for IPv6. 22 September 2021: Wouter - Fix #194: Incorrect NSEC3 response for SOA query below delegation point. 13 September 2021: Wouter - Fix compile failure with openssl 1.0.2. 3 September 2021: Wouter - Fix not reachable annotation in radix_find_prefix_node. 31 August 2021: Willem - Fix #191: dname_parse_wire() returns fqdn wireformat length. 26 August 2021: Wouter - Fix #190: NSD returns 3 NSEC3 records for NODATA response. 23 August 2021: Wouter - Fix #189: nsd 4.3.7 crash answer_delegation: Assertion `query->delegation_rrset' failed. 17 August 2021: Wouter - Fix #188: NSD fails to build against openssl 1.1 on CentOS 7. - Fix sed script in ssldir split handling. 13 August 2021: Wouter - Merge #187: Support using system-wide crypto policies. 10 August 2021: Wouter - Merge #185 by cesarkuroiwa: Mutual TLS. - Fixes for #185: Document client-cert, client-key and client-key-pw in the man page. Fix yacc semicolon. Fix unused variable warning. Use strlcpy instead of strncpy. Fix spelling error in error printout. 2 August 2021: Wouter - Quieter tpkg/do-tests shell script with -q flag. - For #184: Note that all zones can be targeted by some nsd-control commands in the man page. 30 July 2021: Wouter - Move acx_nlnetlabs.m4 to version 41, with lib64 openssl dir check. - Fix to compile with OpenSSL 3.0.0beta2. - Fix configure detection of SSL_CTX_set_security_level. - Fix deprecated functions use from openssl 3.0.0beta2. 23 July 2021: Wouter - Fix free on shutdown of XoT SSL context. 22 July 2021: Wouter - tag 4.3.7 release, with the fixes between rc1 and this release. - main branch continues for 4.3.8. 20 July 2021: Wouter - Fix typo in xfrd-tcp.c. 15 July 2021: Wouter - tag for 4.3.7rc1. - Fix compile of cookies on FreeBSD without IPv6. - Fix for loop initial declaration for nonc99 compiler. 14 July 2021: Wouter - Fix truncate test for EDNS COOKIE making one less RR is added. - Attempt to fix gcc11 warning. 13 July 2021: Willem - Fixes for child server processes getting out of sync with the dnstap-collector process 13 July 2021: Willem - Interoperable DNS Cookies support as per RFC7873 and RFC9018 9 July 2021: Willem - Client side DNS Zone Transfer-over-TLS (XoT) support as per draft-ietf-dprive-xfr-over-tls 29 June 2021: Willem - Fix #168: Buffer overflow in the dname_to_string() function 14 June 2021: Wouter - Update configure nonblocking test to use host. 25 May 2021: Wouter - Fix #179: log notice and server-count. 21 May 2021: Wouter - Test code has -q option for quiet output. 17 May 2021: Wouter - Update the ACX_CHECK_NONBLOCKING_BROKEN test for the configure script. 7 May 2021: Wouter - Fix #176: please review Loglevel on missing zonefile. 6 May 2021: Wouter - Fix #174: NS Records below delegation are not ignored (nsd-checkzone also does not raise any issue). 4 May 2021: Wouter - Fix SVCB sort call sizeof to be the size of the elements sorted. 29 April 2021: Tom - Implement Syntax of SVCB and HTTPS RR type as per draft-ietf-dnsop-svcb-https 13 April 2021: Wouter - Fix for #128: Skip over sendmmsg invalid argument when port is zero. - Fix #171: Invalid negative response (NSEC3) after IXFR. - Fix to make nsec3_chain_find_prev return NULL if one nsec3 left. - remove debug settings from unit test. 9 April 2021: Wouter - Fix for #170: Fix build warnings when IPv6 is disabled. - Fix #170: Disabled IPv6 and DNSTAP enabled triggers a build error. 30 March 2021: Wouter - Fix configure failure for enable systemd because of autoconf. - This became release 4.3.6, the repository continues for 4.3.7 in development. 29 March 2021: Wouter - Note unlisted changes in RELNOTES and prepare for 4.3.6rc1 tag. 29 March 2021: Willem - Per zone Access Control List for queries with an allow-query: option. 24 March 2021: Wouter - Update acx_nlnetlabs.m4 to version 38, fix deprecation test. - Fix configure to use header checks with compile. - Fix warning about unused function log_addr. 18 March 2021: Tom - Add Extended DNS Errors RFC8914 15 March 2021: Wouter - Fix double config.h include in configlexer.c - Fix to remove configyyrename from makedist.sh and also update the flex and bison rules there to add the "c_" prefix. 13 March 2021: Willem - Fix #154: TXT with parentheses fails in 4.3.5. - Align parsing of TXT elements with how bind does it. - A -p option to nsd-checkzone to print a successfully read zone. 12 March 2021: Wouter - Fix that wildcard is printed as a star instead of escaped, in logs and in written zone files. - Fix unit test for wildcard printout change. 11 March 2021: Wouter - Fix #163: A TSIG noncompliance with RFC 2845. 9 March 2021: Willem - Enable configuring a control-interface by interface name. 19 February 2021: Wouter - Fix segfault on high verbosity for TLS channels with dnstap log local address. 18 February 2021: Wouter - Fix #146 with #147: DNSTAP log the local address of the server with the dnstap logs. 16 February 2021: Wouter - Man page documentation for dnstap options. 8 February 2021: Wouter - Fix AF_LOCAL compile error for Solaris. - Fix ifaddrs compile error for Solaris. - Fix ifaddrs.h compile error for Solaris. 4 February 2021: Wouter - Merge PR #153 from fobser: Repair -fno-common linker errors automatically. - Fix uninitialized access of log_buf in error printout on apply ixfr. 26 January 2021: Wouter - Prevent a few more yacc clashes.
2022-09-24 20:35:00 +03:00
/* the item is in the marked list, skip it */
continue;
}
if(!process_add_rrset(store, domain, s))
return 0;
}
return 1;
}
/* check the difference between the domain and RRs from spool */
static int process_diff_domain(FILE* spool, struct ixfr_create* ixfrcr,
struct ixfr_store* store, struct zone* zone, struct domain* domain)
{
/* Read the RR types from spool. Mark off the ones seen,
* later, the notseen ones from the new zone are added RRsets.
* For the ones not in the new zone, they are deleted RRsets.
* If they exist in old and new, check for RR differences. */
uint32_t spool_type_count, i;
uint16_t marktypes[65536];
size_t marktypes_used = 0;
if(!read_spool_u32(spool, &spool_type_count)) {
log_msg(LOG_ERR, "error reading file %s: %s",
ixfrcr->file_name, strerror(errno));
return 0;
}
if(spool_type_count > sizeof(marktypes)) {
log_msg(LOG_ERR, "error reading file %s: spool type count "
"too large", ixfrcr->file_name);
return 0;
}
for(i=0; i<spool_type_count; i++) {
uint16_t tp, kl, rrcount;
struct rrset* rrset;
if(!read_spool_u16(spool, &tp) ||
!read_spool_u16(spool, &kl) ||
!read_spool_u16(spool, &rrcount)) {
log_msg(LOG_ERR, "error reading file %s: %s",
ixfrcr->file_name, strerror(errno));
return 0;
}
/* The rrcount is within limits of sizeof(marktypes), because
* the uint16_t < 65536 */
rrset = domain_find_rrset(domain, zone, tp);
if(!rrset) {
/* rrset in spool but not in new zone, deleted RRset */
if(!process_spool_delrrset(spool, ixfrcr, store,
(void*)dname_name(domain_dname(domain)),
domain_dname(domain)->name_size, tp, kl,
rrcount))
return 0;
} else {
/* add to the marked types, this one is present in
* spool */
marktypes[marktypes_used++] = tp;
/* rrset in old and in new zone, diff the RRset */
if(!process_diff_rrset(spool, ixfrcr, store, domain,
tp, kl, rrcount, rrset))
return 0;
}
}
/* process markoff to see if new zone has RRsets not in spool,
* those are added RRsets. */
if(!process_marktypes(store, zone, domain, marktypes, marktypes_used))
return 0;
return 1;
}
/* add the RRs for the domain in new zone */
static int process_domain_add_RRs(struct ixfr_store* store, struct zone* zone,
struct domain* domain)
{
rrset_type* s;
for(s=domain->rrsets; s; s=s->next) {
if(s->zone != zone)
continue;
if(!process_add_rrset(store, domain, s))
return 0;
}
return 1;
}
/* del the RRs for the domain from the spool */
static int process_domain_del_RRs(struct ixfr_create* ixfrcr,
struct ixfr_store* store, FILE* spool, uint8_t* dname,
size_t dname_len)
{
uint32_t spool_type_count, i;
if(!read_spool_u32(spool, &spool_type_count)) {
log_msg(LOG_ERR, "error reading file %s: %s",
ixfrcr->file_name, strerror(errno));
return 0;
}
if(spool_type_count > 65536) {
log_msg(LOG_ERR, "error reading file %s: del RR spool type "
"count too large", ixfrcr->file_name);
return 0;
}
for(i=0; i<spool_type_count; i++) {
uint16_t tp, kl, rrcount;
if(!read_spool_u16(spool, &tp) ||
!read_spool_u16(spool, &kl) ||
!read_spool_u16(spool, &rrcount)) {
log_msg(LOG_ERR, "error reading file %s: %s",
ixfrcr->file_name, strerror(errno));
return 0;
}
/* The rrcount is within reasonable limits, because
* the uint16_t < 65536 */
if(!process_spool_delrrset(spool, ixfrcr, store, dname,
dname_len, tp, kl, rrcount))
return 0;
}
return 1;
}
/* init the spool dname iterator */
static void spool_dname_iter_init(struct spool_dname_iterator* iter,
FILE* spool, char* file_name)
{
memset(iter, 0, sizeof(*iter));
iter->spool = spool;
iter->file_name = file_name;
}
/* read the dname element into the buffer for the spool dname iterator */
static int spool_dname_iter_read(struct spool_dname_iterator* iter)
{
if(!read_spool_dname(iter->spool, iter->dname, sizeof(iter->dname),
&iter->dname_len)) {
log_msg(LOG_ERR, "error reading file %s: %s",
iter->file_name, strerror(errno));
return 0;
}
return 1;
}
/* get the next name to operate on, that is not processed yet, 0 on failure
* returns okay on endoffile, check with eof for that.
* when done with an element, set iter->is_processed on the element. */
static int spool_dname_iter_next(struct spool_dname_iterator* iter)
{
if(iter->eof)
return 1;
if(!iter->read_first) {
/* read the first one */
if(!spool_dname_iter_read(iter))
return 0;
if(iter->dname_len == 0)
iter->eof = 1;
iter->read_first = 1;
iter->is_processed = 0;
}
if(!iter->is_processed) {
/* the current one needs processing */
return 1;
}
/* read the next one */
if(!spool_dname_iter_read(iter))
return 0;
if(iter->dname_len == 0)
iter->eof = 1;
iter->is_processed = 0;
return 1;
}
/* check if the ixfr is too large */
static int ixfr_create_too_large(struct ixfr_create* ixfrcr,
struct ixfr_store* store)
{
if(store->cancelled)
return 1;
if(ixfrcr->max_size != 0 &&
ixfr_data_size(store->data) > ixfrcr->max_size) {
if(ixfrcr->errorcmdline) {
log_msg(LOG_ERR, "the ixfr for %s exceeds size %u, it is not created",
wiredname2str(ixfrcr->zone_name),
(unsigned)ixfrcr->max_size);
} else {
VERBOSITY(2, (LOG_INFO, "the ixfr for %s exceeds size %u, it is not created",
wiredname2str(ixfrcr->zone_name),
(unsigned)ixfrcr->max_size));
}
ixfr_store_cancel(store);
return 1;
}
return 0;
}
/* process the spool input before the domain */
static int process_spool_before_domain(FILE* spool, struct ixfr_create* ixfrcr,
struct ixfr_store* store, struct domain* domain,
struct spool_dname_iterator* iter, struct region* tmp_region)
{
const dname_type* dname;
if(ixfr_create_too_large(ixfrcr, store))
return 0;
/* read the domains and rrsets before the domain and those are from
* the old zone. If the domain is equal, return to have that processed
* if we bypass, that means the domain does not exist, do that */
while(!iter->eof) {
if(!spool_dname_iter_next(iter))
return 0;
if(iter->eof)
break;
/* see if we are at, before or after the domain */
dname = dname_make(tmp_region, iter->dname, 1);
if(!dname) {
log_msg(LOG_ERR, "error in dname in %s",
iter->file_name);
return 0;
}
if(dname_compare(dname, domain_dname(domain)) < 0) {
/* the dname is smaller than the one from the zone.
* it must be deleted, process it */
if(!process_domain_del_RRs(ixfrcr, store, spool,
iter->dname, iter->dname_len))
return 0;
iter->is_processed = 1;
} else {
/* we are at or after the domain we are looking for,
* done here */
return 1;
}
if(ixfr_create_too_large(ixfrcr, store))
return 0;
}
/* no more domains on spool, done here */
return 1;
}
/* process the spool input for the domain */
static int process_spool_for_domain(FILE* spool, struct ixfr_create* ixfrcr,
struct ixfr_store* store, struct zone* zone, struct domain* domain,
struct spool_dname_iterator* iter, struct region* tmp_region)
{
/* process all the spool that is not the domain, that is before the
* domain in the new zone */
if(!process_spool_before_domain(spool, ixfrcr, store, domain, iter,
tmp_region))
return 0;
if(ixfr_create_too_large(ixfrcr, store))
return 0;
/* are we at the correct domain now? */
if(iter->eof || iter->dname_len != domain_dname(domain)->name_size ||
memcmp(iter->dname, dname_name(domain_dname(domain)),
iter->dname_len) != 0) {
/* the domain from the new zone is not present in the old zone,
* the content is in the added RRs set */
if(!process_domain_add_RRs(store, zone, domain))
return 0;
return 1;
}
/* process the domain */
/* the domain exists both in the old and new zone,
* check for RR differences */
if(!process_diff_domain(spool, ixfrcr, store, zone, domain))
return 0;
iter->is_processed = 1;
return 1;
}
/* process remaining spool items */
static int process_spool_remaining(FILE* spool, struct ixfr_create* ixfrcr,
struct ixfr_store* store, struct spool_dname_iterator* iter)
{
/* the remaining domain names in the spool file, that is after
* the last domain in the new zone. */
if(ixfr_create_too_large(ixfrcr, store))
return 0;
while(!iter->eof) {
if(!spool_dname_iter_next(iter))
return 0;
if(iter->eof)
break;
/* the domain only exists in the spool, the old zone,
* and not in the new zone. That would be domains
* after the new zone domains, or there are no new
* zone domains */
if(!process_domain_del_RRs(ixfrcr, store, spool, iter->dname,
iter->dname_len))
return 0;
iter->is_processed = 1;
if(ixfr_create_too_large(ixfrcr, store))
return 0;
}
return 1;
}
/* walk through the zone and find the differences */
static int ixfr_create_walk_zone(FILE* spool, struct ixfr_create* ixfrcr,
struct ixfr_store* store, struct zone* zone)
{
struct domain* domain;
struct spool_dname_iterator iter;
struct region* tmp_region;
spool_dname_iter_init(&iter, spool, ixfrcr->file_name);
tmp_region = region_create(xalloc, free);
for(domain = zone->apex; domain && domain_is_subdomain(domain,
zone->apex); domain = domain_next(domain)) {
uint32_t count = domain_count_rrsets(domain, zone);
if(count == 0)
continue;
/* the domain is a domain in the new zone */
if(!process_spool_for_domain(spool, ixfrcr, store, zone,
domain, &iter, tmp_region)) {
region_destroy(tmp_region);
return 0;
}
region_free_all(tmp_region);
if(ixfr_create_too_large(ixfrcr, store))
return 0;
}
if(!process_spool_remaining(spool, ixfrcr, store, &iter)) {
region_destroy(tmp_region);
return 0;
}
region_destroy(tmp_region);
return 1;
}
/* see if the ixfr has already been created by reading the file header
* of the to-be-created file, if that file already exists */
static int ixfr_create_already_done_serial(struct zone* zone,
const char* zfile, int checknew, uint32_t old_serial,
uint32_t new_serial)
{
uint32_t file_oldserial = 0, file_newserial = 0;
size_t data_size = 0;
if(!ixfr_read_file_header(zone->opts->name, zfile, 1, &file_oldserial,
&file_newserial, &data_size, 0)) {
/* could not read, so it was not done */
return 0;
}
if(file_oldserial == old_serial &&
(!checknew || file_newserial == new_serial)) {
log_msg(LOG_INFO, "IXFR already exists in file %s.ixfr, nothing to do",
zfile);
return 1;
}
return 0;
}
/* See the data size of the ixfr by reading the file header of the ixfr file */
static int ixfr_read_header_data_size(const char* zname,
const char* zfile, int file_num, size_t* data_size)
{
uint32_t file_oldserial = 0, file_newserial = 0;
if(!ixfr_read_file_header(zname, zfile, file_num, &file_oldserial,
&file_newserial, data_size, 0)) {
/* could not read */
return 0;
}
return 1;
}
/* see if the ixfr has already been created by reading the file header
* of the to-be-created file, if that file already exists */
static int ixfr_create_already_done(struct ixfr_create* ixfrcr,
struct zone* zone, const char* zfile, int checknew)
{
return ixfr_create_already_done_serial(zone, zfile, checknew,
ixfrcr->old_serial, ixfrcr->new_serial);
}
/* store the new soa record for the ixfr */
static int ixfr_create_store_newsoa(struct ixfr_store* store,
struct zone* zone)
{
if(!zone || !zone->soa_rrset) {
log_msg(LOG_ERR, "error no SOA rrset");
return 0;
}
if(zone->soa_rrset->rr_count == 0) {
log_msg(LOG_ERR, "error empty SOA rrset");
return 0;
}
if(!ixfr_store_add_newsoa_rdatas(store, domain_dname(zone->apex),
zone->soa_rrset->rrs[0].type, zone->soa_rrset->rrs[0].klass,
zone->soa_rrset->rrs[0].ttl, zone->soa_rrset->rrs[0].rdatas,
zone->soa_rrset->rrs[0].rdata_count)) {
log_msg(LOG_ERR, "out of memory");
return 0;
}
return 1;
}
/* initialise ixfr_create perform, open spool, read header, get serial */
static int ixfr_perform_init(struct ixfr_create* ixfrcr, struct zone* zone,
struct ixfr_store* store_mem, struct ixfr_store** store, FILE** spool)
{
*spool = fopen(ixfrcr->file_name, "r");
if(!*spool) {
log_msg(LOG_ERR, "could not open %s for reading: %s",
ixfrcr->file_name, strerror(errno));
return 0;
}
if(!read_spool_header(*spool, ixfrcr)) {
fclose(*spool);
return 0;
}
ixfrcr->new_serial = zone_get_current_serial(zone);
Import 4.8.0 (previous was 4.6.0) 29 November 2023: Wouter - Tag for 4.8.0rc1. 28 November 2023: Wouter - Set up doc/RELNOTES for upcoming release. - Fix unit test kill_from_pidfile function for nonexistent files because the argument is evaluated before the test expression. - Fix rr-test to also convert the contents of the just written output file. - Fix test set to remove -f nsd.db and rm nsd.db commands. - Fix test set to remove difffile option. 27 November 2023: Jeroen - Fix #14: Set timeout to 3s when servicing remaining TCP connections. - Fix: Always instate write handler after reading queries from TCP. - Answer first query on connections accepted just before reload. 27 November 2023: Wouter - Merge #305: faster stats. Statistics can be gathered while a reload is in progress. 27 November 2023: Willem - Merge #302: Test package fixes. Correct Auxfiles, kill_from_pidfile function and fix drop_updates, rr-test and xfr_update tests. 1 November 2023: Jeroen - Remove on-disk database. 31 October 2023: Wouter - Merge #301: improve the logging of ixfr fallbacks to axfr. 30 October 2023: Jeroen - Fix processing of consolidated IXFRs. 30 October 2023: Wouter - Fix for interprocess communication to set quit sync command from main process explicitly. 3 October 2023: Wouter - Merge #281: Proxy protocol. An implementation of PROXYv2 for NSD. It can be configured with proxy-protocol-port: portnum with the port number of the interface on which proxy traffic is handled. The interface can support proxy traffic for UDP, TCP and TLS. 21 September 2023: Wouter - Merge #295: Update e-mail addresses, add ref to support contracts 31 August 2023: Wouter - Fix autoconf 2.69 warnings in configure. 14 July 2023: Wouter - Merge #287: Update nsd.conf.5.in. 11 July 2023: Wouter - Fix unused variable warning in unit test of udb. 22 June 2023: Wouter - Fix #284: dnstap_collector.c: SOCK_NONBLOCK is not available on Mac/Darwin. 7 June 2023: Wouter - Merge #282: Improve nsd.conf man page. - Fix unused but set variable warning. - Fix #283: Compile failure in remote.c when --disable-bind8-stats and --without-ssl are specified. 31 May 2023: Wouter - Add missing items to doc/RELNOTES. - Tag for 4.7.0rc1. It became release 4.7.0 on 7 june 2023. The code repository continues with 4.7.1. 30 May 2023: Jeroen - Fix #240: Prefix messages originating from verifier. - Fix #275: Drop unnecessary root server checks. 30 May 2023: Wouter - Next version is 4.7.0, instead of 4.6.2, because of the added features, like TLS for DNSTAP. - Fix unused variable warning in unit test, from clang compile. 24 May 2023: Wouter - For #279: Note that autoreconf -fi creates the configure script and also the needed auxiliary files, for autoconf 2.69 and 2.71. 4 May 2023: Wouter - Fix to remove unused whitespace from acx_nlnetlabs.m4 and config.h. 1 May 2023: Wouter - make depend. - Fix for build to run flex and bison before compiling code that needs the headers. 13 April 2023: Wouter - Fix cirrus script for submit to coverity scan to libtoolize the configure script components config.guess and config.sub. - Fix readme status badge links. 28 March 2023: Wouter - Fix #273: Large TXT record breaks AXFR. - Fix ixfr create from adding too many record types. 16 March 2023: Wouter - Fix include brackets for ssl.h include statements, instead of quotes. - Fix static analyzer warning about nsd_event_method initialization. 15 March 2023: Wouter - Dnstap tls code fixes. 14 March 2023: Wouter - Fix dnstap to not check socket path when using IP address. - dnstap over TLS, default enabled. Configured with the options dnstap-tls, dnstap-tls-server-name, dnstap-tls-cert-bundle, dnstap-tls-client-key-file and dnstap-tls-client-cert-file. - Fix to compile without ssl with dnstap-tls code. 9 March 2023: Wouter - Fix #271: DNSTAP over TCP, with dnstap-ip: "127.0.0.1@3333". - Fix to clean more memory on exit of dnstap collector. 23 February 2023: Wouter - Fix #270: reserved identifier violation. 20 February 2023: Wouter - Merge #269 from Fale: Add systemd service unit. 16 February 2023: Wouter - Fix #266: Fix build with --without-ssl. - Fix #267: Allow unencrypted local operation of nsd-control. - Fix for #267: neater variable definitions. 2 February 2023: Wouter - Merge #265: Fix C99 compatibility issue. 30 January 2023: Wouter - Merge #263: Add bash autocompletion script for nsd-control. - Fix for #262: More error logging for SSL read failures for zone transfers. 27 January 2023: Wouter - Fix #262: Zone(s) not synchronizing properly via TLS. - Fix ixfr_and_restart test to wait for processes to come to a stop. 26 January 2023: Wouter - Fix configure for -Wstrict-prototypes. 10 November 2022: Wouter - Tag for NSD 4.6.1, the repository continues with version 4.6.2. - Fix #239: -Wincompatible-pointer-types warning in remote.c. - Fix unit tests to succeed with --disable-bind8-stats. 1 November 2022: Wouter - Fixup for non-trailing newline lexer change warnings. - Update doc/RELNOTES for changes. - Fix ixfr_gone unit test to not use system default zone list file. - Fix credns tests for vm usage, and not use system default zone list file. - Fix verify tests to use more portable bash location in script. - Fix verify_again test to use ipv4 address for test. 1 November 2022: Tom - Add SVCB dohpath support 28 September 2022: Jeroen - Set ALPN "dot" token during connection establishment as per RFC9103 section 7.1 (Thanks Cesar Kuroiwa). 21 September 2022: Tom - Change zone parsing to accept non-trailing newline. 1 September 2022: Wouter - Merge #231 from moritzbuhl: Fix checking if nonblocking sockets work on OpenBSD. 19 August 2022: Wouter - Update cirrus build script for newer Ubuntu image, and FreeBSD build with libtoolize to install auxiliary files. - Update to clang 14 in cirrus build test on Ubuntu Jammy 22.04. 7 July 2022: Tom - Fix #212: Change commandline control actions to always log. 1 July 2022: Wouter - Fix static analyzer reports, fix wrong log print when skipping xfr, fix to print error on pipe read fail, and assert an xfr is in progress during packet checks.
2024-02-17 20:31:21 +03:00
*store = ixfr_store_start(zone, store_mem);
Import nsd-4.6.0; last import was nsd-4.3.5 23 June 2022: Wouter - Tag for 4.6.0rc1. It became 4.6.0 on 30 June 2022, and it continues with version 4.6.1. 17 June 2022: Wouter - Fix compilation with libev, without event_base_loopbreak. 16 June 2022: Wouter - Fix that the unit test verify_repat cleans up nsd on exit. - Fix to remove ixfrcreate.c asserts about uint16 within limits because of warnings from analyzers. 14 June 2022: Wouter - Fix compilation without libevent and compilation of nsd-mem. - Fix verify handler add of sigchld event for compilation without libevent. 3 June 2022: Wouter - Fix static analyzer reports on ixfrcreate temp file. - Fixup wrong ixfrcreate fread return check. 13 May 2022: Wouter - The code repo continues with version 4.5.1. 6 May 2022: Wouter - Merge PR #209: IXFR out This adds IXFR out functionality to NSD. NSD can copy IXFRs from upstream to downstream clients, or create IXFRs from zonefiles. The options store-ixfr: yes and create-ixfr: yes can be used to turn this on. Default is turned off. The options ixfr-number and ixfr-size can be used to tune the number of IXFR transfers and total data size stored. This is configured per zone, the IXFRs are served to the hosts that are allowed to perform zone transfers. And if TSIG is configured, signed with the same key. The content is stored to file if a zonefile is configured for the zone, in the zonefile.ixfr and zonefile.ixfr.2, .. files. They contain readable text format. The number of IXFRs is num.rixfr in statistics output, also per zone if per zone statistics are enabled. If offline, nsd-checkzone -i can create ixfr files. NSD already supports requesting IXFRs, this addition allows NSD to serve IXFR transfers to clients. NSD stops responding with NOTIMPL to IXFR requests, also for zones that do not have IXFR enabled. The clients gets a full zone reply or a status reply if the serial is up to date. - set version to 4.5.0 for feature change. - Tag for 4.5.0rc1 release. It became the 4.5.0 release on 13 May 2022. 14 April 2022: Wouter - Update cirrus script FreeBSD version. 25 March 2022: Wouter - Fix spelling error in comment in svcbparam_lookup_key. 2 March 2022: Wouter - Fix code analyzer zero divide warning. - Fix code analyzer large value with assertion. - Fix another code analyzer zero divide warning. - Fix code analyzer warning about uninitialized temp storage in loop. 10 February 2022: Wouter - Tag for 4.4.0rc1 release. This became 4.4.0 release on 17 Feb 2022, the code repository continues with version 4.4.1. 9 February 2022: Wouter - Fix unit tests for nds-control-setup exit code and the xfrd-tcp-max default. 7 February 2022: Wouter - Merge #207 Sync nsd-control-setup with unbound-control-setup to generate certificates with SANs. 28 January 2022: Wouter - Fix #206: build with --without-ssl fails. 27 January 2022: Wouter - current code branch continues as version 4.4.0, because of added feature. 26 January 2022: Wouter - Merge #193: Lower memory usage of the XFRD process by default. Instead of preallocating all elements, they are allocated when used. There are options for managing the memory usage, defaults are the same as before. xfrd-tcp-max sets the number of sockets for tcp connections that xfrd can make to download zone contents. And xfrd-tcp-pipeline the number of simultaneous transfers over the same connection. 12 January 2022: Wouter - Fix to document nsd-checkzone -p in the man page for nsd-checkzone. 7 January 2022: Wouter - Fix to change file mode before changing file owner for the nsd-control unix socket file. 3 January 2022: Wouter - Merge #204 from jonathangray: correct some spelling mistakes. 15 December 2021: Wouter - Fix #200: nsd-checkzone succeeds even with incorrect serial in SOA record. 2 December 2021: Wouter - Fix socket_partitioning unit test for FreeBSD. - Fix SVCB test to work around older dig with drill. - Fix unit test to not syslog setlogin failures. 1 December 2021: Wouter - Set up for branch for 4.3.9 release. This became release 4.3.9 on 9 Dec 2021 and included the changes until the SVCB fix on 2 dec 2021, but not the setlogin fix. The main branch continues as 4.3.10. - Fix unit tests for new answer-cookie default. 30 November 2021: Wouter - Fix to remove git tracking and ci information from release tarballs. 3 November 2021: Wouter - Fix #198: nsd-control reconfig core dump. 12 October 2021: Wouter - Tag for 4.3.8 release, from 4.3.8rc2. The main branch continues with version 4.3.9 in development. 7 October 2021: Wouter - Set default for answer-cookie to no. Because in server deployments with mixed server software, a default of yes causes issues. - Tag for 4.3.8rc2, includes the new answer-cookie default. 4 October 2021: Wouter - Tag for 4.3.8rc1. 29 September 2021: Wouter - Fix unit tests for svcb and xot to not touch the default zonelistfile. - Fix unit test for xot tertiary config for zonelistfile default. - Fix unit test for dns-cookies for no unshare, and allow-query for no IPv6 loopback. - Fix unit test allow query to check for IPv6. 22 September 2021: Wouter - Fix #194: Incorrect NSEC3 response for SOA query below delegation point. 13 September 2021: Wouter - Fix compile failure with openssl 1.0.2. 3 September 2021: Wouter - Fix not reachable annotation in radix_find_prefix_node. 31 August 2021: Willem - Fix #191: dname_parse_wire() returns fqdn wireformat length. 26 August 2021: Wouter - Fix #190: NSD returns 3 NSEC3 records for NODATA response. 23 August 2021: Wouter - Fix #189: nsd 4.3.7 crash answer_delegation: Assertion `query->delegation_rrset' failed. 17 August 2021: Wouter - Fix #188: NSD fails to build against openssl 1.1 on CentOS 7. - Fix sed script in ssldir split handling. 13 August 2021: Wouter - Merge #187: Support using system-wide crypto policies. 10 August 2021: Wouter - Merge #185 by cesarkuroiwa: Mutual TLS. - Fixes for #185: Document client-cert, client-key and client-key-pw in the man page. Fix yacc semicolon. Fix unused variable warning. Use strlcpy instead of strncpy. Fix spelling error in error printout. 2 August 2021: Wouter - Quieter tpkg/do-tests shell script with -q flag. - For #184: Note that all zones can be targeted by some nsd-control commands in the man page. 30 July 2021: Wouter - Move acx_nlnetlabs.m4 to version 41, with lib64 openssl dir check. - Fix to compile with OpenSSL 3.0.0beta2. - Fix configure detection of SSL_CTX_set_security_level. - Fix deprecated functions use from openssl 3.0.0beta2. 23 July 2021: Wouter - Fix free on shutdown of XoT SSL context. 22 July 2021: Wouter - tag 4.3.7 release, with the fixes between rc1 and this release. - main branch continues for 4.3.8. 20 July 2021: Wouter - Fix typo in xfrd-tcp.c. 15 July 2021: Wouter - tag for 4.3.7rc1. - Fix compile of cookies on FreeBSD without IPv6. - Fix for loop initial declaration for nonc99 compiler. 14 July 2021: Wouter - Fix truncate test for EDNS COOKIE making one less RR is added. - Attempt to fix gcc11 warning. 13 July 2021: Willem - Fixes for child server processes getting out of sync with the dnstap-collector process 13 July 2021: Willem - Interoperable DNS Cookies support as per RFC7873 and RFC9018 9 July 2021: Willem - Client side DNS Zone Transfer-over-TLS (XoT) support as per draft-ietf-dprive-xfr-over-tls 29 June 2021: Willem - Fix #168: Buffer overflow in the dname_to_string() function 14 June 2021: Wouter - Update configure nonblocking test to use host. 25 May 2021: Wouter - Fix #179: log notice and server-count. 21 May 2021: Wouter - Test code has -q option for quiet output. 17 May 2021: Wouter - Update the ACX_CHECK_NONBLOCKING_BROKEN test for the configure script. 7 May 2021: Wouter - Fix #176: please review Loglevel on missing zonefile. 6 May 2021: Wouter - Fix #174: NS Records below delegation are not ignored (nsd-checkzone also does not raise any issue). 4 May 2021: Wouter - Fix SVCB sort call sizeof to be the size of the elements sorted. 29 April 2021: Tom - Implement Syntax of SVCB and HTTPS RR type as per draft-ietf-dnsop-svcb-https 13 April 2021: Wouter - Fix for #128: Skip over sendmmsg invalid argument when port is zero. - Fix #171: Invalid negative response (NSEC3) after IXFR. - Fix to make nsec3_chain_find_prev return NULL if one nsec3 left. - remove debug settings from unit test. 9 April 2021: Wouter - Fix for #170: Fix build warnings when IPv6 is disabled. - Fix #170: Disabled IPv6 and DNSTAP enabled triggers a build error. 30 March 2021: Wouter - Fix configure failure for enable systemd because of autoconf. - This became release 4.3.6, the repository continues for 4.3.7 in development. 29 March 2021: Wouter - Note unlisted changes in RELNOTES and prepare for 4.3.6rc1 tag. 29 March 2021: Willem - Per zone Access Control List for queries with an allow-query: option. 24 March 2021: Wouter - Update acx_nlnetlabs.m4 to version 38, fix deprecation test. - Fix configure to use header checks with compile. - Fix warning about unused function log_addr. 18 March 2021: Tom - Add Extended DNS Errors RFC8914 15 March 2021: Wouter - Fix double config.h include in configlexer.c - Fix to remove configyyrename from makedist.sh and also update the flex and bison rules there to add the "c_" prefix. 13 March 2021: Willem - Fix #154: TXT with parentheses fails in 4.3.5. - Align parsing of TXT elements with how bind does it. - A -p option to nsd-checkzone to print a successfully read zone. 12 March 2021: Wouter - Fix that wildcard is printed as a star instead of escaped, in logs and in written zone files. - Fix unit test for wildcard printout change. 11 March 2021: Wouter - Fix #163: A TSIG noncompliance with RFC 2845. 9 March 2021: Willem - Enable configuring a control-interface by interface name. 19 February 2021: Wouter - Fix segfault on high verbosity for TLS channels with dnstap log local address. 18 February 2021: Wouter - Fix #146 with #147: DNSTAP log the local address of the server with the dnstap logs. 16 February 2021: Wouter - Man page documentation for dnstap options. 8 February 2021: Wouter - Fix AF_LOCAL compile error for Solaris. - Fix ifaddrs compile error for Solaris. - Fix ifaddrs.h compile error for Solaris. 4 February 2021: Wouter - Merge PR #153 from fobser: Repair -fno-common linker errors automatically. - Fix uninitialized access of log_buf in error printout on apply ixfr. 26 January 2021: Wouter - Prevent a few more yacc clashes.
2022-09-24 20:35:00 +03:00
if(!ixfr_create_store_newsoa(*store, zone)) {
fclose(*spool);
ixfr_store_free(*store);
return 0;
}
return 1;
}
/* rename the other ixfr files */
static int ixfr_create_rename_and_delete_files(const char* zname,
const char* zoptsname, const char* zfile, uint32_t ixfr_number,
size_t ixfr_size, size_t cur_data_size)
{
size_t size_in_use = cur_data_size;
int dest_nr_files = (int)ixfr_number, maxsizehit = 0;
int num = 1;
while(ixfr_file_exists(zfile, num)) {
size_t fsize = 0;
if(!maxsizehit) {
if(!ixfr_read_header_data_size(zoptsname, zfile, num,
&fsize) || size_in_use + fsize > ixfr_size) {
/* no more than this because of storage size */
dest_nr_files = num;
maxsizehit = 1;
}
size_in_use += fsize;
}
num++;
}
num--;
/* num is now the number of ixfr files that exist */
while(num > 0) {
if(num+1 > dest_nr_files) {
(void)ixfr_unlink_it(zname, zfile, num, 0);
} else {
if(!ixfr_rename_it(zname, zfile, num, 0, num+1, 0))
return 0;
}
num--;
}
return 1;
}
/* finish up ixfr create processing */
static void ixfr_create_finishup(struct ixfr_create* ixfrcr,
struct ixfr_store* store, struct zone* zone, int append_mem,
struct nsd* nsd, const char* zfile, uint32_t ixfr_number)
{
char log_buf[1024], nowstr[128];
/* create the log message */
time_t now = time(NULL);
if(store->cancelled || ixfr_create_too_large(ixfrcr, store)) {
/* remove unneeded files.
* since this ixfr cannot be created the others are useless. */
ixfr_delete_superfluous_files(zone, zfile, 0);
return;
}
snprintf(nowstr, sizeof(nowstr), "%s", ctime(&now));
if(strchr(nowstr, '\n'))
*strchr(nowstr, '\n') = 0;
snprintf(log_buf, sizeof(log_buf),
"IXFR created by NSD %s for %s %u to %u of %u bytes at time %s",
PACKAGE_VERSION, wiredname2str(ixfrcr->zone_name),
(unsigned)ixfrcr->old_serial, (unsigned)ixfrcr->new_serial,
(unsigned)ixfr_data_size(store->data), nowstr);
store->data->log_str = strdup(log_buf);
if(!store->data->log_str) {
log_msg(LOG_ERR, "out of memory");
ixfr_store_free(store);
return;
}
if(!ixfr_create_rename_and_delete_files(
wiredname2str(ixfrcr->zone_name), zone->opts->name, zfile,
ixfr_number, ixfrcr->max_size, ixfr_data_size(store->data))) {
log_msg(LOG_ERR, "could not rename other ixfr files");
ixfr_store_free(store);
return;
}
if(!ixfr_write_file(zone, store->data, zfile, 1)) {
log_msg(LOG_ERR, "could not write to file");
ixfr_store_free(store);
return;
}
if(append_mem) {
ixfr_store_finish(store, nsd, log_buf);
}
}
void ixfr_readup_exist(struct zone* zone, struct nsd* nsd,
const char* zfile)
{
/* the .ixfr file already exists with the correct serial numbers
* on the disk. Read up the ixfr files from the drive and put them
* in memory. To match the zone that has just been read.
* We can skip ixfr creation, and read up the files from the drive.
* If the files on the drive are consistent, we end up with exactly
* those ixfrs and that zone in memory.
* Presumably, the user has used nsd-checkzone to create an IXFR
* file and has put a new zone file, so we read up the data that
* we should have now.
* This also takes into account the config on number and size. */
ixfr_read_from_file(nsd, zone, zfile);
}
int ixfr_create_perform(struct ixfr_create* ixfrcr, struct zone* zone,
int append_mem, struct nsd* nsd, const char* zfile,
uint32_t ixfr_number)
{
struct ixfr_store store_mem, *store;
FILE* spool;
if(!ixfr_perform_init(ixfrcr, zone, &store_mem, &store, &spool)) {
(void)unlink(ixfrcr->file_name);
return 0;
}
if(ixfrcr->new_serial == ixfrcr->old_serial ||
compare_serial(ixfrcr->new_serial, ixfrcr->old_serial)<0) {
log_msg(LOG_ERR, "zone %s ixfr could not be created because the serial is the same or moves backwards, from %u to %u",
wiredname2str(ixfrcr->zone_name),
(unsigned)ixfrcr->old_serial,
(unsigned)ixfrcr->new_serial);
ixfr_store_cancel(store);
fclose(spool);
ixfr_store_free(store);
(void)unlink(ixfrcr->file_name);
ixfr_delete_superfluous_files(zone, zfile, 0);
if(append_mem)
ixfr_store_delixfrs(zone);
return 0;
}
if(ixfr_create_already_done(ixfrcr, zone, zfile, 1)) {
ixfr_store_cancel(store);
fclose(spool);
ixfr_store_free(store);
(void)unlink(ixfrcr->file_name);
if(append_mem) {
ixfr_readup_exist(zone, nsd, zfile);
}
return 0;
}
if(!ixfr_create_walk_zone(spool, ixfrcr, store, zone)) {
fclose(spool);
ixfr_store_free(store);
(void)unlink(ixfrcr->file_name);
ixfr_delete_superfluous_files(zone, zfile, 0);
return 0;
}
if(store->data && !store->data->oldsoa) {
log_msg(LOG_ERR, "error spool file did not contain a SOA record");
fclose(spool);
ixfr_store_free(store);
(void)unlink(ixfrcr->file_name);
return 0;
}
if(!store->cancelled)
ixfr_store_finish_data(store);
fclose(spool);
(void)unlink(ixfrcr->file_name);
ixfr_create_finishup(ixfrcr, store, zone, append_mem, nsd, zfile,
ixfr_number);
return 1;
}
void ixfr_create_cancel(struct ixfr_create* ixfrcr)
{
if(!ixfrcr)
return;
(void)unlink(ixfrcr->file_name);
ixfr_create_free(ixfrcr);
}
int ixfr_create_from_difference(struct zone* zone, const char* zfile,
int* ixfr_create_already_done_flag)
{
uint32_t old_serial;
*ixfr_create_already_done_flag = 0;
/* only if the zone is ixfr enabled */
if(!zone_is_ixfr_enabled(zone))
return 0;
/* only if ixfr create is enabled */
if(!zone->opts->pattern->create_ixfr)
return 0;
/* only if there is a zone in memory to compare with */
if(!zone->soa_rrset || !zone->apex)
return 0;
old_serial = zone_get_current_serial(zone);
if(ixfr_create_already_done_serial(zone, zfile, 0, old_serial, 0)) {
*ixfr_create_already_done_flag = 1;
return 0;
}
return 1;
}