xfrout.c revision 553197e28833ed2d8bf26f8112eaa137dbaa040a
a7038d1a0513c8e804937ebc95fc9cb3a46c04f5Mark Andrews * Copyright (C) 2004-2011 Internet Systems Consortium, Inc. ("ISC")
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence * Copyright (C) 1999-2003 Internet Software Consortium.
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 * 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.
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews/* $Id: xfrout.c,v 1.143 2011/12/01 00:53:58 marka Exp $ */
ed019cabc1cc75d4412010c331876e4ae5080a4dDavid Lawrence * Outgoing AXFR and IXFR.
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington * - IXFR over UDP
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ns_g_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT
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 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley "bad zone transfer request: %s (%s)", \
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 "bad zone transfer request: '%s/%s': %s (%s)", \
e44487bfc23599b6b240e09d83d1c862fecfcc82Michael Graff _buf1, _buf2, msg, isc_result_totext(code)); \
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 isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington/**************************************************************************/
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellington/*% Log an RR (for debugging) */
98d010a24a9f1b4b45ce9791845941ef90426d0cBrian Wellingtonlog_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS);
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * We could use xfrout_log(), but that would produce
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * very long lines with a repetitive prefix.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Get rid of final newline.
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>");
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews/**************************************************************************/
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 Wellingtontypedef struct rrstream_methods rrstream_methods_t;
b5debbe212097d1c573a2ba3bd9a3d526d86b0aeBrian Wellingtontypedef struct rrstream {
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.
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.
17a3fcecd069130a5f318685493b0db5639a77c9Brian Wellington/* Forward declarations. */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic rrstream_methods_t ixfr_rrstream_methods;
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington * Returns: anything dns_journal_open() or dns_journal_iter_init()
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * may return.
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington s->common.methods = &ixfr_rrstream_methods;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington CHECK(dns_journal_open(mctx, journal_filename,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ixfr_rrstream_destroy((rrstream_t **) (void *)&s);
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_journal_current_rr(s->journal, name, ttl, rdata);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic rrstream_methods_t ixfr_rrstream_methods = {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/**************************************************************************/
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * An 'axfr_rrstream_t' is an 'rrstream_t' that returns
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * an AXFR-like RR stream from a database.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * The SOAs at the beginning and end of the transfer are
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * not included in the stream.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewstypedef struct axfr_rrstream {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * Forward declarations.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic rrstream_methods_t axfr_rrstream_methods;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsaxfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_rriterator_init(&s->it, db, ver, 0));
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington axfr_rrstream_destroy((rrstream_t **) (void *)&s);
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington /* Skip SOA records. */
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington dns_rriterator_current(&s->it, &name_dummy,
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson /* Skip SOA records. */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsaxfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rriterator_current(&s->it, name, ttl, NULL, rdata);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsstatic rrstream_methods_t axfr_rrstream_methods = {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/**************************************************************************/
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * a single SOA record.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtontypedef struct soa_rrstream {
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * Forward declarations.
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrewssoa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
c99d9017ba00099bfa89e1ed53e63a5cb07d28d5Mark Andrews soa_rrstream_destroy((rrstream_t **) (void *)&s);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewssoa_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
421e4cf66e4cba0b0751a34a9c027e39fe0474f9Mark Andrewsstatic rrstream_methods_t soa_rrstream_methods = {
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 * The component streams are owned by the compound_rrstream_t
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * and are destroyed with it.
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * Forward declarations.
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewsstatic rrstream_methods_t compound_rrstream_methods;
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews * soa_stream != NULL && *soa_stream != NULL
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * data_stream != NULL && *data_stream != NULL
638fe804a524ee0c028863c0301b999c79de7651Mark Andrews * sp != NULL && *sp == NULL
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.
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrewscompound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream,
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews s->common.methods = &compound_rrstream_methods;
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington compound_rrstream_t *s = (compound_rrstream_t *) rs;
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);
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);
9cd6710f91bdffef5aed68ab02533e398f6134d7Brian Wellington * Make sure locks held by the current stream
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington * are released before we switch streams.
8839b6acbf816fedc15b8e9e1c71fd606a9cd8eaBrian Wellington s->result = curstream->methods->first(curstream);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellingtoncompound_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
f15af68028adc665d3bdddf955fc52bad83f0514Brian Wellington compound_rrstream_t *s = (compound_rrstream_t *) rs;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews curstream->methods->current(curstream, name, ttl, rdata);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington compound_rrstream_t *s = (compound_rrstream_t *) rs;
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 Wellingtonstatic rrstream_methods_t compound_rrstream_methods = {
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington/**************************************************************************/
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington * An 'xfrout_ctx_t' contains the state of an outgoing AXFR or IXFR
6f071989da905bb5ab2c6dfd01a71ee5ecea5918Brian Wellington * in progress.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewstypedef struct {
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson dns_name_t *qname; /* Question name of request */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_rdatatype_t qtype; /* dns_rdatatype_{a,i}xfr */
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington dns_zone_t *zone; /* (necessary for stats) */
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 */
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 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_db_t *db, dns_dbversion_t *ver, isc_quota_t *quota,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned int maxtime,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned int idletime,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_senddone(isc_task_t *task, isc_event_t *event);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_client_shutdown(void *arg, isc_result_t result);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_log1(ns_client_t *client, dns_name_t *zonename,
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews/**************************************************************************/
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_transfer_format_t format = client->view->transfer_format;
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * Apply quota.
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington result = isc_quota_attach(&ns_g_server->xfroutquota, "a);
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence * Interpret the question section.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley result = dns_message_firstname(request, DNS_SECTION_QUESTION);
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington * The question section must contain exactly one question, and
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * it must be for AXFR/IXFR as appropriate.
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 FAILC(DNS_R_FORMERR, "multiple questions");
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
368b37b616234fce3d23099eb180f1dd38e1fb62Mark Andrews * Normal zone table does not have a match.
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Try the DLZ database
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington "zone transfer '%s/%s' denied",
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * DLZ only support full zone transfer, not incremental
78951552dccf0d0004d61072bbc71fa4b1aab30fAndreas Gustafsson * not DLZ and not in normal zone table, we are
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * not authoritative
a9ba7e65644c50e1549b38150ba8d4787e1fe643Brian Wellington /* zone table has a match */
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews break; /* Master and slave zones are OK for transfer. */
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Check the authority section. Look for a SOA record with
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * the same name and class as the question.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
3676eeb6ca95c66aae1256f37af8c990d9f25eb4Brian Wellington dns_message_currentname(request, DNS_SECTION_AUTHORITY,
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * Ignore data whose owner name is not the zone apex.
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington if (! dns_name_equal(soa_name, question_name))
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington * Ignore non-SOA data.
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson if (soa_rdataset->rdclass != question_class)
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley "IXFR authority section "
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley "has multiple SOAs");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * If not a DLZ zone, decide whether to allow this transfer.
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington ns_client_aclmsg("zone transfer", question_name, reqtype,
77c67dfb2607618f5e7940486daebafd42a502abBrian Wellington * AXFR over UDP is not possible.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington (client->attributes & NS_CLIENTATTR_TCP) == 0)
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Look up the requesting server in the peer table.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_netaddr_fromsockaddr(&na, &client->peeraddr);
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Decide on the transfer format (one-answer or many-answers).
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews (void)dns_peer_gettransferformat(peer, &format);
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington * Get a dynamically allocated copy of the current SOA.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Outgoing IXFR may have been disabled for this peer
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews * or globally.
25496cebadd170fd5fae2aabf0469eef551259aaBrian Wellington (void) dns_peer_getprovideixfr(peer, &provide_ixfr);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "IXFR request missing SOA");
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews current_serial = dns_soa_getserial(¤t_soa_tuple->rdata);
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.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Sending a single SOA record is also how we refuse
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * IXFR over UDP (currently, we always do).
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (DNS_SERIAL_GE(begin_serial, current_serial) ||
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(soa_rrstream_create(mctx, db, ver, &stream));
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson xfrout_log1(client, question_name, question_class,
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson "IXFR version not in journal, "
3ce4b8b03ebd017c1d1b320429219ba91e705ea4Andreas Gustafsson "falling back to AXFR");
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley * Bracket the data stream with SOAs.
1a69a1a78cfaa86f3b68bbc965232b7876d4da2aDavid Lawrence CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
78951552dccf0d0004d61072bbc71fa4b1aab30fAndreas Gustafsson CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson * Create the xfrout context object. This transfers the ownership
93c786e0924aeca2c258e32355349e6ae60a0f72Andreas Gustafsson * of "stream", "db", "ver", and "quota" to the xfrout context object.
23e4260821eefa5019808e18e14e2b366461aad7Brian Wellington CHECK(xfrout_ctx_create(mctx, client, request->id,
0ec4b862c9abd11c82c88ed62438f0cf06fed25dBob Halley CHECK(xfrout_ctx_create(mctx, client, request->id,
d6643ef587324e40d8bda63e9f80be8141e101edBrian Wellington CHECK(xfr->stream->methods->first(xfr->stream));
34aa7909371f13b4bc0ba6d155cfc38bfa1e3c5cAndreas Gustafsson dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
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);
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington xfrout_log1(client, question_name, question_class,
ba393f380e4cd93029f6a7291d6c2d14f9022b3cBrian Wellington (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
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.
feb40fc5f911d0b2050fb9fd34950a52930b981dBrian Wellington inc_stats(zone, dns_nsstatscounter_xfrrej);
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington data_stream->methods->destroy(&data_stream);
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington /* XXX kludge */
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington xfrout_fail(xfr, result, "setting up zone transfer");
75f6c57d9544aa77a3b1a04587b4702c07343c90Brian Wellington ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington ISC_LOG_DEBUG(3), "zone transfer setup failed");
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonxfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
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,
25276bd1ecb372b82c9235648e5defab0655dcd5Mark Andrews unsigned int len;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (zone != NULL) /* zone will be NULL if it's DLZ */
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 * Allocate another temporary buffer for the compressed
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * response message and its TCP length prefix.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_init(&xfr->txbuf, (char *) mem + 2, len - 2);
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 xfr->client->shutdown = xfrout_client_shutdown;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * These MUST be after the last "goto failure;" / CHECK to
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * prevent a double free by the caller.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Arrange to send as much as we can of "stream" without blocking.
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 dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if ((xfr->client->attributes & NS_CLIENTATTR_TCP) == 0) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * In the UDP case, we put the response data directly into
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * the client message.
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 msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0)
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Account for reserved space.
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 * Reserve space for the 12-byte message header
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * and 4 bytes of question.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_message_gettemprdataset(msg, &qrdataset);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Reserve space for the 12-byte message header
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Try to fit in as many RRs as possible, unless "one-answer"
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * format has been requested.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews unsigned int size;
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 * 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 "RR too large for zone transfer "
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /* XXX DNS_R_RRTOOLARGE? */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews if (isc_log_wouldlog(ns_g_lctx, XFROUT_RR_LOGLEVEL))
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_message_gettempname(msg, &msgname);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews /* Reserve space for RR header. */
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_message_gettemprdata(msg, &msgrdata);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews result = dns_message_gettemprdatalist(msg, &msgrdl);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington result = dns_message_gettemprdataset(msg, &msgrds);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington result = dns_rdatalist_tordataset(msgrdl, msgrds);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington ISC_LIST_APPEND(msgname->list, msgrds, link);
94766449d6125cd5870891b70d46573e5deaceb4Brian Wellington dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
e83cae7fa837e4757c687035d6f6c0900f152749Brian Wellington result = xfr->stream->methods->next(xfr->stream);
86f6b92e35c7bdb5fc1fd1021af75b981863313eMark Andrews if ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
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));
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington "sending TCP message of %d bytes",
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington CHECK(isc_socket_send(xfr->client->tcpsocket, /* XXX */
d6be55c63f83194d97a565d0fd7b632b31b52a68Brian Wellington xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
32b2cdf212de957e3f9b0efca59f098ed4fb42deBrian Wellington /* Advance lasttsig to be the last TSIG generated */
93d6dfaf66258337985427c86181f01fc51f0bb4Mark Andrews CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
777ac454c0cdec27dc11d80b9b2a8d7239d833a8Brian Wellington * Make sure to release any locks held by database
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington * iterators before returning from the event handler.
5c6117688525d0e8d247f50c63364f66bd8d4185Brian Wellington xfrout_fail(xfr, result, "sending zone data");
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington xfr->stream->methods->destroy(&xfr->stream);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length);
613efcd8fbd0d1ce0d0afd1ac85d95cf85bffc27Brian Wellington isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen);
e27021ee1f37185ab839a7a3b6bc078c24255e62Brian Wellington dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
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 isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
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 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
6036112f4874637240d461c3ccbcb8dbfb1f405bAndreas Gustafsson } else if (xfr->end_of_stream == ISC_FALSE) {
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 Andrewsxfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {
ff30cdeb783ca7ffe69b222c56197828e882c229Mark Andrews * If we are currently sending, cancel it and wait for
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * cancel event before destroying the context.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews isc_socket_cancel(xfr->client->tcpsocket, xfr->client->task,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_client_shutdown(void *arg, isc_result_t result) {
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Log outgoing zone transfer messages in a format like
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * <client>: transfer of <zone>: <message>
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 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 dns_name_format(zonename, namebuf, sizeof(namebuf));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews "transfer of '%s/%s': %s", namebuf, classbuf, msgbuf);
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews * Logging function for use when a xfrout_ctx_t has not yet been created.
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrewsxfrout_log1(ns_client_t *client, dns_name_t *zonename,
0b09763c354ec91fb352b6b4cea383bd0195b2d8Mark Andrews dns_rdataclass_t rdclass, int level, const char *fmt, ...) {
48ed268b3378a8b729a0037bc4ae2ed73647a96aBrian Wellington xfrout_logv(client, zonename, rdclass, level, fmt, ap);
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellington * Logging function for use when there is a xfrout_ctx_t.
ca9af3aaf798f98624fc1dc69d8c7d51bf01334dBrian Wellingtonxfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...) {