xfrout.c revision 553197e28833ed2d8bf26f8112eaa137dbaa040a
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley/*
a7038d1a0513c8e804937ebc95fc9cb3a46c04f5Mark Andrews * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Copyright (C) 1999-2003 Internet Software Consortium.
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley *
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley * Permission to use, copy, modify, and/or distribute this software for any
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley * purpose with or without fee is hereby granted, provided that the above
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence *
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
15a44745412679c30a6d022733925af70a38b715David Lawrence * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
15a44745412679c30a6d022733925af70a38b715David Lawrence * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
15a44745412679c30a6d022733925af70a38b715David Lawrence * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15a44745412679c30a6d022733925af70a38b715David Lawrence * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
15a44745412679c30a6d022733925af70a38b715David Lawrence * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15a44745412679c30a6d022733925af70a38b715David Lawrence * PERFORMANCE OF THIS SOFTWARE.
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley */
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews/* $Id: xfrout.c,v 1.143 2011/12/01 00:53:58 marka Exp $ */
9c3531d72aeaad6c5f01efe6a1c82023e1379e4dDavid Lawrence
e419f613d8591885df608cb73065921be07dd12eBob Halley#include <config.h>
e419f613d8591885df608cb73065921be07dd12eBob Halley
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence#include <isc/formatcheck.h>
fca5f81ad69098ea8abba130c7f841c951ef91c2Bob Halley#include <isc/mem.h>
e419f613d8591885df608cb73065921be07dd12eBob Halley#include <isc/timer.h>
e419f613d8591885df608cb73065921be07dd12eBob Halley#include <isc/print.h>
9695ae1c24b168996e3a267855dc754971ccb32cBob Halley#include <isc/stats.h>
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley#include <isc/util.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
1c776a2909632bc755f3fddd3b53addd792ab4d0Brian Wellington#include <dns/db.h>
e419f613d8591885df608cb73065921be07dd12eBob Halley#include <dns/dbiterator.h>
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley#include <dns/dlz.h>
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson#include <dns/fixedname.h>
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington#include <dns/journal.h>
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#include <dns/message.h>
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews#include <dns/peer.h>
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley#include <dns/rdataclass.h>
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington#include <dns/rdatalist.h>
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley#include <dns/rdataset.h>
09f22ac5b09e70bc526015f37168ba33e21ea91fDavid Lawrence#include <dns/rdatasetiter.h>
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington#include <dns/result.h>
09f22ac5b09e70bc526015f37168ba33e21ea91fDavid Lawrence#include <dns/rriterator.h>
09f22ac5b09e70bc526015f37168ba33e21ea91fDavid Lawrence#include <dns/soa.h>
e419f613d8591885df608cb73065921be07dd12eBob Halley#include <dns/stats.h>
e419f613d8591885df608cb73065921be07dd12eBob Halley#include <dns/timer.h>
92ef1a9b9dbd48ecb507b42ac62c15afefdaf838David Lawrence#include <dns/tsig.h>
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews#include <dns/view.h>
bf43fdafa3bff9e84cb03f1a19aca74514d2516eBob Halley#include <dns/zone.h>
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley#include <dns/zt.h>
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington
6bc1a645619a14707da68b130dafe41721fd2f25Brian Wellington#include <named/client.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <named/log.h>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#include <named/server.h>
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley#include <named/xfrout.h>
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence/*! \file
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * \brief
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence * Outgoing AXFR and IXFR.
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington */
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence/*
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * TODO:
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * - IXFR over UDP
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence */
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#define XFROUT_COMMON_LOGARGS \
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ns_g_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington#define XFROUT_PROTOCOL_LOGARGS \
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews XFROUT_COMMON_LOGARGS, ISC_LOG_INFO
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington#define XFROUT_DEBUG_LOGARGS(n) \
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence XFROUT_COMMON_LOGARGS, ISC_LOG_DEBUG(n)
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington#define XFROUT_RR_LOGARGS \
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington XFROUT_COMMON_LOGARGS, XFROUT_RR_LOGLEVEL
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington#define XFROUT_RR_LOGLEVEL ISC_LOG_DEBUG(8)
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence/*%
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafsson * Fail unconditionally and log as a client error.
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafsson * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson * from complaining about "end-of-loop code not reached".
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#define FAILC(code, msg) \
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews do { \
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = (code); \
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley "bad zone transfer request: %s (%s)", \
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley msg, isc_result_totext(code)); \
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (result != ISC_R_SUCCESS) goto failure; \
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington } while (0)
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley#define FAILQ(code, msg, question, rdclass) \
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley do { \
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley char _buf1[DNS_NAME_FORMATSIZE]; \
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley char _buf2[DNS_RDATACLASS_FORMATSIZE]; \
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley result = (code); \
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington dns_name_format(question, _buf1, sizeof(_buf1)); \
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff dns_rdataclass_format(rdclass, _buf2, sizeof(_buf2)); \
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff "bad zone transfer request: '%s/%s': %s (%s)", \
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff _buf1, _buf2, msg, isc_result_totext(code)); \
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (result != ISC_R_SUCCESS) goto failure; \
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley } while (0)
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews#define CHECK(op) \
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews do { result = (op); \
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS) goto failure; \
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } while (0)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/**************************************************************************/
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic inline void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsinc_stats(dns_zone_t *zone, isc_statscounter_t counter) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_stats_increment(ns_g_server->nsstats, counter);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (zone != NULL) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (zonestats != NULL)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_stats_increment(zonestats, counter);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington/**************************************************************************/
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington/*% Log an RR (for debugging) */
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellingtonstatic void
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellingtonlog_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) {
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington isc_result_t result;
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington isc_buffer_t buf;
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington char mem[2000];
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington dns_rdatalist_t rdl;
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington dns_rdataset_t rds;
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington dns_rdata_t rd = DNS_RDATA_INIT;
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington rdl.type = rdata->type;
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington rdl.rdclass = rdata->rdclass;
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington rdl.ttl = ttl;
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington if (rdata->type == dns_rdatatype_sig ||
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington rdata->type == dns_rdatatype_rrsig)
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington rdl.covers = dns_rdata_covers(rdata);
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington else
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington rdl.covers = dns_rdatatype_none;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews ISC_LIST_INIT(rdl.rdata);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews ISC_LINK_INIT(&rdl, link);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dns_rdataset_init(&rds);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dns_rdata_init(&rd);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews dns_rdata_clone(rdata, &rd);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews ISC_LIST_APPEND(rdl.rdata, &rd, link);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_buffer_init(&buf, mem, sizeof(mem));
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews result = dns_rdataset_totext(&rds, name,
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews ISC_FALSE, ISC_FALSE, &buf);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews /*
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * We could use xfrout_log(), but that would produce
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * very long lines with a repetitive prefix.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews */
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews if (result == ISC_R_SUCCESS) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews /*
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Get rid of final newline.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews */
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews INSIST(buf.used >= 1 &&
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews ((char *) buf.base)[buf.used - 1] == '\n');
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews buf.used--;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_log_write(XFROUT_RR_LOGARGS, "%.*s",
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews (int)isc_buffer_usedlength(&buf),
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews (char *)isc_buffer_base(&buf));
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews } else {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>");
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews }
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews}
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews/**************************************************************************/
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington/*
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington * An 'rrstream_t' is a polymorphic iterator that returns
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington * a stream of resource records. There are multiple implementations,
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington * e.g. for generating AXFR and IXFR records streams.
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellingtontypedef struct rrstream_methods rrstream_methods_t;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellingtontypedef struct rrstream {
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington isc_mem_t *mctx;
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff rrstream_methods_t *methods;
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington} rrstream_t;
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonstruct rrstream_methods {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington isc_result_t (*first)(rrstream_t *);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington isc_result_t (*next)(rrstream_t *);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington void (*current)(rrstream_t *,
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_name_t **,
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington isc_uint32_t *,
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington dns_rdata_t **);
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington void (*pause)(rrstream_t *);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson void (*destroy)(rrstream_t **);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington};
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafssonstatic void
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellingtonrrstream_noop_pause(rrstream_t *rs) {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington UNUSED(rs);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington}
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington/**************************************************************************/
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington/*
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * an IXFR-like RR stream from a journal file.
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington *
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington * The SOA at the beginning of each sequence of additions
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * or deletions are included in the stream, but the extra
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington * SOAs at the beginning and end of the entire transfer are
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellington * not included.
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson */
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellingtontypedef struct ixfr_rrstream {
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington rrstream_t common;
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington dns_journal_t *journal;
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington} ixfr_rrstream_t;
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellington/* Forward declarations. */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonixfr_rrstream_destroy(rrstream_t **sp);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic rrstream_methods_t ixfr_rrstream_methods;
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington/*
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington * Returns: anything dns_journal_open() or dns_journal_iter_init()
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * may return.
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington */
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic isc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsixfr_rrstream_create(isc_mem_t *mctx,
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington const char *journal_filename,
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington isc_uint32_t begin_serial,
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington isc_uint32_t end_serial,
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington rrstream_t **sp)
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington{
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington ixfr_rrstream_t *s;
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington isc_result_t result;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington INSIST(sp != NULL && *sp == NULL);
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews s = isc_mem_get(mctx, sizeof(*s));
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington if (s == NULL)
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington return (ISC_R_NOMEMORY);
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington s->common.mctx = mctx;
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington s->common.methods = &ixfr_rrstream_methods;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews s->journal = NULL;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington CHECK(dns_journal_open(mctx, journal_filename,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ISC_FALSE, &s->journal));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *sp = (rrstream_t *) s;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (ISC_R_SUCCESS);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews failure:
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ixfr_rrstream_destroy((rrstream_t **) (void *)&s);
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic isc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsixfr_rrstream_first(rrstream_t *rs) {
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington return (dns_journal_first_rr(s->journal));
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellington}
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic isc_result_t
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellingtonixfr_rrstream_next(rrstream_t *rs) {
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington return (dns_journal_next_rr(s->journal));
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellingtonstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsixfr_rrstream_current(rrstream_t *rs,
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_name_t **name, isc_uint32_t *ttl,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdata_t **rdata)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews{
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_journal_current_rr(s->journal, name, ttl, rdata);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsixfr_rrstream_destroy(rrstream_t **rsp) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (s->journal != 0)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_journal_destroy(&s->journal);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_mem_put(s->common.mctx, s, sizeof(*s));
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic rrstream_methods_t ixfr_rrstream_methods = {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ixfr_rrstream_first,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ixfr_rrstream_next,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ixfr_rrstream_current,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews rrstream_noop_pause,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ixfr_rrstream_destroy
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews};
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/**************************************************************************/
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington/*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * An 'axfr_rrstream_t' is an 'rrstream_t' that returns
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * an AXFR-like RR stream from a database.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * The SOAs at the beginning and end of the transfer are
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * not included in the stream.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewstypedef struct axfr_rrstream {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews rrstream_t common;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rriterator_t it;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_boolean_t it_valid;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews} axfr_rrstream_t;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews/*
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Forward declarations.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews */
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsstatic void
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsaxfr_rrstream_destroy(rrstream_t **rsp);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic rrstream_methods_t axfr_rrstream_methods;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic isc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsaxfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews rrstream_t **sp)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews{
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews axfr_rrstream_t *s;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_result_t result;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(sp != NULL && *sp == NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews s = isc_mem_get(mctx, sizeof(*s));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (s == NULL)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (ISC_R_NOMEMORY);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews s->common.mctx = mctx;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews s->common.methods = &axfr_rrstream_methods;
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews s->it_valid = ISC_FALSE;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_rriterator_init(&s->it, db, ver, 0));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews s->it_valid = ISC_TRUE;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington *sp = (rrstream_t *) s;
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington return (ISC_R_SUCCESS);
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington failure:
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington axfr_rrstream_destroy((rrstream_t **) (void *)&s);
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonstatic isc_result_t
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellingtonaxfr_rrstream_first(rrstream_t *rs) {
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff isc_result_t result;
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington result = dns_rriterator_first(&s->it);
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington if (result != ISC_R_SUCCESS)
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington return (result);
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington /* Skip SOA records. */
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington for (;;) {
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington dns_name_t *name_dummy = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_uint32_t ttl_dummy;
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington dns_rdata_t *rdata = NULL;
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington dns_rriterator_current(&s->it, &name_dummy,
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington &ttl_dummy, NULL, &rdata);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson if (rdata->type != dns_rdatatype_soa)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington break;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington result = dns_rriterator_next(&s->it);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson if (result != ISC_R_SUCCESS)
76c8294c81fb48b1da6e1fc5b83322a4cedb8e58Andreas Gustafsson break;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington }
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington return (result);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington}
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonstatic isc_result_t
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellingtonaxfr_rrstream_next(rrstream_t *rs) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington isc_result_t result;
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellington
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson /* Skip SOA records. */
1b1e1fda4638334b484aa38c15f53a131c0b0fdfAndreas Gustafsson for (;;) {
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellington dns_name_t *name_dummy = NULL;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington isc_uint32_t ttl_dummy;
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellington dns_rdata_t *rdata = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_rriterator_next(&s->it);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews break;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rriterator_current(&s->it, &name_dummy,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews &ttl_dummy, NULL, &rdata);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (rdata->type != dns_rdatatype_soa)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews break;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsaxfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdata_t **rdata)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews{
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rriterator_current(&s->it, name, ttl, NULL, rdata);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsaxfr_rrstream_pause(rrstream_t *rs) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rriterator_pause(&s->it);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellingtonstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsaxfr_rrstream_destroy(rrstream_t **rsp) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (s->it_valid)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rriterator_destroy(&s->it);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_mem_put(s->common.mctx, s, sizeof(*s));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic rrstream_methods_t axfr_rrstream_methods = {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews axfr_rrstream_first,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews axfr_rrstream_next,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews axfr_rrstream_current,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews axfr_rrstream_pause,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews axfr_rrstream_destroy
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews};
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/**************************************************************************/
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * a single SOA record.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtontypedef struct soa_rrstream {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington rrstream_t common;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_difftuple_t *soa_tuple;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews} soa_rrstream_t;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington/*
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * Forward declarations.
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews */
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrewsstatic void
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonsoa_rrstream_destroy(rrstream_t **rsp);
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrewsstatic rrstream_methods_t soa_rrstream_methods;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrewsstatic isc_result_t
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrewssoa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews rrstream_t **sp)
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews{
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews soa_rrstream_t *s;
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews isc_result_t result;
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews INSIST(sp != NULL && *sp == NULL);
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson s = isc_mem_get(mctx, sizeof(*s));
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews if (s == NULL)
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington return (ISC_R_NOMEMORY);
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington s->common.mctx = mctx;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews s->common.methods = &soa_rrstream_methods;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington s->soa_tuple = NULL;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews &s->soa_tuple));
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington *sp = (rrstream_t *) s;
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews return (ISC_R_SUCCESS);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews failure:
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews soa_rrstream_destroy((rrstream_t **) (void *)&s);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews return (result);
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews}
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonstatic isc_result_t
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafssonsoa_rrstream_first(rrstream_t *rs) {
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson UNUSED(rs);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington return (ISC_R_SUCCESS);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington}
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewsstatic isc_result_t
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafssonsoa_rrstream_next(rrstream_t *rs) {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington UNUSED(rs);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington return (ISC_R_NOMORE);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington}
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonstatic void
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewssoa_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
d1cbf714097e900ed1703529584d3e1a50e8a4a8Brian Wellington dns_rdata_t **rdata)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington{
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews soa_rrstream_t *s = (soa_rrstream_t *) rs;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington *name = &s->soa_tuple->name;
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews *ttl = s->soa_tuple->ttl;
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews *rdata = &s->soa_tuple->rdata;
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews}
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewsstatic void
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrewssoa_rrstream_destroy(rrstream_t **rsp) {
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews soa_rrstream_t *s = (soa_rrstream_t *) *rsp;
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews if (s->soa_tuple != NULL)
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews dns_difftuple_free(&s->soa_tuple);
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews isc_mem_put(s->common.mctx, s, sizeof(*s));
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews}
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrewsstatic rrstream_methods_t soa_rrstream_methods = {
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews soa_rrstream_first,
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews soa_rrstream_next,
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews soa_rrstream_current,
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews rrstream_noop_pause,
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews soa_rrstream_destroy
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews};
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews/**************************************************************************/
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews/*
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews * A 'compound_rrstream_t' objects owns a soa_rrstream
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * and another rrstream, the "data stream". It returns
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews * a concatenated stream consisting of the soa_rrstream, then
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews * the data stream, then the soa_rrstream again.
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews *
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews * The component streams are owned by the compound_rrstream_t
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * and are destroyed with it.
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews */
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrewstypedef struct compound_rrstream {
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews rrstream_t common;
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews rrstream_t *components[3];
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews int state;
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews isc_result_t result;
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews} compound_rrstream_t;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews/*
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * Forward declarations.
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews */
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrewsstatic void
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewscompound_rrstream_destroy(rrstream_t **rsp);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewsstatic isc_result_t
638fe804a524ee0c028863c0301b999c79de7651Mark Andrewscompound_rrstream_next(rrstream_t *rs);
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewsstatic rrstream_methods_t compound_rrstream_methods;
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews/*
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews * Requires:
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews * soa_stream != NULL && *soa_stream != NULL
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * data_stream != NULL && *data_stream != NULL
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews * sp != NULL && *sp == NULL
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews *
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * Ensures:
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington * *soa_stream == NULL
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington * *data_stream == NULL
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews * *sp points to a valid compound_rrstream_t
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * The soa and data streams will be destroyed
8b5de9701428e2b5eb50aba96af23dc1186124ddMark Andrews * when the compound_rrstream_t is destroyed.
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonstatic isc_result_t
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewscompound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream,
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington rrstream_t **data_stream, rrstream_t **sp)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington{
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington compound_rrstream_t *s;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson INSIST(sp != NULL && *sp == NULL);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews s = isc_mem_get(mctx, sizeof(*s));
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington if (s == NULL)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington return (ISC_R_NOMEMORY);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson s->common.mctx = mctx;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews s->common.methods = &compound_rrstream_methods;
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews s->components[0] = *soa_stream;
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews s->components[1] = *data_stream;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews s->components[2] = *soa_stream;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews s->state = -1;
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrews s->result = ISC_R_FAILURE;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews *soa_stream = NULL;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews *data_stream = NULL;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington *sp = (rrstream_t *) s;
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson return (ISC_R_SUCCESS);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews}
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewsstatic isc_result_t
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewscompound_rrstream_first(rrstream_t *rs) {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington compound_rrstream_t *s = (compound_rrstream_t *) rs;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington s->state = 0;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington do {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington rrstream_t *curstream = s->components[s->state];
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington s->result = curstream->methods->first(curstream);
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington } while (s->result == ISC_R_NOMORE && s->state < 2);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington return (s->result);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington}
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellingtonstatic isc_result_t
e27021ee1f37185ab839a7a3b6bc078c24255e62Brian Wellingtoncompound_rrstream_next(rrstream_t *rs) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews compound_rrstream_t *s = (compound_rrstream_t *) rs;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington rrstream_t *curstream = s->components[s->state];
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington s->result = curstream->methods->next(curstream);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington while (s->result == ISC_R_NOMORE) {
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington /*
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington * Make sure locks held by the current stream
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington * are released before we switch streams.
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington */
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington curstream->methods->pause(curstream);
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington if (s->state == 2)
b0d31c78bc24080d4c470a8bd98862375f6e3055Mark Andrews return (ISC_R_NOMORE);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews s->state++;
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington curstream = s->components[s->state];
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington s->result = curstream->methods->first(curstream);
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington }
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson return (s->result);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington}
b0d31c78bc24080d4c470a8bd98862375f6e3055Mark Andrews
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafssonstatic void
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellingtoncompound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
b0d31c78bc24080d4c470a8bd98862375f6e3055Mark Andrews dns_rdata_t **rdata)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews{
f15af68028adc665d3bdddf955fc52bad83f0514Brian Wellington compound_rrstream_t *s = (compound_rrstream_t *) rs;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews rrstream_t *curstream;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews INSIST(0 <= s->state && s->state < 3);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(s->result == ISC_R_SUCCESS);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews curstream = s->components[s->state];
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews curstream->methods->current(curstream, name, ttl, rdata);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington}
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
86f6b92e35c7bdb5fc1fd1021af75b981863313eMark Andrewsstatic void
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewscompound_rrstream_pause(rrstream_t *rs)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington{
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington compound_rrstream_t *s = (compound_rrstream_t *) rs;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews rrstream_t *curstream;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington INSIST(0 <= s->state && s->state < 3);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington curstream = s->components[s->state];
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington curstream->methods->pause(curstream);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewscompound_rrstream_destroy(rrstream_t **rsp) {
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington compound_rrstream_t *s = (compound_rrstream_t *) *rsp;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington s->components[0]->methods->destroy(&s->components[0]);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington s->components[1]->methods->destroy(&s->components[1]);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington s->components[2] = NULL; /* Copy of components[0]. */
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington isc_mem_put(s->common.mctx, s, sizeof(*s));
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington}
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellingtonstatic rrstream_methods_t compound_rrstream_methods = {
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington compound_rrstream_first,
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington compound_rrstream_next,
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington compound_rrstream_current,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews compound_rrstream_pause,
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington compound_rrstream_destroy
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington};
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington/**************************************************************************/
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington/*
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington * An 'xfrout_ctx_t' contains the state of an outgoing AXFR or IXFR
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington * in progress.
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington */
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewstypedef struct {
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington isc_mem_t *mctx;
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington ns_client_t *client;
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington unsigned int id; /* ID of request */
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson dns_name_t *qname; /* Question name of request */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdatatype_t qtype; /* dns_rdatatype_{a,i}xfr */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdataclass_t qclass;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_zone_t *zone; /* (necessary for stats) */
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson dns_db_t *db;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_dbversion_t *ver;
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington isc_quota_t *quota;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington rrstream_t *stream; /* The XFR RR stream */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington isc_boolean_t end_of_stream; /* EOS has been reached */
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson isc_buffer_t buf; /* Buffer for message owner
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington names and rdatas */
18b7133679efa8f60fd4e396c628576f3f416b3eBrian Wellington isc_buffer_t txlenbuf; /* Transmit length buffer */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington isc_buffer_t txbuf; /* Transmit message buffer */
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington void *txmem;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned int txmemlen;
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington unsigned int nmsg; /* Number of messages sent */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_tsigkey_t *tsigkey; /* Key used to create TSIG */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_t *lasttsig; /* the last TSIG */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_boolean_t many_answers;
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington int sends; /* Send in progress */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_boolean_t shuttingdown;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews const char *mnemonic; /* Style of transfer */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington} xfrout_ctx_t;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic isc_result_t
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client,
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington unsigned int id, dns_name_t *qname, dns_rdatatype_t qtype,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataclass_t qclass, dns_zone_t *zone,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews rrstream_t *stream, dns_tsigkey_t *tsigkey,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_t *lasttsig,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned int maxtime,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned int idletime,
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington isc_boolean_t many_answers,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfrout_ctx_t **xfrp);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellingtonsendstream(xfrout_ctx_t *xfr);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_senddone(isc_task_t *task, isc_event_t *event);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_maybe_destroy(xfrout_ctx_t *xfr);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellingtonstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_ctx_destroy(xfrout_ctx_t **xfrp);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellingtonstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_client_shutdown(void *arg, isc_result_t result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_log1(ns_client_t *client, dns_name_t *zonename,
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdataclass_t rdclass, int level,
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ISC_FORMAT_PRINTF(3, 4);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/**************************************************************************/
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsvoid
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_result_t result;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_t *question_name;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataset_t *question_rdataset;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_zone_t *zone = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_db_t *db = NULL;
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington dns_dbversion_t *ver = NULL;
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington dns_rdataclass_t question_class;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews rrstream_t *soa_stream = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews rrstream_t *data_stream = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews rrstream_t *stream = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_difftuple_t *current_soa_tuple = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_t *soa_name;
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington dns_rdataset_t *soa_rdataset;
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington dns_rdata_t soa_rdata = DNS_RDATA_INIT;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_boolean_t have_soa = ISC_FALSE;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews const char *mnemonic = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_mem_t *mctx = client->mctx;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_message_t *request = client->message;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfrout_ctx_t *xfr = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_quota_t *quota = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_transfer_format_t format = client->view->transfer_format;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_netaddr_t na;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_peer_t *peer = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_t *tsigbuf = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews char *journalfile;
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington char keyname[DNS_NAME_FORMATSIZE];
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson isc_boolean_t is_poll = ISC_FALSE;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson isc_boolean_t is_dlz = ISC_FALSE;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson switch (reqtype) {
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson case dns_rdatatype_axfr:
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington mnemonic = "AXFR";
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson break;
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington case dns_rdatatype_ixfr:
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews mnemonic = "IXFR";
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley break;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley default:
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley INSIST(0);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley break;
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews }
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington ns_client_log(client,
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington ISC_LOG_DEBUG(6), "%s request", mnemonic);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington /*
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * Apply quota.
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington */
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington result = isc_quota_attach(&ns_g_server->xfroutquota, &quota);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington if (result != ISC_R_SUCCESS) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley "%s request denied: %s", mnemonic,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley isc_result_totext(result));
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington goto failure;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley /*
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence * Interpret the question section.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley result = dns_message_firstname(request, DNS_SECTION_QUESTION);
5c29047792191d6141f69b2684314d0b762fedebBrian Wellington INSIST(result == ISC_R_SUCCESS);
5c29047792191d6141f69b2684314d0b762fedebBrian Wellington
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley /*
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington * The question section must contain exactly one question, and
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * it must be for AXFR/IXFR as appropriate.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington question_name = NULL;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
63bf060be4ff2a7ade02fd86abb98694a5afc250Brian Wellington question_rdataset = ISC_LIST_HEAD(question_name->list);
63bf060be4ff2a7ade02fd86abb98694a5afc250Brian Wellington question_class = question_rdataset->rdclass;
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington INSIST(question_rdataset->type == reqtype);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington if (ISC_LIST_NEXT(question_rdataset, link) != NULL)
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington FAILC(DNS_R_FORMERR, "multiple questions");
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington result = dns_message_nextname(request, DNS_SECTION_QUESTION);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington if (result != ISC_R_NOMORE)
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington FAILC(DNS_R_FORMERR, "multiple questions");
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
c50936eb40263b65ebf6afe4e6556e2dc67c10e4Brian Wellington &zone);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (result != ISC_R_SUCCESS) {
c50936eb40263b65ebf6afe4e6556e2dc67c10e4Brian Wellington /*
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews * Normal zone table does not have a match.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Try the DLZ database
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (client->view->dlzdatabase != NULL) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley result = dns_dlzallowzonexfr(client->view,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley question_name,
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington &client->peeraddr,
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington &db);
c50936eb40263b65ebf6afe4e6556e2dc67c10e4Brian Wellington
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington if (result == ISC_R_NOPERM) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley char _buf1[DNS_NAME_FORMATSIZE];
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley char _buf2[DNS_RDATACLASS_FORMATSIZE];
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington result = DNS_R_REFUSED;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews dns_name_format(question_name, _buf1,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley sizeof(_buf1));
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_rdataclass_format(question_class,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley _buf2, sizeof(_buf2));
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley NS_LOGMODULE_XFER_OUT,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley ISC_LOG_ERROR,
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington "zone transfer '%s/%s' denied",
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington _buf1, _buf2);
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington goto failure;
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (result != ISC_R_SUCCESS)
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley question_name, question_class);
a9ba7e65644c50e1549b38150ba8d4787e1fe643Brian Wellington is_dlz = ISC_TRUE;
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington /*
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * DLZ only support full zone transfer, not incremental
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (reqtype != dns_rdatatype_axfr) {
78951552dccf0d0004d61072bbc71fa4b1aab30fAndreas Gustafsson mnemonic = "AXFR-style IXFR";
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews reqtype = dns_rdatatype_axfr;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
78951552dccf0d0004d61072bbc71fa4b1aab30fAndreas Gustafsson
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews } else {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
78951552dccf0d0004d61072bbc71fa4b1aab30fAndreas Gustafsson * not DLZ and not in normal zone table, we are
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * not authoritative
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews question_name, question_class);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else {
a9ba7e65644c50e1549b38150ba8d4787e1fe643Brian Wellington /* zone table has a match */
a9ba7e65644c50e1549b38150ba8d4787e1fe643Brian Wellington switch(dns_zone_gettype(zone)) {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley case dns_zone_master:
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley case dns_zone_slave:
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley case dns_zone_dlz:
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews break; /* Master and slave zones are OK for transfer. */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley default:
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley CHECK(dns_zone_getdb(zone, &db));
77c67dfb2607618f5e7940486daebafd42a502abBrian Wellington dns_db_currentversion(db, &ver);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington }
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley "%s question section OK", mnemonic);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Check the authority section. Look for a SOA record with
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * the same name and class as the question.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result == ISC_R_SUCCESS;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington {
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington soa_name = NULL;
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington dns_message_currentname(request, DNS_SECTION_AUTHORITY,
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington &soa_name);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington /*
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * Ignore data whose owner name is not the zone apex.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington if (! dns_name_equal(soa_name, question_name))
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington continue;
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington soa_rdataset != NULL;
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington {
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington /*
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * Ignore non-SOA data.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (soa_rdataset->type != dns_rdatatype_soa)
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley continue;
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson if (soa_rdataset->rdclass != question_class)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington continue;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
77c67dfb2607618f5e7940486daebafd42a502abBrian Wellington CHECK(dns_rdataset_first(soa_rdataset));
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_rdataset_current(soa_rdataset, &soa_rdata);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley result = dns_rdataset_next(soa_rdataset);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (result == ISC_R_SUCCESS)
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley FAILC(DNS_R_FORMERR,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley "IXFR authority section "
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley "has multiple SOAs");
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley have_soa = ISC_TRUE;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley goto got_soa;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley got_soa:
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (result != ISC_R_NOMORE)
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley CHECK(result);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington "%s authority section OK", mnemonic);
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington /*
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * If not a DLZ zone, decide whether to allow this transfer.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley if (!is_dlz) {
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington ns_client_aclmsg("zone transfer", question_name, reqtype,
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington client->view->rdclass, msg, sizeof(msg));
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley CHECK(ns_client_checkacl(client, NULL, msg,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley dns_zone_getxfracl(zone),
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley ISC_TRUE, ISC_LOG_ERROR));
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley /*
77c67dfb2607618f5e7940486daebafd42a502abBrian Wellington * AXFR over UDP is not possible.
77c67dfb2607618f5e7940486daebafd42a502abBrian Wellington */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington if (reqtype == dns_rdatatype_axfr &&
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington (client->attributes & NS_CLIENTATTR_TCP) == 0)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley /*
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Look up the requesting server in the peer table.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_netaddr_fromsockaddr(&na, &client->peeraddr);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Decide on the transfer format (one-answer or many-answers).
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (peer != NULL)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews (void)dns_peer_gettransferformat(peer, &format);
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington * Get a dynamically allocated copy of the current SOA.
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (is_dlz)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_db_currentversion(db, &ver);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews &current_soa_tuple));
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (reqtype == dns_rdatatype_ixfr) {
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington isc_uint32_t begin_serial, current_serial;
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington isc_boolean_t provide_ixfr;
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Outgoing IXFR may have been disabled for this peer
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * or globally.
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington */
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington provide_ixfr = client->view->provideixfr;
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington if (peer != NULL)
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington (void) dns_peer_getprovideixfr(peer, &provide_ixfr);
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington if (provide_ixfr == ISC_FALSE)
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews goto axfr_fallback;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (! have_soa)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews FAILC(DNS_R_FORMERR,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "IXFR request missing SOA");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews begin_serial = dns_soa_getserial(&soa_rdata);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews current_serial = dns_soa_getserial(&current_soa_tuple->rdata);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * RFC1995 says "If an IXFR query with the same or
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington * newer version number than that of the server
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * is received, it is replied to with a single SOA
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * record of the server's current version, just as
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * in AXFR". The claim about AXFR is incorrect,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * but other than that, we do as the RFC says.
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Sending a single SOA record is also how we refuse
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * IXFR over UDP (currently, we always do).
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (DNS_SERIAL_GE(begin_serial, current_serial) ||
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews (client->attributes & NS_CLIENTATTR_TCP) == 0)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(soa_rrstream_create(mctx, db, ver, &stream));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews is_poll = ISC_TRUE;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews goto have_stream;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews journalfile = dns_zone_getjournal(zone);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (journalfile != NULL)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = ixfr_rrstream_create(mctx,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews journalfile,
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington begin_serial,
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington current_serial,
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson &data_stream);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews else
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson result = ISC_R_NOTFOUND;
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson if (result == ISC_R_NOTFOUND ||
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson result == ISC_R_RANGE) {
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson xfrout_log1(client, question_name, question_class,
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson ISC_LOG_DEBUG(4),
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson "IXFR version not in journal, "
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson "falling back to AXFR");
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington mnemonic = "AXFR-style IXFR";
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley goto axfr_fallback;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley CHECK(result);
c03bb27f0675a6e60ceea66b451548e8481bc05cMark Andrews } else {
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley axfr_fallback:
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley CHECK(axfr_rrstream_create(mctx, db, ver,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley &data_stream));
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley }
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley /*
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Bracket the data stream with SOAs.
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson */
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
78951552dccf0d0004d61072bbc71fa4b1aab30fAndreas Gustafsson CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence &stream));
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson soa_stream = NULL;
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson data_stream = NULL;
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley have_stream:
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson /*
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson * Create the xfrout context object. This transfers the ownership
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson * of "stream", "db", "ver", and "quota" to the xfrout context object.
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson */
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington if (is_dlz)
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington CHECK(xfrout_ctx_create(mctx, client, request->id,
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington question_name, reqtype, question_class,
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington zone, db, ver, quota, stream,
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington dns_message_gettsigkey(request),
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington tsigbuf,
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson 3600,
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson 3600,
1f1d36a87b65186d9f89aac7f456ab1fd2a39ef6Andreas Gustafsson (format == dns_many_answers) ?
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence ISC_TRUE : ISC_FALSE,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley &xfr));
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley else
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley CHECK(xfrout_ctx_create(mctx, client, request->id,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley question_name, reqtype, question_class,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley zone, db, ver, quota, stream,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence dns_message_gettsigkey(request),
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley tsigbuf,
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington dns_zone_getmaxxfrout(zone),
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson dns_zone_getidleout(zone),
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson (format == dns_many_answers) ?
0a3e2e1d590dac7fb011e72bd3a4982c179d8e68Brian Wellington ISC_TRUE : ISC_FALSE,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley &xfr));
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley xfr->mnemonic = mnemonic;
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington stream = NULL;
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington quota = NULL;
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington CHECK(xfr->stream->methods->first(xfr->stream));
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington if (xfr->tsigkey != NULL)
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington else
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington keyname[0] = '\0';
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington if (is_poll)
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington xfrout_log1(client, question_name, question_class,
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews else
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington xfrout_log1(client, question_name, question_class,
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington ISC_LOG_INFO, "%s started%s%s", mnemonic,
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington /*
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington * Hand the context over to sendstream(). Set xfr to NULL;
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington * sendstream() is responsible for either passing the
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington * context on to a later event handler or destroying it.
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington */
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington sendstream(xfr);
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington xfr = NULL;
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington result = ISC_R_SUCCESS;
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington failure:
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington if (result == DNS_R_REFUSED)
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington inc_stats(zone, dns_nsstatscounter_xfrrej);
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington if (quota != NULL)
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington isc_quota_detach(&quota);
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington if (current_soa_tuple != NULL)
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington dns_difftuple_free(&current_soa_tuple);
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington if (stream != NULL)
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington stream->methods->destroy(&stream);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson if (soa_stream != NULL)
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington soa_stream->methods->destroy(&soa_stream);
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington if (data_stream != NULL)
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington data_stream->methods->destroy(&data_stream);
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington if (ver != NULL)
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington dns_db_closeversion(db, &ver, ISC_FALSE);
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington if (db != NULL)
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington dns_db_detach(&db);
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington if (zone != NULL)
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington dns_zone_detach(&zone);
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington /* XXX kludge */
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington if (xfr != NULL) {
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington xfrout_fail(xfr, result, "setting up zone transfer");
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington } else if (result != ISC_R_SUCCESS) {
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington NS_LOGMODULE_XFER_OUT,
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington ISC_LOG_DEBUG(3), "zone transfer setup failed");
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington ns_client_error(client, result);
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington }
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington}
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonstatic isc_result_t
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonxfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington dns_name_t *qname, dns_rdatatype_t qtype,
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdataclass_t qclass, dns_zone_t *zone,
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington dns_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
187604c1adfe841d909d4a8453b6900e652f7f6dBrian Wellington rrstream_t *stream, dns_tsigkey_t *tsigkey,
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington isc_buffer_t *lasttsig, unsigned int maxtime,
538fea1c91c68c0a5569c7b8552c8fd0490055efBrian Wellington unsigned int idletime, isc_boolean_t many_answers,
538fea1c91c68c0a5569c7b8552c8fd0490055efBrian Wellington xfrout_ctx_t **xfrp)
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson{
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington xfrout_ctx_t *xfr;
538fea1c91c68c0a5569c7b8552c8fd0490055efBrian Wellington isc_result_t result;
25276bd1ecb372b82c9235648e5defab0655dcd5Mark Andrews unsigned int len;
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson void *mem;
777ac454c0cdec27dc11d80b9b2a8d7239d833a8Brian Wellington
e49c834de8cdf92d4b85ef0fbf1d9dc59620a342Brian Wellington INSIST(xfrp != NULL && *xfrp == NULL);
25276bd1ecb372b82c9235648e5defab0655dcd5Mark Andrews xfr = isc_mem_get(mctx, sizeof(*xfr));
25276bd1ecb372b82c9235648e5defab0655dcd5Mark Andrews if (xfr == NULL)
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson return (ISC_R_NOMEMORY);
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington xfr->mctx = NULL;
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson isc_mem_attach(mctx, &xfr->mctx);
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington xfr->client = NULL;
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington ns_client_attach(client, &xfr->client);
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington xfr->id = id;
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington xfr->qname = qname;
e1f16346db02486f751c6db683fffe53c866c186Andreas Gustafsson xfr->qtype = qtype;
e1f16346db02486f751c6db683fffe53c866c186Andreas Gustafsson xfr->qclass = qclass;
e1f16346db02486f751c6db683fffe53c866c186Andreas Gustafsson xfr->zone = NULL;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley xfr->db = NULL;
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley xfr->ver = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (zone != NULL) /* zone will be NULL if it's DLZ */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_zone_attach(zone, &xfr->zone);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_db_attach(db, &xfr->db);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_db_attachversion(db, ver, &xfr->ver);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->end_of_stream = ISC_FALSE;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->tsigkey = tsigkey;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->lasttsig = lasttsig;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->txmem = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->txmemlen = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->nmsg = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->many_answers = many_answers,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->sends = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->shuttingdown = ISC_FALSE;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->mnemonic = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->buf.base = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->buf.length = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->txmem = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->txmemlen = 0;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->stream = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->quota = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews /*
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * Allocate a temporary buffer for the uncompressed response
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * message data. The size should be no more than 65535 bytes
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * so that the compressed data will fit in a TCP message,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * and no less than 65535 bytes so that an almost maximum-sized
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * RR will fit. Note that although 65535-byte RRs are allowed
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * in principle, they cannot be zone-transferred (at least not
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * if uncompressible), because the message and RR headers would
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * push the size of the TCP message over the 65536 byte limit.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews len = 65535;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews mem = isc_mem_get(mctx, len);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (mem == NULL) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = ISC_R_NOMEMORY;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews goto failure;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_init(&xfr->buf, mem, len);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Allocate another temporary buffer for the compressed
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * response message and its TCP length prefix.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews len = 2 + 65535;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews mem = isc_mem_get(mctx, len);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (mem == NULL) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = ISC_R_NOMEMORY;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews goto failure;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_init(&xfr->txlenbuf, mem, 2);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->txmem = mem;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->txmemlen = len;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_timer_setidle(xfr->client->timer,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews maxtime, idletime, ISC_FALSE));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Register a shutdown callback with the client, so that we
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * can stop the transfer immediately when the client task
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * gets a shutdown event.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->client->shutdown = xfrout_client_shutdown;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->client->shutdown_arg = xfr;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * These MUST be after the last "goto failure;" / CHECK to
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * prevent a double free by the caller.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->quota = quota;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->stream = stream;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *xfrp = xfr;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (ISC_R_SUCCESS);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsfailure:
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfrout_ctx_destroy(&xfr);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews return (result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Arrange to send as much as we can of "stream" without blocking.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Requires:
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * The stream iterator is initialized and points at an RR,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * or possibly at the end of the stream (that is, the
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * _first method of the iterator has been called).
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewssendstream(xfrout_ctx_t *xfr) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_message_t *tcpmsg = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_result_t result;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_region_t used;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_region_t region;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataset_t *qrdataset;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_t *msgname = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdata_t *msgrdata = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdatalist_t *msgrdl = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataset_t *msgrds = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_compress_t cctx;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_boolean_t cleanup_cctx = ISC_FALSE;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews int n_rrs;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_clear(&xfr->buf);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_clear(&xfr->txlenbuf);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_clear(&xfr->txbuf);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * In the UDP case, we put the response data directly into
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * the client message.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msg = xfr->client->message;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_message_reply(msg, ISC_TRUE));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * TCP. Build a response dns_message_t, temporarily storing
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * the raw, uncompressed owner names and RR data contiguously
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * in xfr->buf. We know that if the uncompressed data fits
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * in xfr->buf, the compressed data will surely fit in a TCP
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * message.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_message_create(xfr->mctx,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews DNS_MESSAGE_INTENTRENDER, &tcpmsg));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msg = tcpmsg;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msg->id = xfr->id;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msg->rcode = dns_rcode_noerror;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msg->flags |= DNS_MESSAGEFLAG_RA;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (xfr->lasttsig != NULL)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_free(&xfr->lasttsig);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Account for reserved space.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (xfr->tsigkey != NULL)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(msg->reserved != 0U);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_add(&xfr->buf, msg->reserved);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Include a question section in the first message only.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * BIND 8.2.1 will not recognize an IXFR if it does not
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * have a question section.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (xfr->nmsg == 0) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_t *qname = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_region_t r;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Reserve space for the 12-byte message header
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * and 4 bytes of question.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_add(&xfr->buf, 12 + 4);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews qrdataset = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_message_gettemprdataset(msg, &qrdataset);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews goto failure;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataset_init(qrdataset);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataset_makequestion(qrdataset,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->client->message->rdclass,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->qtype);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_message_gettempname(msg, &qname);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews goto failure;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_init(qname, NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_availableregion(&xfr->buf, &r);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(r.length >= xfr->qname->length);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews r.length = xfr->qname->length;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->qname->length);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_fromregion(qname, &r);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ISC_LIST_INIT(qname->list);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ISC_LIST_APPEND(qname->list, qrdataset, link);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Reserve space for the 12-byte message header
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_add(&xfr->buf, 12);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msg->tcp_continuation = 1;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Try to fit in as many RRs as possible, unless "one-answer"
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * format has been requested.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews for (n_rrs = 0; ; n_rrs++) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_t *name = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_uint32_t ttl;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdata_t *rdata = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned int size;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_region_t r;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msgname = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msgrdata = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msgrdl = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msgrds = NULL;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->stream->methods->current(xfr->stream,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews &name, &ttl, &rdata);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews size = name->length + 10 + rdata->length;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_availableregion(&xfr->buf, &r);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (size >= r.length) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * RR would not fit. If there are other RRs in the
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * buffer, send them now and leave this RR to the
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * next message. If this RR overflows the buffer
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * all by itself, fail.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews *
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * In theory some RRs might fit in a TCP message
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * when compressed even if they do not fit when
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * uncompressed, but surely we don't want
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * to send such monstrosities to an unsuspecting
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * slave.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (n_rrs == 0) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfrout_log(xfr, ISC_LOG_WARNING,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "RR too large for zone transfer "
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "(%d bytes)", size);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /* XXX DNS_R_RRTOOLARGE? */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = ISC_R_NOSPACE;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews goto failure;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews break;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews log_rr(name, rdata, ttl); /* XXX */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_message_gettempname(msg, &msgname);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews goto failure;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_init(msgname, NULL);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_availableregion(&xfr->buf, &r);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews INSIST(r.length >= name->length);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews r.length = name->length;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_fromregion(msgname, &r);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /* Reserve space for RR header. */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_add(&xfr->buf, 10);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_message_gettemprdata(msg, &msgrdata);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result != ISC_R_SUCCESS)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews goto failure;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_availableregion(&xfr->buf, &r);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews r.length = rdata->length;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews dns_rdata_init(msgrdata);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdata_fromregion(msgrdata,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews rdata->rdclass, rdata->type, &r);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_message_gettemprdatalist(msg, &msgrdl);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington if (result != ISC_R_SUCCESS)
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington goto failure;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews msgrdl->type = rdata->type;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington msgrdl->rdclass = rdata->rdclass;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington msgrdl->ttl = ttl;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington if (rdata->type == dns_rdatatype_sig ||
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington rdata->type == dns_rdatatype_rrsig)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msgrdl->covers = dns_rdata_covers(rdata);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington else
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews msgrdl->covers = dns_rdatatype_none;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington ISC_LINK_INIT(msgrdl, link);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews ISC_LIST_INIT(msgrdl->rdata);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington result = dns_message_gettemprdataset(msg, &msgrds);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington if (result != ISC_R_SUCCESS)
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington goto failure;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington dns_rdataset_init(msgrds);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington result = dns_rdatalist_tordataset(msgrdl, msgrds);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington INSIST(result == ISC_R_SUCCESS);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington ISC_LIST_APPEND(msgname->list, msgrds, link);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington msgname = NULL;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington result = xfr->stream->methods->next(xfr->stream);
f15af68028adc665d3bdddf955fc52bad83f0514Brian Wellington if (result == ISC_R_NOMORE) {
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington xfr->end_of_stream = ISC_TRUE;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington break;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington }
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington CHECK(result);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington if (! xfr->many_answers)
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews break;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington }
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
86f6b92e35c7bdb5fc1fd1021af75b981863313eMark Andrews if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
86f6b92e35c7bdb5fc1fd1021af75b981863313eMark Andrews dns_compress_setsensitive(&cctx, ISC_TRUE);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews cleanup_cctx = ISC_TRUE;
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington CHECK(dns_message_renderend(msg));
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington dns_compress_invalidate(&cctx);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington cleanup_cctx = ISC_FALSE;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews isc_buffer_usedregion(&xfr->txbuf, &used);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington isc_buffer_putuint16(&xfr->txlenbuf,
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington (isc_uint16_t)used.length);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington region.base = xfr->txlenbuf.base;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington region.length = 2 + used.length;
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington xfrout_log(xfr, ISC_LOG_DEBUG(8),
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington "sending TCP message of %d bytes",
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington used.length);
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington &region, xfr->client->task,
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington xfrout_senddone,
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington xfr));
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews xfr->sends++;
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington } else {
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington ns_client_send(xfr->client);
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington xfr->stream->methods->pause(xfr->stream);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews xfrout_ctx_destroy(&xfr);
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington return;
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington }
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington /* Advance lasttsig to be the last TSIG generated */
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington xfr->nmsg++;
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington failure:
c70908209ee26c51a8e7242a56fdb73847249728Brian Wellington if (msgname != NULL) {
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews if (msgrds != NULL) {
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews if (dns_rdataset_isassociated(msgrds))
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington dns_rdataset_disassociate(msgrds);
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington dns_message_puttemprdataset(msg, &msgrds);
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington }
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington if (msgrdl != NULL) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_message_puttemprdatalist(msg, &msgrdl);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews if (msgrdata != NULL)
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington dns_message_puttemprdata(msg, &msgrdata);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington dns_message_puttempname(msg, &msgname);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington }
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington if (tcpmsg != NULL)
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington dns_message_destroy(&tcpmsg);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington if (cleanup_cctx)
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington dns_compress_invalidate(&cctx);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
777ac454c0cdec27dc11d80b9b2a8d7239d833a8Brian Wellington * Make sure to release any locks held by database
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington * iterators before returning from the event handler.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->stream->methods->pause(xfr->stream);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (result == ISC_R_SUCCESS)
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews return;
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington xfrout_fail(xfr, result, "sending zone data");
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington}
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafssonstatic void
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellingtonxfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews xfrout_ctx_t *xfr = *xfrp;
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington ns_client_t *client = NULL;
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington INSIST(xfr->sends == 0);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington xfr->client->shutdown = NULL;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington xfr->client->shutdown_arg = NULL;
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington if (xfr->stream != NULL)
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington xfr->stream->methods->destroy(&xfr->stream);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington if (xfr->buf.base != NULL)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington if (xfr->txmem != NULL)
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington if (xfr->lasttsig != NULL)
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington isc_buffer_free(&xfr->lasttsig);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington if (xfr->quota != NULL)
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington isc_quota_detach(&xfr->quota);
e27021ee1f37185ab839a7a3b6bc078c24255e62Brian Wellington if (xfr->ver != NULL)
e27021ee1f37185ab839a7a3b6bc078c24255e62Brian Wellington dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
e27021ee1f37185ab839a7a3b6bc078c24255e62Brian Wellington if (xfr->zone != NULL)
e27021ee1f37185ab839a7a3b6bc078c24255e62Brian Wellington dns_zone_detach(&xfr->zone);
e27021ee1f37185ab839a7a3b6bc078c24255e62Brian Wellington if (xfr->db != NULL)
e27021ee1f37185ab839a7a3b6bc078c24255e62Brian Wellington dns_db_detach(&xfr->db);
e27021ee1f37185ab839a7a3b6bc078c24255e62Brian Wellington
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington /*
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington * We want to detch the client after we have released the memory
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington * context as ns_client_detach checks the memory reference count.
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington */
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington ns_client_attach(xfr->client, &client);
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson ns_client_detach(&xfr->client);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington ns_client_detach(&client);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington *xfrp = NULL;
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington}
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellingtonstatic void
60e9e7065418e658c069ce91cc6f27c4a55bb4a5Brian Wellingtonxfrout_senddone(isc_task_t *task, isc_event_t *event) {
6036112f4874637240d461c3ccbcb8dbfb1f405bAndreas Gustafsson isc_socketevent_t *sev = (isc_socketevent_t *)event;
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington xfrout_ctx_t *xfr = (xfrout_ctx_t *)event->ev_arg;
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington isc_result_t evresult = sev->result;
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews UNUSED(task);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington isc_event_free(&event);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington xfr->sends--;
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington INSIST(xfr->sends == 0);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington (void)isc_timer_touch(xfr->client->timer);
6036112f4874637240d461c3ccbcb8dbfb1f405bAndreas Gustafsson if (xfr->shuttingdown == ISC_TRUE) {
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson xfrout_maybe_destroy(xfr);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else if (evresult != ISC_R_SUCCESS) {
6036112f4874637240d461c3ccbcb8dbfb1f405bAndreas Gustafsson xfrout_fail(xfr, evresult, "send");
6036112f4874637240d461c3ccbcb8dbfb1f405bAndreas Gustafsson } else if (xfr->end_of_stream == ISC_FALSE) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews sendstream(xfr);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /* End of zone transfer stream. */
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews inc_stats(xfr->zone, dns_nsstatscounter_xfrdone);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews xfrout_log(xfr, ISC_LOG_INFO, "%s ended", xfr->mnemonic);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ns_client_next(xfr->client, ISC_R_SUCCESS);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfrout_ctx_destroy(&xfr);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews }
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfr->shuttingdown = ISC_TRUE;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s",
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington msg, isc_result_totext(result));
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington xfrout_maybe_destroy(xfr);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews}
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsstatic void
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsxfrout_maybe_destroy(xfrout_ctx_t *xfr) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews INSIST(xfr->shuttingdown == ISC_TRUE);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (xfr->sends > 0) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /*
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * If we are currently sending, cancel it and wait for
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * cancel event before destroying the context.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task,
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington ISC_SOCKCANCEL_SEND);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews } else {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ns_client_next(xfr->client, ISC_R_CANCELED);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfrout_ctx_destroy(&xfr);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington }
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_client_shutdown(void *arg, isc_result_t result) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfrout_ctx_t *xfr = (xfrout_ctx_t *) arg;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfrout_fail(xfr, result, "aborted");
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington}
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington/*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Log outgoing zone transfer messages in a format like
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * <client>: transfer of <zone>: <message>
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_logv(ns_client_t *client, dns_name_t *zonename,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ISC_FORMAT_PRINTF(5, 0);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_logv(ns_client_t *client, dns_name_t *zonename,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataclass_t rdclass, int level, const char *fmt, va_list ap)
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews{
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews char msgbuf[2048];
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews char namebuf[DNS_NAME_FORMATSIZE];
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews char classbuf[DNS_RDATACLASS_FORMATSIZE];
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_name_format(zonename, namebuf, sizeof(namebuf));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews NS_LOGMODULE_XFER_OUT, level,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews}
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington/*
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Logging function for use when a xfrout_ctx_t has not yet been created.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic void
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_log1(ns_client_t *client, dns_name_t *zonename,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataclass_t rdclass, int level, const char *fmt, ...) {
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington va_list ap;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington va_start(ap, fmt);
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington xfrout_logv(client, zonename, rdclass, level, fmt, ap);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews va_end(ap);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington}
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/*
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * Logging function for use when there is a xfrout_ctx_t.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonstatic void
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonxfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...) {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington va_list ap;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington va_start(ap, fmt);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington va_end(ap);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington}
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellington