xfrout.c revision 0bfcec250f9705a1211d0374f0fc1049960de84b
7d32c065c7bb56f281651ae3dd2888f32ce4f1d9Bob Halley * Copyright (C) 1999, 2000 Internet Software Consortium.
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * Permission to use, copy, modify, and distribute this software for any
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * purpose with or without fee is hereby granted, provided that the above
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * copyright notice and this permission notice appear in all copies.
15a44745412679c30a6d022733925af70a38b715David Lawrence * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
15a44745412679c30a6d022733925af70a38b715David Lawrence * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
15a44745412679c30a6d022733925af70a38b715David Lawrence * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
15a44745412679c30a6d022733925af70a38b715David Lawrence * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
15a44745412679c30a6d022733925af70a38b715David Lawrence * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15a44745412679c30a6d022733925af70a38b715David Lawrence * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
15a44745412679c30a6d022733925af70a38b715David Lawrence * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
b589e90689c6e87bf9608424ca8d99571c18bc61Mark Andrews/* $Id: xfrout.c,v 1.68 2000/06/15 04:41:59 marka Exp $ */
34b394b43e2207e8f8f3703f0402422121455638David Lawrence * Outgoing AXFR and IXFR.
0bd044c2afee944d93879a7de82cd2ccc0635798David Lawrence * - IXFR over UDP
0bd044c2afee944d93879a7de82cd2ccc0635798David Lawrence ns_g_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * Fail unconditionally and log as a client error.
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
34b394b43e2207e8f8f3703f0402422121455638David Lawrence * from complaining about "end-of-loop code not reached".
34b394b43e2207e8f8f3703f0402422121455638David Lawrence ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews "bad zone transfer request: %s (%s)", \
34b394b43e2207e8f8f3703f0402422121455638David Lawrence/**************************************************************************/
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson * A db_rr_iterator_t is an iterator that iterates over an entire database,
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson * returning one RR at a time, in some arbitrary order.
34b394b43e2207e8f8f3703f0402422121455638David Lawrencetypedef struct db_rr_iterator db_rr_iterator_t;
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrewsdb_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrewsdb_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrewsdb_rr_iterator_init(db_rr_iterator_t *it, dns_db_t *db, dns_dbversion_t *ver,
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews result = dns_db_createiterator(it->db, ISC_FALSE, &it->dbit);
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews INSIST(! dns_rdataset_isassociated(&it->rdataset));
1ac4b2a1da88e574319b374bc733eccf8ac45327Andreas Gustafssondb_rr_iterator_first(db_rr_iterator_t *it) {
1ac4b2a1da88e574319b374bc733eccf8ac45327Andreas Gustafsson it->result = dns_dbiterator_first(it->dbit);
1ac4b2a1da88e574319b374bc733eccf8ac45327Andreas Gustafsson it->result = dns_dbiterator_current(it->dbit, &it->node,
34b394b43e2207e8f8f3703f0402422121455638David Lawrence it->result = dns_db_allrdatasets(it->db, it->node,
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews it->result = dns_rdatasetiter_first(it->rdatasetit);
34b394b43e2207e8f8f3703f0402422121455638David Lawrence dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews it->result = dns_rdataset_first(&it->rdataset);
34b394b43e2207e8f8f3703f0402422121455638David Lawrence it->result = dns_rdataset_next(&it->rdataset);
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews it->result = dns_rdatasetiter_next(it->rdatasetit);
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * The while loop body is executed more than once
fad44a20eede1bbc66716241dede225500c91caaAndreas Gustafsson * only when an empty dbnode needs to be skipped.
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson dns_rdatasetiter_destroy(&it->rdatasetit);
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews /* We are at the end of the entire database. */
34b394b43e2207e8f8f3703f0402422121455638David Lawrence it->result = dns_dbiterator_current(it->dbit,
40f53fa8d9c6a4fc38c0014495e7a42b08f52481David Lawrence it->result = dns_db_allrdatasets(it->db, it->node,
34b394b43e2207e8f8f3703f0402422121455638David Lawrence it->result = dns_rdatasetiter_first(it->rdatasetit);
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews dns_rdatasetiter_current(it->rdatasetit, &it->rdataset);
34b394b43e2207e8f8f3703f0402422121455638David Lawrencedb_rr_iterator_destroy(db_rr_iterator_t *it) {
34b394b43e2207e8f8f3703f0402422121455638David Lawrence if (dns_rdataset_isassociated(&it->rdataset))
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson dns_rdataset_disassociate(&it->rdataset);
5fc7ba3e1ac5d72239e9971e0f469dd5796738f9Andreas Gustafsson dns_rdatasetiter_destroy(&it->rdatasetit);
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graffdb_rr_iterator_current(db_rr_iterator_t *it, dns_name_t **name,
94a08e09db3dc844b6ee4841c368a2d7074a9c3fAndreas Gustafsson dns_rdataset_current(&it->rdataset, &it->rdata);
6e49e91bd08778d7eae45a2229dcf41ed97cc636David Lawrence/**************************************************************************/
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews/* Log an RR (for debugging) */
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrewslog_rr(dns_name_t *name, dns_rdata_t *rdata, isc_uint32_t ttl) {
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS);
542deb20c44666a870855bf755a100d254db074dAndreas Gustafsson /* Get rid of final newline. */
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews INSIST(buf.used >= 1 && ((char *) buf.base)[buf.used-1] == '\n');
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * We could use xfrout_log(), but that would produce
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * very long lines with a repetitive prefix.
94a08e09db3dc844b6ee4841c368a2d7074a9c3fAndreas Gustafsson "%.*s", (int) r.length, (char *) r.base);
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews "<RR too large to print>");
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews/**************************************************************************/
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * An 'rrstream_t' is a polymorphic iterator that returns
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * a stream of resource records. There are multiple implementations,
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * e.g. for generating AXFR and IXFR records streams.
34b394b43e2207e8f8f3703f0402422121455638David Lawrencetypedef struct rrstream_methods rrstream_methods_t;
34b394b43e2207e8f8f3703f0402422121455638David Lawrencetypedef struct rrstream {
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews/**************************************************************************/
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns
e6c22f37d8df55a9f66b479a22717e179bcf79a3Andreas Gustafsson * an IXFR-like RR stream from a journal file.
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * The SOA at the beginning of each sequence of additions
d981ca645597116d227a48bf37cc5edc061c854dBob Halley * or deletions are included in the stream, but the extra
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * SOAs at the beginning and end of the entire transfer are
b589e90689c6e87bf9608424ca8d99571c18bc61Mark Andrews * not included.
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrewstypedef struct ixfr_rrstream {
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews/* Forward declarations. */
e6c22f37d8df55a9f66b479a22717e179bcf79a3Andreas Gustafssonstatic rrstream_methods_t ixfr_rrstream_methods;
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * Returns: anything dns_journal_open() or dns_journal_iter_init()
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * may return.
373ce67419680a398ba3dc51a14a486caaf0afb0Mark Andrews CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial));
d8813e2ceee2f4adaf697931c2491de265ce5eb9Brian Wellington ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
d8813e2ceee2f4adaf697931c2491de265ce5eb9Brian Wellington ixfr_rrstream_t *s = (ixfr_rrstream_t *) rs;
34b394b43e2207e8f8f3703f0402422121455638David Lawrence dns_journal_current_rr(s->journal, name, ttl, rdata);
34b394b43e2207e8f8f3703f0402422121455638David Lawrence ixfr_rrstream_t *s = (ixfr_rrstream_t *) *rsp;
d8813e2ceee2f4adaf697931c2491de265ce5eb9Brian Wellington isc_mem_put(s->common.mctx, s, sizeof(*s));
34b394b43e2207e8f8f3703f0402422121455638David Lawrencestatic rrstream_methods_t ixfr_rrstream_methods = {
373ce67419680a398ba3dc51a14a486caaf0afb0Mark Andrews/**************************************************************************/
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrews * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns
3ddd814a97de1d152ba0913c592d6e6dc83d38a6Michael Graff * an AXFR-like RR stream from a database.
d8813e2ceee2f4adaf697931c2491de265ce5eb9Brian Wellington * The SOAs at the beginning and end of the transfer are
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews * not included in the stream.
ffe74cc719aa0f10c38fbc1f2f3ea7db0960cb8fMark Andrewstypedef struct axfr_rrstream {
d8813e2ceee2f4adaf697931c2491de265ce5eb9Brian Wellington * Forward declarations.
d8813e2ceee2f4adaf697931c2491de265ce5eb9Brian Wellingtonstatic rrstream_methods_t axfr_rrstream_methods;
34b394b43e2207e8f8f3703f0402422121455638David Lawrenceaxfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
d8813e2ceee2f4adaf697931c2491de265ce5eb9Brian Wellington CHECK(db_rr_iterator_init(&s->it, db, ver, 0));
d8813e2ceee2f4adaf697931c2491de265ce5eb9Brian Wellington axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
d8813e2ceee2f4adaf697931c2491de265ce5eb9Brian Wellington /* Skip SOA records. */
cf3f14106d082e4676431c10c54b60b9a0e9b127Brian Wellington db_rr_iterator_current(&s->it, &name_dummy,
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews /* Skip SOA records. */
9281e7aa775026dc47c01745fdcc438645146877Mark Andrewsaxfr_rrstream_current(rrstream_t *rs, dns_name_t **name, isc_uint32_t *ttl,
542deb20c44666a870855bf755a100d254db074dAndreas Gustafsson axfr_rrstream_t *s = (axfr_rrstream_t *) rs;
9281e7aa775026dc47c01745fdcc438645146877Mark Andrews db_rr_iterator_current(&s->it, name, ttl, rdata);
6d12fdf96621801e80f3f4c2a8a569fe48766a20David Lawrence axfr_rrstream_t *s = (axfr_rrstream_t *) *rsp;
82ca33427bdd4f3bc4ed3431e86bd810fe751674Andreas Gustafsson isc_mem_put(s->common.mctx, s, sizeof(*s));
d981ca645597116d227a48bf37cc5edc061c854dBob Halleystatic rrstream_methods_t axfr_rrstream_methods = {
e27a69f8bd9538e08f775265167ba6cc5f47c587Bob Halley/**************************************************************************/
82ca33427bdd4f3bc4ed3431e86bd810fe751674Andreas Gustafsson * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns
542deb20c44666a870855bf755a100d254db074dAndreas Gustafsson * a single SOA record.
419590499823ce15b5d2ad4fe71eaf04bd5a86c0Michael Grafftypedef struct soa_rrstream {
e27a69f8bd9538e08f775265167ba6cc5f47c587Bob Halley * Forward declarations.
e27a69f8bd9538e08f775265167ba6cc5f47c587Bob Halleysoa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
soa_rrstream_t *s;
if (s == NULL)
return (ISC_R_NOMEMORY);
&s->soa_tuple));
return (ISC_R_SUCCESS);
return (result);
static isc_result_t
return (ISC_R_SUCCESS);
static isc_result_t
return (ISC_R_NOMORE);
typedef struct compound_rrstream {
int state;
static isc_result_t
static isc_result_t
if (s == NULL)
return (ISC_R_NOMEMORY);
return (ISC_R_SUCCESS);
static isc_result_t
s->state = 0;
return (s->result);
static isc_result_t
return (ISC_R_NOMORE);
s->state++;
return (s->result);
void *txmem;
unsigned int txmemlen;
} xfrout_ctx_t;
static isc_result_t
unsigned int maxtime,
unsigned int idletime,
const char *fmt, ...);
switch (reqtype) {
case dns_rdatatype_axfr:
case dns_rdatatype_ixfr:
INSIST(0);
goto failure;
&zone);
case dns_zone_master:
case dns_zone_slave:
&soa_name);
goto got_soa;
goto axfr_fallback;
if (! have_soa)
goto have_stream;
&data_stream);
goto axfr_fallback;
&data_stream));
&stream));
&xfr));
static isc_result_t
unsigned int len;
void *mem;
return (ISC_R_NOMEMORY);
goto failure;
goto failure;
ISC_FALSE));
return (ISC_R_SUCCESS);
return (result);
int n_rrs;
isc_region_t r;
goto failure;
goto failure;
unsigned int size;
isc_region_t r;
if (n_rrs == 0) {
goto failure;
xfr));
const char *fmt, ...)