Home | History | Annotate | Line # | Download | only in dns
xfrin.c revision 1.1.1.10
      1       1.1  christos /*	$NetBSD: xfrin.c,v 1.1.1.10 2023/01/25 20:36:46 christos Exp $	*/
      2       1.1  christos 
      3       1.1  christos /*
      4       1.1  christos  * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
      5       1.1  christos  *
      6   1.1.1.9  christos  * SPDX-License-Identifier: MPL-2.0
      7   1.1.1.9  christos  *
      8       1.1  christos  * This Source Code Form is subject to the terms of the Mozilla Public
      9       1.1  christos  * License, v. 2.0. If a copy of the MPL was not distributed with this
     10   1.1.1.6  christos  * file, you can obtain one at https://mozilla.org/MPL/2.0/.
     11       1.1  christos  *
     12       1.1  christos  * See the COPYRIGHT file distributed with this work for additional
     13       1.1  christos  * information regarding copyright ownership.
     14       1.1  christos  */
     15       1.1  christos 
     16       1.1  christos /*! \file */
     17       1.1  christos 
     18   1.1.1.2  christos #include <inttypes.h>
     19   1.1.1.2  christos #include <stdbool.h>
     20   1.1.1.2  christos 
     21       1.1  christos #include <isc/mem.h>
     22       1.1  christos #include <isc/print.h>
     23       1.1  christos #include <isc/random.h>
     24   1.1.1.4  christos #include <isc/string.h> /* Required for HP/UX (and others?) */
     25       1.1  christos #include <isc/task.h>
     26       1.1  christos #include <isc/timer.h>
     27       1.1  christos #include <isc/util.h>
     28       1.1  christos 
     29       1.1  christos #include <dns/callbacks.h>
     30       1.1  christos #include <dns/catz.h>
     31       1.1  christos #include <dns/db.h>
     32       1.1  christos #include <dns/diff.h>
     33       1.1  christos #include <dns/events.h>
     34       1.1  christos #include <dns/journal.h>
     35       1.1  christos #include <dns/log.h>
     36       1.1  christos #include <dns/message.h>
     37       1.1  christos #include <dns/rdataclass.h>
     38       1.1  christos #include <dns/rdatalist.h>
     39       1.1  christos #include <dns/rdataset.h>
     40       1.1  christos #include <dns/result.h>
     41       1.1  christos #include <dns/soa.h>
     42       1.1  christos #include <dns/tcpmsg.h>
     43       1.1  christos #include <dns/timer.h>
     44       1.1  christos #include <dns/tsig.h>
     45       1.1  christos #include <dns/view.h>
     46       1.1  christos #include <dns/xfrin.h>
     47       1.1  christos #include <dns/zone.h>
     48       1.1  christos 
     49       1.1  christos #include <dst/dst.h>
     50       1.1  christos 
     51       1.1  christos /*
     52       1.1  christos  * Incoming AXFR and IXFR.
     53       1.1  christos  */
     54       1.1  christos 
     55       1.1  christos /*%
     56       1.1  christos  * It would be non-sensical (or at least obtuse) to use FAIL() with an
     57       1.1  christos  * ISC_R_SUCCESS code, but the test is there to keep the Solaris compiler
     58       1.1  christos  * from complaining about "end-of-loop code not reached".
     59       1.1  christos  */
     60   1.1.1.4  christos #define FAIL(code)                           \
     61   1.1.1.4  christos 	do {                                 \
     62   1.1.1.4  christos 		result = (code);             \
     63   1.1.1.4  christos 		if (result != ISC_R_SUCCESS) \
     64   1.1.1.4  christos 			goto failure;        \
     65       1.1  christos 	} while (0)
     66       1.1  christos 
     67   1.1.1.4  christos #define CHECK(op)                            \
     68   1.1.1.4  christos 	do {                                 \
     69   1.1.1.4  christos 		result = (op);               \
     70   1.1.1.4  christos 		if (result != ISC_R_SUCCESS) \
     71   1.1.1.4  christos 			goto failure;        \
     72       1.1  christos 	} while (0)
     73       1.1  christos 
     74       1.1  christos /*%
     75       1.1  christos  * The states of the *XFR state machine.  We handle both IXFR and AXFR
     76       1.1  christos  * with a single integrated state machine because they cannot be distinguished
     77       1.1  christos  * immediately - an AXFR response to an IXFR request can only be detected
     78       1.1  christos  * when the first two (2) response RRs have already been received.
     79       1.1  christos  */
     80       1.1  christos typedef enum {
     81       1.1  christos 	XFRST_SOAQUERY,
     82       1.1  christos 	XFRST_GOTSOA,
     83       1.1  christos 	XFRST_INITIALSOA,
     84       1.1  christos 	XFRST_FIRSTDATA,
     85       1.1  christos 	XFRST_IXFR_DELSOA,
     86       1.1  christos 	XFRST_IXFR_DEL,
     87       1.1  christos 	XFRST_IXFR_ADDSOA,
     88       1.1  christos 	XFRST_IXFR_ADD,
     89       1.1  christos 	XFRST_IXFR_END,
     90       1.1  christos 	XFRST_AXFR,
     91       1.1  christos 	XFRST_AXFR_END
     92       1.1  christos } xfrin_state_t;
     93       1.1  christos 
     94       1.1  christos /*%
     95       1.1  christos  * Incoming zone transfer context.
     96       1.1  christos  */
     97       1.1  christos 
     98       1.1  christos struct dns_xfrin_ctx {
     99   1.1.1.4  christos 	unsigned int magic;
    100   1.1.1.4  christos 	isc_mem_t *mctx;
    101   1.1.1.4  christos 	dns_zone_t *zone;
    102   1.1.1.4  christos 
    103   1.1.1.4  christos 	int refcount;
    104   1.1.1.4  christos 
    105   1.1.1.4  christos 	isc_task_t *task;
    106   1.1.1.4  christos 	isc_timer_t *timer;
    107   1.1.1.4  christos 	isc_socketmgr_t *socketmgr;
    108   1.1.1.4  christos 
    109   1.1.1.4  christos 	int connects; /*%< Connect in progress */
    110   1.1.1.4  christos 	int sends;    /*%< Send in progress */
    111   1.1.1.4  christos 	int recvs;    /*%< Receive in progress */
    112   1.1.1.4  christos 	bool shuttingdown;
    113   1.1.1.4  christos 	isc_result_t shutdown_result;
    114       1.1  christos 
    115   1.1.1.4  christos 	dns_name_t name; /*%< Name of zone to transfer */
    116   1.1.1.4  christos 	dns_rdataclass_t rdclass;
    117       1.1  christos 
    118   1.1.1.4  christos 	bool checkid, logit;
    119   1.1.1.4  christos 	dns_messageid_t id;
    120       1.1  christos 
    121       1.1  christos 	/*%
    122       1.1  christos 	 * Requested transfer type (dns_rdatatype_axfr or
    123       1.1  christos 	 * dns_rdatatype_ixfr).  The actual transfer type
    124       1.1  christos 	 * may differ due to IXFR->AXFR fallback.
    125       1.1  christos 	 */
    126   1.1.1.4  christos 	dns_rdatatype_t reqtype;
    127   1.1.1.4  christos 	isc_dscp_t dscp;
    128       1.1  christos 
    129   1.1.1.4  christos 	isc_sockaddr_t masteraddr;
    130   1.1.1.4  christos 	isc_sockaddr_t sourceaddr;
    131   1.1.1.4  christos 	isc_socket_t *socket;
    132       1.1  christos 
    133       1.1  christos 	/*% Buffer for IXFR/AXFR request message */
    134   1.1.1.4  christos 	isc_buffer_t qbuffer;
    135   1.1.1.4  christos 	unsigned char qbuffer_data[512];
    136       1.1  christos 
    137       1.1  christos 	/*% Incoming reply TCP message */
    138   1.1.1.4  christos 	dns_tcpmsg_t tcpmsg;
    139   1.1.1.4  christos 	bool tcpmsg_valid;
    140       1.1  christos 
    141   1.1.1.3  christos 	/*%
    142   1.1.1.3  christos 	 * Whether the zone originally had a database attached at the time this
    143   1.1.1.3  christos 	 * transfer context was created.  Used by maybe_free() when making
    144   1.1.1.3  christos 	 * logging decisions.
    145   1.1.1.3  christos 	 */
    146   1.1.1.4  christos 	bool zone_had_db;
    147   1.1.1.3  christos 
    148   1.1.1.4  christos 	dns_db_t *db;
    149   1.1.1.4  christos 	dns_dbversion_t *ver;
    150   1.1.1.4  christos 	dns_diff_t diff; /*%< Pending database changes */
    151   1.1.1.4  christos 	int difflen;	 /*%< Number of pending tuples */
    152   1.1.1.4  christos 
    153   1.1.1.4  christos 	xfrin_state_t state;
    154   1.1.1.4  christos 	uint32_t end_serial;
    155   1.1.1.4  christos 	bool is_ixfr;
    156   1.1.1.4  christos 
    157   1.1.1.4  christos 	unsigned int nmsg;  /*%< Number of messages recvd */
    158   1.1.1.4  christos 	unsigned int nrecs; /*%< Number of records recvd */
    159   1.1.1.4  christos 	uint64_t nbytes;    /*%< Number of bytes received */
    160   1.1.1.4  christos 
    161   1.1.1.4  christos 	unsigned int maxrecords; /*%< The maximum number of
    162   1.1.1.4  christos 				  *   records set for the zone */
    163   1.1.1.4  christos 
    164   1.1.1.4  christos 	isc_time_t start; /*%< Start time of the transfer */
    165   1.1.1.4  christos 	isc_time_t end;	  /*%< End time of the transfer */
    166   1.1.1.4  christos 
    167   1.1.1.4  christos 	dns_tsigkey_t *tsigkey; /*%< Key used to create TSIG */
    168   1.1.1.4  christos 	isc_buffer_t *lasttsig; /*%< The last TSIG */
    169   1.1.1.4  christos 	dst_context_t *tsigctx; /*%< TSIG verification context */
    170   1.1.1.4  christos 	unsigned int sincetsig; /*%< recvd since the last TSIG */
    171   1.1.1.4  christos 	dns_xfrindone_t done;
    172       1.1  christos 
    173       1.1  christos 	/*%
    174       1.1  christos 	 * AXFR- and IXFR-specific data.  Only one is used at a time
    175       1.1  christos 	 * according to the is_ixfr flag, so this could be a union,
    176       1.1  christos 	 * but keeping them separate makes it a bit simpler to clean
    177       1.1  christos 	 * things up when destroying the context.
    178       1.1  christos 	 */
    179   1.1.1.4  christos 	dns_rdatacallbacks_t axfr;
    180       1.1  christos 
    181       1.1  christos 	struct {
    182   1.1.1.4  christos 		uint32_t request_serial;
    183   1.1.1.4  christos 		uint32_t current_serial;
    184   1.1.1.4  christos 		dns_journal_t *journal;
    185       1.1  christos 	} ixfr;
    186   1.1.1.8  christos 
    187   1.1.1.8  christos 	dns_rdata_t firstsoa;
    188   1.1.1.8  christos 	unsigned char *firstsoa_data;
    189       1.1  christos };
    190       1.1  christos 
    191   1.1.1.4  christos #define XFRIN_MAGIC    ISC_MAGIC('X', 'f', 'r', 'I')
    192   1.1.1.4  christos #define VALID_XFRIN(x) ISC_MAGIC_VALID(x, XFRIN_MAGIC)
    193       1.1  christos 
    194       1.1  christos /**************************************************************************/
    195       1.1  christos /*
    196       1.1  christos  * Forward declarations.
    197       1.1  christos  */
    198       1.1  christos 
    199       1.1  christos static isc_result_t
    200   1.1.1.4  christos xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_task_t *task,
    201   1.1.1.4  christos 	     isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
    202   1.1.1.4  christos 	     dns_name_t *zonename, dns_rdataclass_t rdclass,
    203   1.1.1.4  christos 	     dns_rdatatype_t reqtype, const isc_sockaddr_t *masteraddr,
    204   1.1.1.4  christos 	     const isc_sockaddr_t *sourceaddr, isc_dscp_t dscp,
    205   1.1.1.4  christos 	     dns_tsigkey_t *tsigkey, dns_xfrin_ctx_t **xfrp);
    206       1.1  christos 
    207   1.1.1.4  christos static isc_result_t
    208   1.1.1.4  christos axfr_init(dns_xfrin_ctx_t *xfr);
    209   1.1.1.4  christos static isc_result_t
    210   1.1.1.4  christos axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);
    211   1.1.1.4  christos static isc_result_t
    212   1.1.1.4  christos axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name,
    213   1.1.1.4  christos 	     dns_ttl_t ttl, dns_rdata_t *rdata);
    214   1.1.1.4  christos static isc_result_t
    215   1.1.1.4  christos axfr_apply(dns_xfrin_ctx_t *xfr);
    216   1.1.1.4  christos static isc_result_t
    217   1.1.1.4  christos axfr_commit(dns_xfrin_ctx_t *xfr);
    218   1.1.1.4  christos static isc_result_t
    219   1.1.1.4  christos axfr_finalize(dns_xfrin_ctx_t *xfr);
    220   1.1.1.4  christos 
    221   1.1.1.4  christos static isc_result_t
    222   1.1.1.4  christos ixfr_init(dns_xfrin_ctx_t *xfr);
    223   1.1.1.4  christos static isc_result_t
    224   1.1.1.4  christos ixfr_apply(dns_xfrin_ctx_t *xfr);
    225   1.1.1.4  christos static isc_result_t
    226   1.1.1.4  christos ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name,
    227   1.1.1.4  christos 	     dns_ttl_t ttl, dns_rdata_t *rdata);
    228   1.1.1.4  christos static isc_result_t
    229   1.1.1.4  christos ixfr_commit(dns_xfrin_ctx_t *xfr);
    230   1.1.1.4  christos 
    231   1.1.1.4  christos static isc_result_t
    232   1.1.1.4  christos xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, uint32_t ttl,
    233   1.1.1.4  christos        dns_rdata_t *rdata);
    234   1.1.1.4  christos 
    235   1.1.1.4  christos static isc_result_t
    236   1.1.1.4  christos xfrin_start(dns_xfrin_ctx_t *xfr);
    237   1.1.1.4  christos 
    238   1.1.1.4  christos static void
    239   1.1.1.4  christos xfrin_connect_done(isc_task_t *task, isc_event_t *event);
    240   1.1.1.4  christos static isc_result_t
    241   1.1.1.4  christos xfrin_send_request(dns_xfrin_ctx_t *xfr);
    242   1.1.1.4  christos static void
    243   1.1.1.4  christos xfrin_send_done(isc_task_t *task, isc_event_t *event);
    244   1.1.1.4  christos static void
    245   1.1.1.4  christos xfrin_recv_done(isc_task_t *task, isc_event_t *event);
    246   1.1.1.4  christos static void
    247   1.1.1.4  christos xfrin_timeout(isc_task_t *task, isc_event_t *event);
    248   1.1.1.4  christos 
    249   1.1.1.4  christos static void
    250   1.1.1.4  christos maybe_free(dns_xfrin_ctx_t *xfr);
    251       1.1  christos 
    252       1.1  christos static void
    253       1.1  christos xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg);
    254       1.1  christos static isc_result_t
    255       1.1  christos render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf);
    256       1.1  christos 
    257       1.1  christos static void
    258       1.1  christos xfrin_logv(int level, const char *zonetext, const isc_sockaddr_t *masteraddr,
    259   1.1.1.4  christos 	   const char *fmt, va_list ap) ISC_FORMAT_PRINTF(4, 0);
    260       1.1  christos 
    261       1.1  christos static void
    262       1.1  christos xfrin_log1(int level, const char *zonetext, const isc_sockaddr_t *masteraddr,
    263   1.1.1.4  christos 	   const char *fmt, ...) ISC_FORMAT_PRINTF(4, 5);
    264       1.1  christos 
    265       1.1  christos static void
    266       1.1  christos xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
    267   1.1.1.4  christos 	ISC_FORMAT_PRINTF(3, 4);
    268       1.1  christos 
    269       1.1  christos /**************************************************************************/
    270       1.1  christos /*
    271       1.1  christos  * AXFR handling
    272       1.1  christos  */
    273       1.1  christos 
    274       1.1  christos static isc_result_t
    275       1.1  christos axfr_init(dns_xfrin_ctx_t *xfr) {
    276       1.1  christos 	isc_result_t result;
    277       1.1  christos 
    278   1.1.1.2  christos 	xfr->is_ixfr = false;
    279       1.1  christos 
    280   1.1.1.4  christos 	if (xfr->db != NULL) {
    281       1.1  christos 		dns_db_detach(&xfr->db);
    282   1.1.1.4  christos 	}
    283       1.1  christos 
    284       1.1  christos 	CHECK(axfr_makedb(xfr, &xfr->db));
    285       1.1  christos 	dns_rdatacallbacks_init(&xfr->axfr);
    286       1.1  christos 	CHECK(dns_db_beginload(xfr->db, &xfr->axfr));
    287       1.1  christos 	result = ISC_R_SUCCESS;
    288   1.1.1.4  christos failure:
    289       1.1  christos 	return (result);
    290       1.1  christos }
    291       1.1  christos 
    292       1.1  christos static isc_result_t
    293       1.1  christos axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
    294       1.1  christos 	isc_result_t result;
    295       1.1  christos 
    296       1.1  christos 	result = dns_db_create(xfr->mctx, /* XXX */
    297   1.1.1.4  christos 			       "rbt",	  /* XXX guess */
    298   1.1.1.4  christos 			       &xfr->name, dns_dbtype_zone, xfr->rdclass, 0,
    299   1.1.1.4  christos 			       NULL, /* XXX guess */
    300       1.1  christos 			       dbp);
    301       1.1  christos 	if (result == ISC_R_SUCCESS) {
    302       1.1  christos 		dns_zone_rpz_enable_db(xfr->zone, *dbp);
    303       1.1  christos 		dns_zone_catz_enable_db(xfr->zone, *dbp);
    304       1.1  christos 	}
    305       1.1  christos 	return (result);
    306       1.1  christos }
    307       1.1  christos 
    308       1.1  christos static isc_result_t
    309   1.1.1.4  christos axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name,
    310   1.1.1.4  christos 	     dns_ttl_t ttl, dns_rdata_t *rdata) {
    311       1.1  christos 	isc_result_t result;
    312       1.1  christos 
    313       1.1  christos 	dns_difftuple_t *tuple = NULL;
    314       1.1  christos 
    315   1.1.1.4  christos 	if (rdata->rdclass != xfr->rdclass) {
    316   1.1.1.4  christos 		return (DNS_R_BADCLASS);
    317   1.1.1.4  christos 	}
    318       1.1  christos 
    319       1.1  christos 	CHECK(dns_zone_checknames(xfr->zone, name, rdata));
    320   1.1.1.4  christos 	CHECK(dns_difftuple_create(xfr->diff.mctx, op, name, ttl, rdata,
    321   1.1.1.4  christos 				   &tuple));
    322       1.1  christos 	dns_diff_append(&xfr->diff, &tuple);
    323   1.1.1.4  christos 	if (++xfr->difflen > 100) {
    324       1.1  christos 		CHECK(axfr_apply(xfr));
    325   1.1.1.4  christos 	}
    326       1.1  christos 	result = ISC_R_SUCCESS;
    327   1.1.1.4  christos failure:
    328       1.1  christos 	return (result);
    329       1.1  christos }
    330       1.1  christos 
    331       1.1  christos /*
    332       1.1  christos  * Store a set of AXFR RRs in the database.
    333       1.1  christos  */
    334       1.1  christos static isc_result_t
    335       1.1  christos axfr_apply(dns_xfrin_ctx_t *xfr) {
    336       1.1  christos 	isc_result_t result;
    337   1.1.1.2  christos 	uint64_t records;
    338       1.1  christos 
    339       1.1  christos 	CHECK(dns_diff_load(&xfr->diff, xfr->axfr.add, xfr->axfr.add_private));
    340       1.1  christos 	xfr->difflen = 0;
    341       1.1  christos 	dns_diff_clear(&xfr->diff);
    342       1.1  christos 	if (xfr->maxrecords != 0U) {
    343       1.1  christos 		result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL);
    344       1.1  christos 		if (result == ISC_R_SUCCESS && records > xfr->maxrecords) {
    345       1.1  christos 			result = DNS_R_TOOMANYRECORDS;
    346       1.1  christos 			goto failure;
    347       1.1  christos 		}
    348       1.1  christos 	}
    349       1.1  christos 	result = ISC_R_SUCCESS;
    350   1.1.1.4  christos failure:
    351       1.1  christos 	return (result);
    352       1.1  christos }
    353       1.1  christos 
    354       1.1  christos static isc_result_t
    355       1.1  christos axfr_commit(dns_xfrin_ctx_t *xfr) {
    356       1.1  christos 	isc_result_t result;
    357       1.1  christos 
    358       1.1  christos 	CHECK(axfr_apply(xfr));
    359       1.1  christos 	CHECK(dns_db_endload(xfr->db, &xfr->axfr));
    360   1.1.1.2  christos 	CHECK(dns_zone_verifydb(xfr->zone, xfr->db, NULL));
    361       1.1  christos 
    362       1.1  christos 	result = ISC_R_SUCCESS;
    363   1.1.1.4  christos failure:
    364       1.1  christos 	return (result);
    365       1.1  christos }
    366       1.1  christos 
    367       1.1  christos static isc_result_t
    368       1.1  christos axfr_finalize(dns_xfrin_ctx_t *xfr) {
    369       1.1  christos 	isc_result_t result;
    370       1.1  christos 
    371   1.1.1.2  christos 	CHECK(dns_zone_replacedb(xfr->zone, xfr->db, true));
    372       1.1  christos 
    373       1.1  christos 	result = ISC_R_SUCCESS;
    374   1.1.1.4  christos failure:
    375       1.1  christos 	return (result);
    376       1.1  christos }
    377       1.1  christos 
    378       1.1  christos /**************************************************************************/
    379       1.1  christos /*
    380       1.1  christos  * IXFR handling
    381       1.1  christos  */
    382       1.1  christos 
    383       1.1  christos static isc_result_t
    384       1.1  christos ixfr_init(dns_xfrin_ctx_t *xfr) {
    385       1.1  christos 	isc_result_t result;
    386       1.1  christos 	char *journalfile;
    387       1.1  christos 
    388       1.1  christos 	if (xfr->reqtype != dns_rdatatype_ixfr) {
    389       1.1  christos 		xfrin_log(xfr, ISC_LOG_ERROR,
    390       1.1  christos 			  "got incremental response to AXFR request");
    391       1.1  christos 		return (DNS_R_FORMERR);
    392       1.1  christos 	}
    393       1.1  christos 
    394   1.1.1.2  christos 	xfr->is_ixfr = true;
    395       1.1  christos 	INSIST(xfr->db != NULL);
    396       1.1  christos 	xfr->difflen = 0;
    397       1.1  christos 
    398       1.1  christos 	journalfile = dns_zone_getjournal(xfr->zone);
    399   1.1.1.4  christos 	if (journalfile != NULL) {
    400       1.1  christos 		CHECK(dns_journal_open(xfr->mctx, journalfile,
    401       1.1  christos 				       DNS_JOURNAL_CREATE, &xfr->ixfr.journal));
    402   1.1.1.4  christos 	}
    403       1.1  christos 
    404       1.1  christos 	result = ISC_R_SUCCESS;
    405   1.1.1.4  christos failure:
    406       1.1  christos 	return (result);
    407       1.1  christos }
    408       1.1  christos 
    409       1.1  christos static isc_result_t
    410   1.1.1.4  christos ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op, dns_name_t *name,
    411   1.1.1.4  christos 	     dns_ttl_t ttl, dns_rdata_t *rdata) {
    412       1.1  christos 	isc_result_t result;
    413       1.1  christos 	dns_difftuple_t *tuple = NULL;
    414       1.1  christos 
    415   1.1.1.4  christos 	if (rdata->rdclass != xfr->rdclass) {
    416   1.1.1.4  christos 		return (DNS_R_BADCLASS);
    417   1.1.1.4  christos 	}
    418       1.1  christos 
    419   1.1.1.4  christos 	if (op == DNS_DIFFOP_ADD) {
    420       1.1  christos 		CHECK(dns_zone_checknames(xfr->zone, name, rdata));
    421   1.1.1.4  christos 	}
    422   1.1.1.4  christos 	CHECK(dns_difftuple_create(xfr->diff.mctx, op, name, ttl, rdata,
    423   1.1.1.4  christos 				   &tuple));
    424       1.1  christos 	dns_diff_append(&xfr->diff, &tuple);
    425   1.1.1.4  christos 	if (++xfr->difflen > 100) {
    426       1.1  christos 		CHECK(ixfr_apply(xfr));
    427   1.1.1.4  christos 	}
    428       1.1  christos 	result = ISC_R_SUCCESS;
    429   1.1.1.4  christos failure:
    430       1.1  christos 	return (result);
    431       1.1  christos }
    432       1.1  christos 
    433       1.1  christos /*
    434       1.1  christos  * Apply a set of IXFR changes to the database.
    435       1.1  christos  */
    436       1.1  christos static isc_result_t
    437       1.1  christos ixfr_apply(dns_xfrin_ctx_t *xfr) {
    438       1.1  christos 	isc_result_t result;
    439   1.1.1.2  christos 	uint64_t records;
    440       1.1  christos 
    441       1.1  christos 	if (xfr->ver == NULL) {
    442       1.1  christos 		CHECK(dns_db_newversion(xfr->db, &xfr->ver));
    443   1.1.1.4  christos 		if (xfr->ixfr.journal != NULL) {
    444       1.1  christos 			CHECK(dns_journal_begin_transaction(xfr->ixfr.journal));
    445   1.1.1.4  christos 		}
    446       1.1  christos 	}
    447       1.1  christos 	CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver));
    448       1.1  christos 	if (xfr->maxrecords != 0U) {
    449       1.1  christos 		result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL);
    450       1.1  christos 		if (result == ISC_R_SUCCESS && records > xfr->maxrecords) {
    451       1.1  christos 			result = DNS_R_TOOMANYRECORDS;
    452       1.1  christos 			goto failure;
    453       1.1  christos 		}
    454       1.1  christos 	}
    455       1.1  christos 	if (xfr->ixfr.journal != NULL) {
    456       1.1  christos 		result = dns_journal_writediff(xfr->ixfr.journal, &xfr->diff);
    457   1.1.1.4  christos 		if (result != ISC_R_SUCCESS) {
    458       1.1  christos 			goto failure;
    459   1.1.1.4  christos 		}
    460       1.1  christos 	}
    461       1.1  christos 	dns_diff_clear(&xfr->diff);
    462       1.1  christos 	xfr->difflen = 0;
    463       1.1  christos 	result = ISC_R_SUCCESS;
    464   1.1.1.4  christos failure:
    465       1.1  christos 	return (result);
    466       1.1  christos }
    467       1.1  christos 
    468       1.1  christos static isc_result_t
    469       1.1  christos ixfr_commit(dns_xfrin_ctx_t *xfr) {
    470       1.1  christos 	isc_result_t result;
    471       1.1  christos 
    472       1.1  christos 	CHECK(ixfr_apply(xfr));
    473       1.1  christos 	if (xfr->ver != NULL) {
    474   1.1.1.2  christos 		CHECK(dns_zone_verifydb(xfr->zone, xfr->db, xfr->ver));
    475       1.1  christos 		/* XXX enter ready-to-commit state here */
    476   1.1.1.4  christos 		if (xfr->ixfr.journal != NULL) {
    477       1.1  christos 			CHECK(dns_journal_commit(xfr->ixfr.journal));
    478   1.1.1.4  christos 		}
    479   1.1.1.2  christos 		dns_db_closeversion(xfr->db, &xfr->ver, true);
    480       1.1  christos 		dns_zone_markdirty(xfr->zone);
    481       1.1  christos 	}
    482       1.1  christos 	result = ISC_R_SUCCESS;
    483   1.1.1.4  christos failure:
    484       1.1  christos 	return (result);
    485       1.1  christos }
    486       1.1  christos 
    487       1.1  christos /**************************************************************************/
    488       1.1  christos /*
    489       1.1  christos  * Common AXFR/IXFR protocol code
    490       1.1  christos  */
    491       1.1  christos 
    492       1.1  christos /*
    493       1.1  christos  * Handle a single incoming resource record according to the current
    494       1.1  christos  * state.
    495       1.1  christos  */
    496       1.1  christos static isc_result_t
    497   1.1.1.2  christos xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, uint32_t ttl,
    498   1.1.1.4  christos        dns_rdata_t *rdata) {
    499       1.1  christos 	isc_result_t result;
    500       1.1  christos 
    501       1.1  christos 	xfr->nrecs++;
    502       1.1  christos 
    503       1.1  christos 	if (rdata->type == dns_rdatatype_none ||
    504  1.1.1.10  christos 	    dns_rdatatype_ismeta(rdata->type))
    505  1.1.1.10  christos 	{
    506       1.1  christos 		FAIL(DNS_R_FORMERR);
    507   1.1.1.4  christos 	}
    508       1.1  christos 
    509   1.1.1.7  christos 	/*
    510   1.1.1.7  christos 	 * Immediately reject the entire transfer if the RR that is currently
    511   1.1.1.7  christos 	 * being processed is an SOA record that is not placed at the zone
    512   1.1.1.7  christos 	 * apex.
    513   1.1.1.7  christos 	 */
    514   1.1.1.7  christos 	if (rdata->type == dns_rdatatype_soa &&
    515  1.1.1.10  christos 	    !dns_name_equal(&xfr->name, name))
    516  1.1.1.10  christos 	{
    517   1.1.1.7  christos 		char namebuf[DNS_NAME_FORMATSIZE];
    518   1.1.1.7  christos 		dns_name_format(name, namebuf, sizeof(namebuf));
    519   1.1.1.7  christos 		xfrin_log(xfr, ISC_LOG_DEBUG(3), "SOA name mismatch: '%s'",
    520   1.1.1.7  christos 			  namebuf);
    521   1.1.1.7  christos 		FAIL(DNS_R_NOTZONETOP);
    522   1.1.1.7  christos 	}
    523   1.1.1.7  christos 
    524   1.1.1.4  christos redo:
    525       1.1  christos 	switch (xfr->state) {
    526       1.1  christos 	case XFRST_SOAQUERY:
    527       1.1  christos 		if (rdata->type != dns_rdatatype_soa) {
    528       1.1  christos 			xfrin_log(xfr, ISC_LOG_ERROR,
    529       1.1  christos 				  "non-SOA response to SOA query");
    530       1.1  christos 			FAIL(DNS_R_FORMERR);
    531       1.1  christos 		}
    532       1.1  christos 		xfr->end_serial = dns_soa_getserial(rdata);
    533       1.1  christos 		if (!DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) &&
    534   1.1.1.4  christos 		    !dns_zone_isforced(xfr->zone))
    535   1.1.1.4  christos 		{
    536       1.1  christos 			xfrin_log(xfr, ISC_LOG_DEBUG(3),
    537       1.1  christos 				  "requested serial %u, "
    538       1.1  christos 				  "master has %u, not updating",
    539       1.1  christos 				  xfr->ixfr.request_serial, xfr->end_serial);
    540       1.1  christos 			FAIL(DNS_R_UPTODATE);
    541       1.1  christos 		}
    542       1.1  christos 		xfr->state = XFRST_GOTSOA;
    543       1.1  christos 		break;
    544       1.1  christos 
    545       1.1  christos 	case XFRST_GOTSOA:
    546       1.1  christos 		/*
    547       1.1  christos 		 * Skip other records in the answer section.
    548       1.1  christos 		 */
    549       1.1  christos 		break;
    550       1.1  christos 
    551       1.1  christos 	case XFRST_INITIALSOA:
    552       1.1  christos 		if (rdata->type != dns_rdatatype_soa) {
    553       1.1  christos 			xfrin_log(xfr, ISC_LOG_ERROR,
    554       1.1  christos 				  "first RR in zone transfer must be SOA");
    555       1.1  christos 			FAIL(DNS_R_FORMERR);
    556       1.1  christos 		}
    557       1.1  christos 		/*
    558       1.1  christos 		 * Remember the serial number in the initial SOA.
    559       1.1  christos 		 * We need it to recognize the end of an IXFR.
    560       1.1  christos 		 */
    561       1.1  christos 		xfr->end_serial = dns_soa_getserial(rdata);
    562       1.1  christos 		if (xfr->reqtype == dns_rdatatype_ixfr &&
    563   1.1.1.4  christos 		    !DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) &&
    564   1.1.1.4  christos 		    !dns_zone_isforced(xfr->zone))
    565       1.1  christos 		{
    566       1.1  christos 			/*
    567       1.1  christos 			 * This must be the single SOA record that is
    568       1.1  christos 			 * sent when the current version on the master
    569       1.1  christos 			 * is not newer than the version in the request.
    570       1.1  christos 			 */
    571       1.1  christos 			xfrin_log(xfr, ISC_LOG_DEBUG(3),
    572       1.1  christos 				  "requested serial %u, "
    573       1.1  christos 				  "master has %u, not updating",
    574       1.1  christos 				  xfr->ixfr.request_serial, xfr->end_serial);
    575       1.1  christos 			FAIL(DNS_R_UPTODATE);
    576       1.1  christos 		}
    577   1.1.1.4  christos 		if (xfr->reqtype == dns_rdatatype_axfr) {
    578   1.1.1.2  christos 			xfr->checkid = false;
    579   1.1.1.4  christos 		}
    580   1.1.1.8  christos 		xfr->firstsoa = *rdata;
    581   1.1.1.8  christos 		if (xfr->firstsoa_data != NULL) {
    582   1.1.1.8  christos 			isc_mem_free(xfr->mctx, xfr->firstsoa_data);
    583   1.1.1.8  christos 		}
    584   1.1.1.8  christos 		xfr->firstsoa_data = isc_mem_allocate(xfr->mctx, rdata->length);
    585   1.1.1.8  christos 		memcpy(xfr->firstsoa_data, rdata->data, rdata->length);
    586   1.1.1.8  christos 		xfr->firstsoa.data = xfr->firstsoa_data;
    587       1.1  christos 		xfr->state = XFRST_FIRSTDATA;
    588       1.1  christos 		break;
    589       1.1  christos 
    590       1.1  christos 	case XFRST_FIRSTDATA:
    591       1.1  christos 		/*
    592       1.1  christos 		 * If the transfer begins with one SOA record, it is an AXFR,
    593       1.1  christos 		 * if it begins with two SOAs, it is an IXFR.
    594       1.1  christos 		 */
    595       1.1  christos 		if (xfr->reqtype == dns_rdatatype_ixfr &&
    596       1.1  christos 		    rdata->type == dns_rdatatype_soa &&
    597   1.1.1.4  christos 		    xfr->ixfr.request_serial == dns_soa_getserial(rdata))
    598   1.1.1.4  christos 		{
    599       1.1  christos 			xfrin_log(xfr, ISC_LOG_DEBUG(3),
    600       1.1  christos 				  "got incremental response");
    601       1.1  christos 			CHECK(ixfr_init(xfr));
    602       1.1  christos 			xfr->state = XFRST_IXFR_DELSOA;
    603       1.1  christos 		} else {
    604       1.1  christos 			xfrin_log(xfr, ISC_LOG_DEBUG(3),
    605       1.1  christos 				  "got nonincremental response");
    606       1.1  christos 			CHECK(axfr_init(xfr));
    607       1.1  christos 			xfr->state = XFRST_AXFR;
    608       1.1  christos 		}
    609       1.1  christos 		goto redo;
    610       1.1  christos 
    611       1.1  christos 	case XFRST_IXFR_DELSOA:
    612       1.1  christos 		INSIST(rdata->type == dns_rdatatype_soa);
    613       1.1  christos 		CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
    614       1.1  christos 		xfr->state = XFRST_IXFR_DEL;
    615       1.1  christos 		break;
    616       1.1  christos 
    617       1.1  christos 	case XFRST_IXFR_DEL:
    618       1.1  christos 		if (rdata->type == dns_rdatatype_soa) {
    619   1.1.1.2  christos 			uint32_t soa_serial = dns_soa_getserial(rdata);
    620       1.1  christos 			xfr->state = XFRST_IXFR_ADDSOA;
    621       1.1  christos 			xfr->ixfr.current_serial = soa_serial;
    622       1.1  christos 			goto redo;
    623       1.1  christos 		}
    624       1.1  christos 		CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
    625       1.1  christos 		break;
    626       1.1  christos 
    627       1.1  christos 	case XFRST_IXFR_ADDSOA:
    628       1.1  christos 		INSIST(rdata->type == dns_rdatatype_soa);
    629       1.1  christos 		CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
    630       1.1  christos 		xfr->state = XFRST_IXFR_ADD;
    631       1.1  christos 		break;
    632       1.1  christos 
    633       1.1  christos 	case XFRST_IXFR_ADD:
    634       1.1  christos 		if (rdata->type == dns_rdatatype_soa) {
    635   1.1.1.2  christos 			uint32_t soa_serial = dns_soa_getserial(rdata);
    636       1.1  christos 			if (soa_serial == xfr->end_serial) {
    637       1.1  christos 				CHECK(ixfr_commit(xfr));
    638       1.1  christos 				xfr->state = XFRST_IXFR_END;
    639       1.1  christos 				break;
    640       1.1  christos 			} else if (soa_serial != xfr->ixfr.current_serial) {
    641       1.1  christos 				xfrin_log(xfr, ISC_LOG_ERROR,
    642       1.1  christos 					  "IXFR out of sync: "
    643       1.1  christos 					  "expected serial %u, got %u",
    644       1.1  christos 					  xfr->ixfr.current_serial, soa_serial);
    645       1.1  christos 				FAIL(DNS_R_FORMERR);
    646       1.1  christos 			} else {
    647       1.1  christos 				CHECK(ixfr_commit(xfr));
    648       1.1  christos 				xfr->state = XFRST_IXFR_DELSOA;
    649       1.1  christos 				goto redo;
    650       1.1  christos 			}
    651       1.1  christos 		}
    652       1.1  christos 		if (rdata->type == dns_rdatatype_ns &&
    653  1.1.1.10  christos 		    dns_name_iswildcard(name))
    654  1.1.1.10  christos 		{
    655       1.1  christos 			FAIL(DNS_R_INVALIDNS);
    656   1.1.1.4  christos 		}
    657       1.1  christos 		CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
    658       1.1  christos 		break;
    659       1.1  christos 
    660       1.1  christos 	case XFRST_AXFR:
    661       1.1  christos 		/*
    662       1.1  christos 		 * Old BINDs sent cross class A records for non IN classes.
    663       1.1  christos 		 */
    664       1.1  christos 		if (rdata->type == dns_rdatatype_a &&
    665       1.1  christos 		    rdata->rdclass != xfr->rdclass &&
    666       1.1  christos 		    xfr->rdclass != dns_rdataclass_in)
    667   1.1.1.4  christos 		{
    668       1.1  christos 			break;
    669   1.1.1.4  christos 		}
    670       1.1  christos 		CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
    671       1.1  christos 		if (rdata->type == dns_rdatatype_soa) {
    672   1.1.1.8  christos 			/*
    673   1.1.1.8  christos 			 * Use dns_rdata_compare instead of memcmp to
    674   1.1.1.8  christos 			 * allow for case differences.
    675   1.1.1.8  christos 			 */
    676   1.1.1.8  christos 			if (dns_rdata_compare(rdata, &xfr->firstsoa) != 0) {
    677   1.1.1.8  christos 				xfrin_log(xfr, ISC_LOG_ERROR,
    678   1.1.1.8  christos 					  "start and ending SOA records "
    679   1.1.1.8  christos 					  "mismatch");
    680   1.1.1.8  christos 				FAIL(DNS_R_FORMERR);
    681   1.1.1.8  christos 			}
    682       1.1  christos 			CHECK(axfr_commit(xfr));
    683       1.1  christos 			xfr->state = XFRST_AXFR_END;
    684       1.1  christos 			break;
    685       1.1  christos 		}
    686       1.1  christos 		break;
    687       1.1  christos 	case XFRST_AXFR_END:
    688       1.1  christos 	case XFRST_IXFR_END:
    689       1.1  christos 		FAIL(DNS_R_EXTRADATA);
    690   1.1.1.9  christos 		FALLTHROUGH;
    691       1.1  christos 	default:
    692   1.1.1.9  christos 		UNREACHABLE();
    693       1.1  christos 	}
    694       1.1  christos 	result = ISC_R_SUCCESS;
    695   1.1.1.4  christos failure:
    696       1.1  christos 	return (result);
    697       1.1  christos }
    698       1.1  christos 
    699       1.1  christos isc_result_t
    700       1.1  christos dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
    701   1.1.1.2  christos 		 const isc_sockaddr_t *masteraddr,
    702   1.1.1.4  christos 		 const isc_sockaddr_t *sourceaddr, isc_dscp_t dscp,
    703   1.1.1.4  christos 		 dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
    704   1.1.1.2  christos 		 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
    705   1.1.1.2  christos 		 isc_task_t *task, dns_xfrindone_t done,
    706   1.1.1.4  christos 		 dns_xfrin_ctx_t **xfrp) {
    707       1.1  christos 	dns_name_t *zonename = dns_zone_getorigin(zone);
    708       1.1  christos 	dns_xfrin_ctx_t *xfr = NULL;
    709       1.1  christos 	isc_result_t result;
    710       1.1  christos 	dns_db_t *db = NULL;
    711       1.1  christos 
    712       1.1  christos 	REQUIRE(xfrp != NULL && *xfrp == NULL);
    713       1.1  christos 
    714       1.1  christos 	(void)dns_zone_getdb(zone, &db);
    715       1.1  christos 
    716   1.1.1.4  christos 	if (xfrtype == dns_rdatatype_soa || xfrtype == dns_rdatatype_ixfr) {
    717       1.1  christos 		REQUIRE(db != NULL);
    718   1.1.1.4  christos 	}
    719       1.1  christos 
    720       1.1  christos 	CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename,
    721       1.1  christos 			   dns_zone_getclass(zone), xfrtype, masteraddr,
    722       1.1  christos 			   sourceaddr, dscp, tsigkey, &xfr));
    723       1.1  christos 
    724   1.1.1.3  christos 	if (db != NULL) {
    725   1.1.1.3  christos 		xfr->zone_had_db = true;
    726   1.1.1.3  christos 	}
    727   1.1.1.3  christos 
    728       1.1  christos 	CHECK(xfrin_start(xfr));
    729       1.1  christos 
    730       1.1  christos 	xfr->done = done;
    731   1.1.1.4  christos 	if (xfr->done != NULL) {
    732       1.1  christos 		xfr->refcount++;
    733   1.1.1.4  christos 	}
    734       1.1  christos 	*xfrp = xfr;
    735       1.1  christos 
    736   1.1.1.4  christos failure:
    737   1.1.1.4  christos 	if (db != NULL) {
    738       1.1  christos 		dns_db_detach(&db);
    739   1.1.1.4  christos 	}
    740       1.1  christos 	if (result != ISC_R_SUCCESS) {
    741   1.1.1.4  christos 		char zonetext[DNS_NAME_MAXTEXT + 32];
    742       1.1  christos 		dns_zone_name(zone, zonetext, sizeof(zonetext));
    743       1.1  christos 		xfrin_log1(ISC_LOG_ERROR, zonetext, masteraddr,
    744       1.1  christos 			   "zone transfer setup failed");
    745       1.1  christos 	}
    746       1.1  christos 	return (result);
    747       1.1  christos }
    748       1.1  christos 
    749       1.1  christos void
    750       1.1  christos dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
    751   1.1.1.4  christos 	if (!xfr->shuttingdown) {
    752       1.1  christos 		xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
    753   1.1.1.4  christos 	}
    754       1.1  christos }
    755       1.1  christos 
    756       1.1  christos void
    757       1.1  christos dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target) {
    758       1.1  christos 	REQUIRE(target != NULL && *target == NULL);
    759       1.1  christos 	source->refcount++;
    760       1.1  christos 	*target = source;
    761       1.1  christos }
    762       1.1  christos 
    763       1.1  christos void
    764       1.1  christos dns_xfrin_detach(dns_xfrin_ctx_t **xfrp) {
    765       1.1  christos 	dns_xfrin_ctx_t *xfr = *xfrp;
    766   1.1.1.4  christos 	*xfrp = NULL;
    767       1.1  christos 	INSIST(xfr->refcount > 0);
    768       1.1  christos 	xfr->refcount--;
    769       1.1  christos 	maybe_free(xfr);
    770       1.1  christos }
    771       1.1  christos 
    772       1.1  christos static void
    773       1.1  christos xfrin_cancelio(dns_xfrin_ctx_t *xfr) {
    774       1.1  christos 	if (xfr->connects > 0) {
    775       1.1  christos 		isc_socket_cancel(xfr->socket, xfr->task,
    776       1.1  christos 				  ISC_SOCKCANCEL_CONNECT);
    777       1.1  christos 	} else if (xfr->recvs > 0) {
    778       1.1  christos 		dns_tcpmsg_cancelread(&xfr->tcpmsg);
    779       1.1  christos 	} else if (xfr->sends > 0) {
    780   1.1.1.4  christos 		isc_socket_cancel(xfr->socket, xfr->task, ISC_SOCKCANCEL_SEND);
    781       1.1  christos 	}
    782       1.1  christos }
    783       1.1  christos 
    784       1.1  christos static void
    785       1.1  christos xfrin_reset(dns_xfrin_ctx_t *xfr) {
    786       1.1  christos 	REQUIRE(VALID_XFRIN(xfr));
    787       1.1  christos 
    788       1.1  christos 	xfrin_log(xfr, ISC_LOG_INFO, "resetting");
    789       1.1  christos 
    790       1.1  christos 	xfrin_cancelio(xfr);
    791       1.1  christos 
    792   1.1.1.4  christos 	if (xfr->socket != NULL) {
    793       1.1  christos 		isc_socket_detach(&xfr->socket);
    794   1.1.1.4  christos 	}
    795       1.1  christos 
    796   1.1.1.4  christos 	if (xfr->lasttsig != NULL) {
    797       1.1  christos 		isc_buffer_free(&xfr->lasttsig);
    798   1.1.1.4  christos 	}
    799       1.1  christos 
    800       1.1  christos 	dns_diff_clear(&xfr->diff);
    801       1.1  christos 	xfr->difflen = 0;
    802       1.1  christos 
    803   1.1.1.4  christos 	if (xfr->ixfr.journal != NULL) {
    804       1.1  christos 		dns_journal_destroy(&xfr->ixfr.journal);
    805   1.1.1.4  christos 	}
    806       1.1  christos 
    807   1.1.1.4  christos 	if (xfr->axfr.add_private != NULL) {
    808       1.1  christos 		(void)dns_db_endload(xfr->db, &xfr->axfr);
    809   1.1.1.4  christos 	}
    810       1.1  christos 
    811       1.1  christos 	if (xfr->tcpmsg_valid) {
    812       1.1  christos 		dns_tcpmsg_invalidate(&xfr->tcpmsg);
    813   1.1.1.2  christos 		xfr->tcpmsg_valid = false;
    814       1.1  christos 	}
    815       1.1  christos 
    816   1.1.1.4  christos 	if (xfr->ver != NULL) {
    817   1.1.1.2  christos 		dns_db_closeversion(xfr->db, &xfr->ver, false);
    818   1.1.1.4  christos 	}
    819       1.1  christos }
    820       1.1  christos 
    821       1.1  christos static void
    822       1.1  christos xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
    823       1.1  christos 	if (result != DNS_R_UPTODATE && result != DNS_R_TOOMANYRECORDS) {
    824   1.1.1.4  christos 		xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg,
    825   1.1.1.4  christos 			  isc_result_totext(result));
    826   1.1.1.4  christos 		if (xfr->is_ixfr) {
    827       1.1  christos 			/* Pass special result code to force AXFR retry */
    828       1.1  christos 			result = DNS_R_BADIXFR;
    829   1.1.1.4  christos 		}
    830       1.1  christos 	}
    831       1.1  christos 	xfrin_cancelio(xfr);
    832       1.1  christos 	/*
    833       1.1  christos 	 * Close the journal.
    834       1.1  christos 	 */
    835   1.1.1.4  christos 	if (xfr->ixfr.journal != NULL) {
    836       1.1  christos 		dns_journal_destroy(&xfr->ixfr.journal);
    837   1.1.1.4  christos 	}
    838       1.1  christos 	if (xfr->done != NULL) {
    839       1.1  christos 		(xfr->done)(xfr->zone, result);
    840       1.1  christos 		xfr->done = NULL;
    841       1.1  christos 	}
    842   1.1.1.2  christos 	xfr->shuttingdown = true;
    843       1.1  christos 	xfr->shutdown_result = result;
    844       1.1  christos 	maybe_free(xfr);
    845       1.1  christos }
    846       1.1  christos 
    847       1.1  christos static isc_result_t
    848   1.1.1.4  christos xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_task_t *task,
    849   1.1.1.4  christos 	     isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
    850   1.1.1.4  christos 	     dns_name_t *zonename, dns_rdataclass_t rdclass,
    851   1.1.1.4  christos 	     dns_rdatatype_t reqtype, const isc_sockaddr_t *masteraddr,
    852   1.1.1.4  christos 	     const isc_sockaddr_t *sourceaddr, isc_dscp_t dscp,
    853   1.1.1.4  christos 	     dns_tsigkey_t *tsigkey, dns_xfrin_ctx_t **xfrp) {
    854       1.1  christos 	dns_xfrin_ctx_t *xfr = NULL;
    855       1.1  christos 	isc_result_t result;
    856       1.1  christos 
    857       1.1  christos 	xfr = isc_mem_get(mctx, sizeof(*xfr));
    858       1.1  christos 	xfr->mctx = NULL;
    859       1.1  christos 	isc_mem_attach(mctx, &xfr->mctx);
    860       1.1  christos 	xfr->refcount = 0;
    861       1.1  christos 	xfr->zone = NULL;
    862       1.1  christos 	dns_zone_iattach(zone, &xfr->zone);
    863       1.1  christos 	xfr->task = NULL;
    864       1.1  christos 	isc_task_attach(task, &xfr->task);
    865       1.1  christos 	xfr->timer = NULL;
    866       1.1  christos 	xfr->socketmgr = socketmgr;
    867       1.1  christos 	xfr->done = NULL;
    868       1.1  christos 
    869       1.1  christos 	xfr->connects = 0;
    870       1.1  christos 	xfr->sends = 0;
    871       1.1  christos 	xfr->recvs = 0;
    872   1.1.1.2  christos 	xfr->shuttingdown = false;
    873       1.1  christos 	xfr->shutdown_result = ISC_R_UNSET;
    874       1.1  christos 
    875       1.1  christos 	dns_name_init(&xfr->name, NULL);
    876       1.1  christos 	xfr->rdclass = rdclass;
    877   1.1.1.2  christos 	xfr->checkid = true;
    878   1.1.1.4  christos 	xfr->logit = true;
    879   1.1.1.4  christos 	xfr->id = (dns_messageid_t)isc_random16();
    880       1.1  christos 	xfr->reqtype = reqtype;
    881       1.1  christos 	xfr->dscp = dscp;
    882       1.1  christos 
    883       1.1  christos 	/* sockaddr */
    884       1.1  christos 	xfr->socket = NULL;
    885       1.1  christos 	/* qbuffer */
    886       1.1  christos 	/* qbuffer_data */
    887       1.1  christos 	/* tcpmsg */
    888   1.1.1.2  christos 	xfr->tcpmsg_valid = false;
    889       1.1  christos 
    890   1.1.1.3  christos 	xfr->zone_had_db = false;
    891       1.1  christos 	xfr->db = NULL;
    892   1.1.1.4  christos 	if (db != NULL) {
    893       1.1  christos 		dns_db_attach(db, &xfr->db);
    894   1.1.1.4  christos 	}
    895       1.1  christos 	xfr->ver = NULL;
    896       1.1  christos 	dns_diff_init(xfr->mctx, &xfr->diff);
    897       1.1  christos 	xfr->difflen = 0;
    898       1.1  christos 
    899   1.1.1.4  christos 	if (reqtype == dns_rdatatype_soa) {
    900       1.1  christos 		xfr->state = XFRST_SOAQUERY;
    901   1.1.1.4  christos 	} else {
    902       1.1  christos 		xfr->state = XFRST_INITIALSOA;
    903   1.1.1.4  christos 	}
    904       1.1  christos 	/* end_serial */
    905       1.1  christos 
    906       1.1  christos 	xfr->nmsg = 0;
    907       1.1  christos 	xfr->nrecs = 0;
    908       1.1  christos 	xfr->nbytes = 0;
    909       1.1  christos 	xfr->maxrecords = dns_zone_getmaxrecords(zone);
    910       1.1  christos 	isc_time_now(&xfr->start);
    911       1.1  christos 
    912       1.1  christos 	xfr->tsigkey = NULL;
    913   1.1.1.4  christos 	if (tsigkey != NULL) {
    914       1.1  christos 		dns_tsigkey_attach(tsigkey, &xfr->tsigkey);
    915   1.1.1.4  christos 	}
    916       1.1  christos 	xfr->lasttsig = NULL;
    917       1.1  christos 	xfr->tsigctx = NULL;
    918       1.1  christos 	xfr->sincetsig = 0;
    919   1.1.1.2  christos 	xfr->is_ixfr = false;
    920       1.1  christos 
    921       1.1  christos 	/* ixfr.request_serial */
    922       1.1  christos 	/* ixfr.current_serial */
    923       1.1  christos 	xfr->ixfr.journal = NULL;
    924       1.1  christos 
    925       1.1  christos 	xfr->axfr.add = NULL;
    926       1.1  christos 	xfr->axfr.add_private = NULL;
    927   1.1.1.8  christos 	dns_rdata_init(&xfr->firstsoa);
    928   1.1.1.8  christos 	xfr->firstsoa_data = NULL;
    929       1.1  christos 
    930   1.1.1.4  christos 	dns_name_dup(zonename, mctx, &xfr->name);
    931       1.1  christos 
    932       1.1  christos 	CHECK(isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
    933       1.1  christos 			       task, xfrin_timeout, xfr, &xfr->timer));
    934   1.1.1.4  christos 	CHECK(dns_timer_setidle(xfr->timer, dns_zone_getmaxxfrin(xfr->zone),
    935   1.1.1.4  christos 				dns_zone_getidlein(xfr->zone), false));
    936       1.1  christos 
    937       1.1  christos 	xfr->masteraddr = *masteraddr;
    938       1.1  christos 
    939       1.1  christos 	INSIST(isc_sockaddr_pf(masteraddr) == isc_sockaddr_pf(sourceaddr));
    940       1.1  christos 	xfr->sourceaddr = *sourceaddr;
    941       1.1  christos 	isc_sockaddr_setport(&xfr->sourceaddr, 0);
    942       1.1  christos 
    943       1.1  christos 	/*
    944   1.1.1.4  christos 	 * Reserve 2 bytes for TCP length at the beginning of the buffer.
    945       1.1  christos 	 */
    946       1.1  christos 	isc_buffer_init(&xfr->qbuffer, &xfr->qbuffer_data[2],
    947       1.1  christos 			sizeof(xfr->qbuffer_data) - 2);
    948       1.1  christos 
    949       1.1  christos 	xfr->magic = XFRIN_MAGIC;
    950       1.1  christos 	*xfrp = xfr;
    951       1.1  christos 	return (ISC_R_SUCCESS);
    952       1.1  christos 
    953   1.1.1.4  christos failure:
    954   1.1.1.4  christos 	if (xfr->timer != NULL) {
    955       1.1  christos 		isc_timer_detach(&xfr->timer);
    956   1.1.1.4  christos 	}
    957   1.1.1.4  christos 	if (dns_name_dynamic(&xfr->name)) {
    958       1.1  christos 		dns_name_free(&xfr->name, xfr->mctx);
    959   1.1.1.4  christos 	}
    960   1.1.1.4  christos 	if (xfr->tsigkey != NULL) {
    961       1.1  christos 		dns_tsigkey_detach(&xfr->tsigkey);
    962   1.1.1.4  christos 	}
    963   1.1.1.4  christos 	if (xfr->db != NULL) {
    964       1.1  christos 		dns_db_detach(&xfr->db);
    965   1.1.1.4  christos 	}
    966       1.1  christos 	isc_task_detach(&xfr->task);
    967       1.1  christos 	dns_zone_idetach(&xfr->zone);
    968       1.1  christos 	isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
    969       1.1  christos 
    970       1.1  christos 	return (result);
    971       1.1  christos }
    972       1.1  christos 
    973       1.1  christos static isc_result_t
    974       1.1  christos xfrin_start(dns_xfrin_ctx_t *xfr) {
    975       1.1  christos 	isc_result_t result;
    976       1.1  christos 	CHECK(isc_socket_create(xfr->socketmgr,
    977       1.1  christos 				isc_sockaddr_pf(&xfr->sourceaddr),
    978   1.1.1.4  christos 				isc_sockettype_tcp, &xfr->socket));
    979       1.1  christos 	isc_socket_setname(xfr->socket, "xfrin", NULL);
    980       1.1  christos #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
    981       1.1  christos 	CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr,
    982       1.1  christos 			      ISC_SOCKET_REUSEADDRESS));
    983   1.1.1.4  christos #endif /* ifndef BROKEN_TCP_BIND_BEFORE_CONNECT */
    984       1.1  christos 	isc_socket_dscp(xfr->socket, xfr->dscp);
    985       1.1  christos 	CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task,
    986       1.1  christos 				 xfrin_connect_done, xfr));
    987       1.1  christos 	xfr->connects++;
    988       1.1  christos 	return (ISC_R_SUCCESS);
    989   1.1.1.4  christos failure:
    990       1.1  christos 	xfrin_fail(xfr, result, "failed setting up socket");
    991       1.1  christos 	return (result);
    992       1.1  christos }
    993       1.1  christos 
    994       1.1  christos /* XXX the resolver could use this, too */
    995       1.1  christos 
    996       1.1  christos static isc_result_t
    997       1.1  christos render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf) {
    998       1.1  christos 	dns_compress_t cctx;
    999   1.1.1.2  christos 	bool cleanup_cctx = false;
   1000       1.1  christos 	isc_result_t result;
   1001       1.1  christos 
   1002       1.1  christos 	CHECK(dns_compress_init(&cctx, -1, mctx));
   1003   1.1.1.2  christos 	cleanup_cctx = true;
   1004       1.1  christos 	CHECK(dns_message_renderbegin(msg, &cctx, buf));
   1005       1.1  christos 	CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
   1006       1.1  christos 	CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
   1007       1.1  christos 	CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0));
   1008       1.1  christos 	CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0));
   1009       1.1  christos 	CHECK(dns_message_renderend(msg));
   1010       1.1  christos 	result = ISC_R_SUCCESS;
   1011   1.1.1.4  christos failure:
   1012   1.1.1.4  christos 	if (cleanup_cctx) {
   1013       1.1  christos 		dns_compress_invalidate(&cctx);
   1014   1.1.1.4  christos 	}
   1015       1.1  christos 	return (result);
   1016       1.1  christos }
   1017       1.1  christos 
   1018       1.1  christos /*
   1019       1.1  christos  * A connection has been established.
   1020       1.1  christos  */
   1021       1.1  christos static void
   1022       1.1  christos xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
   1023   1.1.1.4  christos 	isc_socket_connev_t *cev = (isc_socket_connev_t *)event;
   1024   1.1.1.4  christos 	dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)event->ev_arg;
   1025       1.1  christos 	isc_result_t result = cev->result;
   1026       1.1  christos 	char sourcetext[ISC_SOCKADDR_FORMATSIZE];
   1027       1.1  christos 	char signerbuf[DNS_NAME_FORMATSIZE];
   1028       1.1  christos 	const char *signer = "", *sep = "";
   1029       1.1  christos 	isc_sockaddr_t sockaddr;
   1030   1.1.1.4  christos 	dns_zonemgr_t *zmgr;
   1031       1.1  christos 	isc_time_t now;
   1032       1.1  christos 
   1033       1.1  christos 	REQUIRE(VALID_XFRIN(xfr));
   1034       1.1  christos 
   1035       1.1  christos 	UNUSED(task);
   1036       1.1  christos 
   1037       1.1  christos 	INSIST(event->ev_type == ISC_SOCKEVENT_CONNECT);
   1038       1.1  christos 	isc_event_free(&event);
   1039       1.1  christos 
   1040       1.1  christos 	xfr->connects--;
   1041       1.1  christos 	if (xfr->shuttingdown) {
   1042       1.1  christos 		maybe_free(xfr);
   1043       1.1  christos 		return;
   1044       1.1  christos 	}
   1045       1.1  christos 
   1046       1.1  christos 	zmgr = dns_zone_getmgr(xfr->zone);
   1047       1.1  christos 	if (zmgr != NULL) {
   1048       1.1  christos 		if (result != ISC_R_SUCCESS) {
   1049       1.1  christos 			TIME_NOW(&now);
   1050       1.1  christos 			dns_zonemgr_unreachableadd(zmgr, &xfr->masteraddr,
   1051       1.1  christos 						   &xfr->sourceaddr, &now);
   1052       1.1  christos 			goto failure;
   1053   1.1.1.4  christos 		} else {
   1054       1.1  christos 			dns_zonemgr_unreachabledel(zmgr, &xfr->masteraddr,
   1055       1.1  christos 						   &xfr->sourceaddr);
   1056   1.1.1.4  christos 		}
   1057       1.1  christos 	}
   1058       1.1  christos 
   1059       1.1  christos 	result = isc_socket_getsockname(xfr->socket, &sockaddr);
   1060       1.1  christos 	if (result == ISC_R_SUCCESS) {
   1061       1.1  christos 		isc_sockaddr_format(&sockaddr, sourcetext, sizeof(sourcetext));
   1062       1.1  christos 	} else {
   1063       1.1  christos 		strlcpy(sourcetext, "<UNKNOWN>", sizeof(sourcetext));
   1064       1.1  christos 	}
   1065       1.1  christos 
   1066       1.1  christos 	if (xfr->tsigkey != NULL && xfr->tsigkey->key != NULL) {
   1067   1.1.1.4  christos 		dns_name_format(dst_key_name(xfr->tsigkey->key), signerbuf,
   1068   1.1.1.4  christos 				sizeof(signerbuf));
   1069       1.1  christos 		sep = " TSIG ";
   1070       1.1  christos 		signer = signerbuf;
   1071       1.1  christos 	}
   1072       1.1  christos 
   1073   1.1.1.4  christos 	xfrin_log(xfr, ISC_LOG_INFO, "connected using %s%s%s", sourcetext, sep,
   1074   1.1.1.4  christos 		  signer);
   1075       1.1  christos 
   1076       1.1  christos 	dns_tcpmsg_init(xfr->mctx, xfr->socket, &xfr->tcpmsg);
   1077   1.1.1.2  christos 	xfr->tcpmsg_valid = true;
   1078       1.1  christos 
   1079       1.1  christos 	CHECK(xfrin_send_request(xfr));
   1080   1.1.1.4  christos failure:
   1081   1.1.1.4  christos 	if (result != ISC_R_SUCCESS) {
   1082       1.1  christos 		xfrin_fail(xfr, result, "failed to connect");
   1083   1.1.1.4  christos 	}
   1084       1.1  christos }
   1085       1.1  christos 
   1086       1.1  christos /*
   1087       1.1  christos  * Convert a tuple into a dns_name_t suitable for inserting
   1088       1.1  christos  * into the given dns_message_t.
   1089       1.1  christos  */
   1090       1.1  christos static isc_result_t
   1091   1.1.1.4  christos tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target) {
   1092       1.1  christos 	isc_result_t result;
   1093       1.1  christos 	dns_rdata_t *rdata = NULL;
   1094       1.1  christos 	dns_rdatalist_t *rdl = NULL;
   1095       1.1  christos 	dns_rdataset_t *rds = NULL;
   1096       1.1  christos 	dns_name_t *name = NULL;
   1097       1.1  christos 
   1098       1.1  christos 	REQUIRE(target != NULL && *target == NULL);
   1099       1.1  christos 
   1100       1.1  christos 	CHECK(dns_message_gettemprdata(msg, &rdata));
   1101       1.1  christos 	dns_rdata_init(rdata);
   1102       1.1  christos 	dns_rdata_clone(&tuple->rdata, rdata);
   1103       1.1  christos 
   1104       1.1  christos 	CHECK(dns_message_gettemprdatalist(msg, &rdl));
   1105       1.1  christos 	dns_rdatalist_init(rdl);
   1106       1.1  christos 	rdl->type = tuple->rdata.type;
   1107       1.1  christos 	rdl->rdclass = tuple->rdata.rdclass;
   1108       1.1  christos 	rdl->ttl = tuple->ttl;
   1109       1.1  christos 	ISC_LIST_APPEND(rdl->rdata, rdata, link);
   1110       1.1  christos 
   1111       1.1  christos 	CHECK(dns_message_gettemprdataset(msg, &rds));
   1112       1.1  christos 	CHECK(dns_rdatalist_tordataset(rdl, rds));
   1113       1.1  christos 
   1114       1.1  christos 	CHECK(dns_message_gettempname(msg, &name));
   1115       1.1  christos 	dns_name_clone(&tuple->name, name);
   1116       1.1  christos 	ISC_LIST_APPEND(name->list, rds, link);
   1117       1.1  christos 
   1118       1.1  christos 	*target = name;
   1119       1.1  christos 	return (ISC_R_SUCCESS);
   1120       1.1  christos 
   1121   1.1.1.4  christos failure:
   1122       1.1  christos 
   1123       1.1  christos 	if (rds != NULL) {
   1124       1.1  christos 		dns_rdataset_disassociate(rds);
   1125       1.1  christos 		dns_message_puttemprdataset(msg, &rds);
   1126       1.1  christos 	}
   1127       1.1  christos 	if (rdl != NULL) {
   1128       1.1  christos 		ISC_LIST_UNLINK(rdl->rdata, rdata, link);
   1129       1.1  christos 		dns_message_puttemprdatalist(msg, &rdl);
   1130       1.1  christos 	}
   1131   1.1.1.4  christos 	if (rdata != NULL) {
   1132       1.1  christos 		dns_message_puttemprdata(msg, &rdata);
   1133   1.1.1.4  christos 	}
   1134       1.1  christos 
   1135       1.1  christos 	return (result);
   1136       1.1  christos }
   1137       1.1  christos 
   1138       1.1  christos /*
   1139       1.1  christos  * Build an *XFR request and send its length prefix.
   1140       1.1  christos  */
   1141       1.1  christos static isc_result_t
   1142       1.1  christos xfrin_send_request(dns_xfrin_ctx_t *xfr) {
   1143       1.1  christos 	isc_result_t result;
   1144       1.1  christos 	isc_region_t region;
   1145       1.1  christos 	dns_rdataset_t *qrdataset = NULL;
   1146       1.1  christos 	dns_message_t *msg = NULL;
   1147       1.1  christos 	dns_difftuple_t *soatuple = NULL;
   1148       1.1  christos 	dns_name_t *qname = NULL;
   1149       1.1  christos 	dns_dbversion_t *ver = NULL;
   1150       1.1  christos 	dns_name_t *msgsoaname = NULL;
   1151       1.1  christos 
   1152       1.1  christos 	/* Create the request message */
   1153   1.1.1.6  christos 	dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg);
   1154       1.1  christos 	CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
   1155       1.1  christos 
   1156       1.1  christos 	/* Create a name for the question section. */
   1157       1.1  christos 	CHECK(dns_message_gettempname(msg, &qname));
   1158       1.1  christos 	dns_name_clone(&xfr->name, qname);
   1159       1.1  christos 
   1160       1.1  christos 	/* Formulate the question and attach it to the question name. */
   1161       1.1  christos 	CHECK(dns_message_gettemprdataset(msg, &qrdataset));
   1162       1.1  christos 	dns_rdataset_makequestion(qrdataset, xfr->rdclass, xfr->reqtype);
   1163       1.1  christos 	ISC_LIST_APPEND(qname->list, qrdataset, link);
   1164       1.1  christos 	qrdataset = NULL;
   1165       1.1  christos 
   1166       1.1  christos 	dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
   1167       1.1  christos 	qname = NULL;
   1168       1.1  christos 
   1169       1.1  christos 	if (xfr->reqtype == dns_rdatatype_ixfr) {
   1170       1.1  christos 		/* Get the SOA and add it to the authority section. */
   1171       1.1  christos 		/* XXX is using the current version the right thing? */
   1172       1.1  christos 		dns_db_currentversion(xfr->db, &ver);
   1173       1.1  christos 		CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx,
   1174       1.1  christos 					    DNS_DIFFOP_EXISTS, &soatuple));
   1175       1.1  christos 		xfr->ixfr.request_serial = dns_soa_getserial(&soatuple->rdata);
   1176       1.1  christos 		xfr->ixfr.current_serial = xfr->ixfr.request_serial;
   1177       1.1  christos 		xfrin_log(xfr, ISC_LOG_DEBUG(3),
   1178       1.1  christos 			  "requesting IXFR for serial %u",
   1179       1.1  christos 			  xfr->ixfr.request_serial);
   1180       1.1  christos 
   1181       1.1  christos 		CHECK(tuple2msgname(soatuple, msg, &msgsoaname));
   1182       1.1  christos 		dns_message_addname(msg, msgsoaname, DNS_SECTION_AUTHORITY);
   1183   1.1.1.4  christos 	} else if (xfr->reqtype == dns_rdatatype_soa) {
   1184       1.1  christos 		CHECK(dns_db_getsoaserial(xfr->db, NULL,
   1185       1.1  christos 					  &xfr->ixfr.request_serial));
   1186   1.1.1.4  christos 	}
   1187       1.1  christos 
   1188   1.1.1.2  christos 	xfr->checkid = true;
   1189   1.1.1.4  christos 	xfr->logit = true;
   1190       1.1  christos 	xfr->id++;
   1191       1.1  christos 	xfr->nmsg = 0;
   1192       1.1  christos 	xfr->nrecs = 0;
   1193       1.1  christos 	xfr->nbytes = 0;
   1194       1.1  christos 	isc_time_now(&xfr->start);
   1195       1.1  christos 	msg->id = xfr->id;
   1196   1.1.1.4  christos 	if (xfr->tsigctx != NULL) {
   1197       1.1  christos 		dst_context_destroy(&xfr->tsigctx);
   1198   1.1.1.4  christos 	}
   1199       1.1  christos 
   1200       1.1  christos 	CHECK(render(msg, xfr->mctx, &xfr->qbuffer));
   1201       1.1  christos 
   1202       1.1  christos 	/*
   1203       1.1  christos 	 * Free the last tsig, if there is one.
   1204       1.1  christos 	 */
   1205   1.1.1.4  christos 	if (xfr->lasttsig != NULL) {
   1206       1.1  christos 		isc_buffer_free(&xfr->lasttsig);
   1207   1.1.1.4  christos 	}
   1208       1.1  christos 
   1209       1.1  christos 	/*
   1210       1.1  christos 	 * Save the query TSIG and don't let message_destroy free it.
   1211       1.1  christos 	 */
   1212       1.1  christos 	CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
   1213       1.1  christos 
   1214       1.1  christos 	isc_buffer_usedregion(&xfr->qbuffer, &region);
   1215       1.1  christos 	INSIST(region.length <= 65535);
   1216       1.1  christos 
   1217       1.1  christos 	/*
   1218       1.1  christos 	 * Record message length and adjust region to include TCP
   1219       1.1  christos 	 * length field.
   1220       1.1  christos 	 */
   1221       1.1  christos 	xfr->qbuffer_data[0] = (region.length >> 8) & 0xff;
   1222       1.1  christos 	xfr->qbuffer_data[1] = region.length & 0xff;
   1223       1.1  christos 	region.base -= 2;
   1224       1.1  christos 	region.length += 2;
   1225   1.1.1.4  christos 	CHECK(isc_socket_send(xfr->socket, &region, xfr->task, xfrin_send_done,
   1226   1.1.1.4  christos 			      xfr));
   1227       1.1  christos 	xfr->sends++;
   1228       1.1  christos 
   1229   1.1.1.4  christos failure:
   1230   1.1.1.4  christos 	if (qname != NULL) {
   1231       1.1  christos 		dns_message_puttempname(msg, &qname);
   1232   1.1.1.4  christos 	}
   1233   1.1.1.4  christos 	if (qrdataset != NULL) {
   1234       1.1  christos 		dns_message_puttemprdataset(msg, &qrdataset);
   1235   1.1.1.4  christos 	}
   1236   1.1.1.4  christos 	if (msg != NULL) {
   1237   1.1.1.6  christos 		dns_message_detach(&msg);
   1238   1.1.1.4  christos 	}
   1239   1.1.1.4  christos 	if (soatuple != NULL) {
   1240       1.1  christos 		dns_difftuple_free(&soatuple);
   1241   1.1.1.4  christos 	}
   1242   1.1.1.4  christos 	if (ver != NULL) {
   1243   1.1.1.2  christos 		dns_db_closeversion(xfr->db, &ver, false);
   1244   1.1.1.4  christos 	}
   1245       1.1  christos 	return (result);
   1246       1.1  christos }
   1247       1.1  christos 
   1248       1.1  christos static void
   1249       1.1  christos xfrin_send_done(isc_task_t *task, isc_event_t *event) {
   1250   1.1.1.4  christos 	isc_socketevent_t *sev = (isc_socketevent_t *)event;
   1251   1.1.1.4  christos 	dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)event->ev_arg;
   1252       1.1  christos 	isc_result_t result;
   1253       1.1  christos 
   1254       1.1  christos 	REQUIRE(VALID_XFRIN(xfr));
   1255       1.1  christos 
   1256       1.1  christos 	UNUSED(task);
   1257       1.1  christos 
   1258       1.1  christos 	INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
   1259       1.1  christos 
   1260       1.1  christos 	xfr->sends--;
   1261       1.1  christos 	xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request data");
   1262       1.1  christos 	CHECK(sev->result);
   1263       1.1  christos 
   1264   1.1.1.4  christos 	CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task, xfrin_recv_done,
   1265   1.1.1.4  christos 				     xfr));
   1266       1.1  christos 	xfr->recvs++;
   1267   1.1.1.4  christos failure:
   1268       1.1  christos 	isc_event_free(&event);
   1269   1.1.1.4  christos 	if (result != ISC_R_SUCCESS) {
   1270       1.1  christos 		xfrin_fail(xfr, result, "failed sending request data");
   1271   1.1.1.4  christos 	}
   1272       1.1  christos }
   1273       1.1  christos 
   1274       1.1  christos static void
   1275       1.1  christos xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
   1276   1.1.1.4  christos 	dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)ev->ev_arg;
   1277       1.1  christos 	isc_result_t result;
   1278       1.1  christos 	dns_message_t *msg = NULL;
   1279       1.1  christos 	dns_name_t *name;
   1280       1.1  christos 	dns_tcpmsg_t *tcpmsg;
   1281       1.1  christos 	const dns_name_t *tsigowner = NULL;
   1282       1.1  christos 
   1283       1.1  christos 	REQUIRE(VALID_XFRIN(xfr));
   1284       1.1  christos 
   1285       1.1  christos 	UNUSED(task);
   1286       1.1  christos 
   1287       1.1  christos 	INSIST(ev->ev_type == DNS_EVENT_TCPMSG);
   1288       1.1  christos 	tcpmsg = ev->ev_sender;
   1289       1.1  christos 	isc_event_free(&ev);
   1290       1.1  christos 
   1291       1.1  christos 	xfr->recvs--;
   1292       1.1  christos 	if (xfr->shuttingdown) {
   1293       1.1  christos 		maybe_free(xfr);
   1294       1.1  christos 		return;
   1295       1.1  christos 	}
   1296       1.1  christos 
   1297       1.1  christos 	CHECK(tcpmsg->result);
   1298       1.1  christos 
   1299       1.1  christos 	xfrin_log(xfr, ISC_LOG_DEBUG(7), "received %u bytes",
   1300       1.1  christos 		  tcpmsg->buffer.used);
   1301       1.1  christos 
   1302       1.1  christos 	CHECK(isc_timer_touch(xfr->timer));
   1303       1.1  christos 
   1304   1.1.1.6  christos 	dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
   1305       1.1  christos 
   1306       1.1  christos 	CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
   1307       1.1  christos 	CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
   1308       1.1  christos 
   1309       1.1  christos 	msg->tsigctx = xfr->tsigctx;
   1310       1.1  christos 	xfr->tsigctx = NULL;
   1311       1.1  christos 
   1312       1.1  christos 	dns_message_setclass(msg, xfr->rdclass);
   1313       1.1  christos 
   1314   1.1.1.4  christos 	if (xfr->nmsg > 0) {
   1315       1.1  christos 		msg->tcp_continuation = 1;
   1316   1.1.1.4  christos 	}
   1317       1.1  christos 
   1318       1.1  christos 	result = dns_message_parse(msg, &tcpmsg->buffer,
   1319       1.1  christos 				   DNS_MESSAGEPARSE_PRESERVEORDER);
   1320       1.1  christos 
   1321   1.1.1.4  christos 	if (result == ISC_R_SUCCESS) {
   1322   1.1.1.2  christos 		dns_message_logpacket(msg, "received message from",
   1323   1.1.1.4  christos 				      &tcpmsg->address, DNS_LOGCATEGORY_XFER_IN,
   1324   1.1.1.4  christos 				      DNS_LOGMODULE_XFER_IN, ISC_LOG_DEBUG(10),
   1325   1.1.1.4  christos 				      xfr->mctx);
   1326   1.1.1.4  christos 	} else {
   1327       1.1  christos 		xfrin_log(xfr, ISC_LOG_DEBUG(10), "dns_message_parse: %s",
   1328       1.1  christos 			  dns_result_totext(result));
   1329   1.1.1.4  christos 	}
   1330       1.1  christos 
   1331       1.1  christos 	if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror ||
   1332   1.1.1.4  christos 	    msg->opcode != dns_opcode_query || msg->rdclass != xfr->rdclass ||
   1333   1.1.1.4  christos 	    (xfr->checkid && msg->id != xfr->id))
   1334   1.1.1.4  christos 	{
   1335       1.1  christos 		if (result == ISC_R_SUCCESS && msg->rcode != dns_rcode_noerror)
   1336   1.1.1.4  christos 		{
   1337       1.1  christos 			result = ISC_RESULTCLASS_DNSRCODE + msg->rcode; /*XXX*/
   1338   1.1.1.4  christos 		} else if (result == ISC_R_SUCCESS &&
   1339  1.1.1.10  christos 			   msg->opcode != dns_opcode_query)
   1340  1.1.1.10  christos 		{
   1341       1.1  christos 			result = DNS_R_UNEXPECTEDOPCODE;
   1342   1.1.1.4  christos 		} else if (result == ISC_R_SUCCESS &&
   1343  1.1.1.10  christos 			   msg->rdclass != xfr->rdclass)
   1344  1.1.1.10  christos 		{
   1345       1.1  christos 			result = DNS_R_BADCLASS;
   1346   1.1.1.4  christos 		} else if (result == ISC_R_SUCCESS || result == DNS_R_NOERROR) {
   1347       1.1  christos 			result = DNS_R_UNEXPECTEDID;
   1348   1.1.1.4  christos 		}
   1349       1.1  christos 		if (xfr->reqtype == dns_rdatatype_axfr ||
   1350  1.1.1.10  christos 		    xfr->reqtype == dns_rdatatype_soa)
   1351  1.1.1.10  christos 		{
   1352       1.1  christos 			goto failure;
   1353   1.1.1.4  christos 		}
   1354       1.1  christos 		xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
   1355   1.1.1.4  christos 			  isc_result_totext(result));
   1356   1.1.1.4  christos 	try_axfr:
   1357   1.1.1.6  christos 		dns_message_detach(&msg);
   1358       1.1  christos 		xfrin_reset(xfr);
   1359       1.1  christos 		xfr->reqtype = dns_rdatatype_soa;
   1360       1.1  christos 		xfr->state = XFRST_SOAQUERY;
   1361       1.1  christos 		(void)xfrin_start(xfr);
   1362       1.1  christos 		return;
   1363   1.1.1.4  christos 	} else if (!xfr->checkid && msg->id != xfr->id && xfr->logit) {
   1364   1.1.1.4  christos 		xfrin_log(xfr, ISC_LOG_WARNING,
   1365   1.1.1.4  christos 			  "detected message ID mismatch on incoming AXFR "
   1366   1.1.1.4  christos 			  "stream, transfer will fail in BIND 9.17.2 and "
   1367   1.1.1.4  christos 			  "later if AXFR source is not fixed");
   1368   1.1.1.4  christos 		xfr->logit = false;
   1369       1.1  christos 	}
   1370       1.1  christos 
   1371       1.1  christos 	/*
   1372       1.1  christos 	 * Does the server know about IXFR?  If it doesn't we will get
   1373       1.1  christos 	 * a message with a empty answer section or a potentially a CNAME /
   1374       1.1  christos 	 * DNAME, the later is handled by xfr_rr() which will return FORMERR
   1375       1.1  christos 	 * if the first RR in the answer section is not a SOA record.
   1376       1.1  christos 	 */
   1377       1.1  christos 	if (xfr->reqtype == dns_rdatatype_ixfr &&
   1378       1.1  christos 	    xfr->state == XFRST_INITIALSOA &&
   1379   1.1.1.4  christos 	    msg->counts[DNS_SECTION_ANSWER] == 0)
   1380   1.1.1.4  christos 	{
   1381       1.1  christos 		xfrin_log(xfr, ISC_LOG_DEBUG(3),
   1382       1.1  christos 			  "empty answer section, retrying with AXFR");
   1383       1.1  christos 		goto try_axfr;
   1384       1.1  christos 	}
   1385       1.1  christos 
   1386       1.1  christos 	if (xfr->reqtype == dns_rdatatype_soa &&
   1387  1.1.1.10  christos 	    (msg->flags & DNS_MESSAGEFLAG_AA) == 0)
   1388  1.1.1.10  christos 	{
   1389       1.1  christos 		FAIL(DNS_R_NOTAUTHORITATIVE);
   1390       1.1  christos 	}
   1391       1.1  christos 
   1392       1.1  christos 	result = dns_message_checksig(msg, dns_zone_getview(xfr->zone));
   1393       1.1  christos 	if (result != ISC_R_SUCCESS) {
   1394       1.1  christos 		xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
   1395   1.1.1.4  christos 			  isc_result_totext(result));
   1396       1.1  christos 		goto failure;
   1397       1.1  christos 	}
   1398       1.1  christos 
   1399       1.1  christos 	for (result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
   1400       1.1  christos 	     result == ISC_R_SUCCESS;
   1401       1.1  christos 	     result = dns_message_nextname(msg, DNS_SECTION_ANSWER))
   1402       1.1  christos 	{
   1403       1.1  christos 		dns_rdataset_t *rds;
   1404       1.1  christos 
   1405       1.1  christos 		name = NULL;
   1406       1.1  christos 		dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
   1407   1.1.1.4  christos 		for (rds = ISC_LIST_HEAD(name->list); rds != NULL;
   1408       1.1  christos 		     rds = ISC_LIST_NEXT(rds, link))
   1409       1.1  christos 		{
   1410       1.1  christos 			for (result = dns_rdataset_first(rds);
   1411       1.1  christos 			     result == ISC_R_SUCCESS;
   1412       1.1  christos 			     result = dns_rdataset_next(rds))
   1413       1.1  christos 			{
   1414       1.1  christos 				dns_rdata_t rdata = DNS_RDATA_INIT;
   1415       1.1  christos 				dns_rdataset_current(rds, &rdata);
   1416       1.1  christos 				CHECK(xfr_rr(xfr, name, rds->ttl, &rdata));
   1417       1.1  christos 			}
   1418       1.1  christos 		}
   1419       1.1  christos 	}
   1420   1.1.1.4  christos 	if (result != ISC_R_NOMORE) {
   1421       1.1  christos 		goto failure;
   1422   1.1.1.4  christos 	}
   1423       1.1  christos 
   1424       1.1  christos 	if (dns_message_gettsig(msg, &tsigowner) != NULL) {
   1425       1.1  christos 		/*
   1426       1.1  christos 		 * Reset the counter.
   1427       1.1  christos 		 */
   1428       1.1  christos 		xfr->sincetsig = 0;
   1429       1.1  christos 
   1430       1.1  christos 		/*
   1431       1.1  christos 		 * Free the last tsig, if there is one.
   1432       1.1  christos 		 */
   1433   1.1.1.4  christos 		if (xfr->lasttsig != NULL) {
   1434       1.1  christos 			isc_buffer_free(&xfr->lasttsig);
   1435   1.1.1.4  christos 		}
   1436       1.1  christos 
   1437       1.1  christos 		/*
   1438       1.1  christos 		 * Update the last tsig pointer.
   1439       1.1  christos 		 */
   1440   1.1.1.4  christos 		CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
   1441       1.1  christos 	} else if (dns_message_gettsigkey(msg) != NULL) {
   1442       1.1  christos 		xfr->sincetsig++;
   1443       1.1  christos 		if (xfr->sincetsig > 100 || xfr->nmsg == 0 ||
   1444       1.1  christos 		    xfr->state == XFRST_AXFR_END ||
   1445       1.1  christos 		    xfr->state == XFRST_IXFR_END)
   1446       1.1  christos 		{
   1447       1.1  christos 			result = DNS_R_EXPECTEDTSIG;
   1448       1.1  christos 			goto failure;
   1449       1.1  christos 		}
   1450       1.1  christos 	}
   1451       1.1  christos 
   1452       1.1  christos 	/*
   1453       1.1  christos 	 * Update the number of messages received.
   1454       1.1  christos 	 */
   1455       1.1  christos 	xfr->nmsg++;
   1456       1.1  christos 
   1457       1.1  christos 	/*
   1458       1.1  christos 	 * Update the number of bytes received.
   1459       1.1  christos 	 */
   1460       1.1  christos 	xfr->nbytes += tcpmsg->buffer.used;
   1461       1.1  christos 
   1462       1.1  christos 	/*
   1463       1.1  christos 	 * Take the context back.
   1464       1.1  christos 	 */
   1465       1.1  christos 	INSIST(xfr->tsigctx == NULL);
   1466       1.1  christos 	xfr->tsigctx = msg->tsigctx;
   1467       1.1  christos 	msg->tsigctx = NULL;
   1468       1.1  christos 
   1469   1.1.1.6  christos 	dns_message_detach(&msg);
   1470       1.1  christos 
   1471       1.1  christos 	switch (xfr->state) {
   1472       1.1  christos 	case XFRST_GOTSOA:
   1473       1.1  christos 		xfr->reqtype = dns_rdatatype_axfr;
   1474       1.1  christos 		xfr->state = XFRST_INITIALSOA;
   1475       1.1  christos 		CHECK(xfrin_send_request(xfr));
   1476       1.1  christos 		break;
   1477       1.1  christos 	case XFRST_AXFR_END:
   1478       1.1  christos 		CHECK(axfr_finalize(xfr));
   1479   1.1.1.9  christos 		FALLTHROUGH;
   1480       1.1  christos 	case XFRST_IXFR_END:
   1481       1.1  christos 		/*
   1482       1.1  christos 		 * Close the journal.
   1483       1.1  christos 		 */
   1484   1.1.1.4  christos 		if (xfr->ixfr.journal != NULL) {
   1485       1.1  christos 			dns_journal_destroy(&xfr->ixfr.journal);
   1486   1.1.1.4  christos 		}
   1487       1.1  christos 
   1488       1.1  christos 		/*
   1489       1.1  christos 		 * Inform the caller we succeeded.
   1490       1.1  christos 		 */
   1491       1.1  christos 		if (xfr->done != NULL) {
   1492       1.1  christos 			(xfr->done)(xfr->zone, ISC_R_SUCCESS);
   1493       1.1  christos 			xfr->done = NULL;
   1494       1.1  christos 		}
   1495       1.1  christos 		/*
   1496       1.1  christos 		 * We should have no outstanding events at this
   1497       1.1  christos 		 * point, thus maybe_free() should succeed.
   1498       1.1  christos 		 */
   1499   1.1.1.2  christos 		xfr->shuttingdown = true;
   1500       1.1  christos 		xfr->shutdown_result = ISC_R_SUCCESS;
   1501       1.1  christos 		maybe_free(xfr);
   1502       1.1  christos 		break;
   1503       1.1  christos 	default:
   1504       1.1  christos 		/*
   1505       1.1  christos 		 * Read the next message.
   1506       1.1  christos 		 */
   1507       1.1  christos 		CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
   1508       1.1  christos 					     xfrin_recv_done, xfr));
   1509       1.1  christos 		xfr->recvs++;
   1510       1.1  christos 	}
   1511       1.1  christos 	return;
   1512       1.1  christos 
   1513   1.1.1.4  christos failure:
   1514   1.1.1.4  christos 	if (msg != NULL) {
   1515   1.1.1.6  christos 		dns_message_detach(&msg);
   1516   1.1.1.4  christos 	}
   1517   1.1.1.4  christos 	if (result != ISC_R_SUCCESS) {
   1518       1.1  christos 		xfrin_fail(xfr, result, "failed while receiving responses");
   1519   1.1.1.4  christos 	}
   1520       1.1  christos }
   1521       1.1  christos 
   1522       1.1  christos static void
   1523       1.1  christos xfrin_timeout(isc_task_t *task, isc_event_t *event) {
   1524   1.1.1.4  christos 	dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *)event->ev_arg;
   1525       1.1  christos 
   1526       1.1  christos 	REQUIRE(VALID_XFRIN(xfr));
   1527       1.1  christos 
   1528       1.1  christos 	UNUSED(task);
   1529       1.1  christos 
   1530       1.1  christos 	isc_event_free(&event);
   1531       1.1  christos 	/*
   1532       1.1  christos 	 * This will log "giving up: timeout".
   1533       1.1  christos 	 */
   1534       1.1  christos 	xfrin_fail(xfr, ISC_R_TIMEDOUT, "giving up");
   1535       1.1  christos }
   1536       1.1  christos 
   1537       1.1  christos static void
   1538       1.1  christos maybe_free(dns_xfrin_ctx_t *xfr) {
   1539   1.1.1.2  christos 	uint64_t msecs;
   1540   1.1.1.2  christos 	uint64_t persec;
   1541       1.1  christos 	const char *result_str;
   1542       1.1  christos 
   1543       1.1  christos 	REQUIRE(VALID_XFRIN(xfr));
   1544       1.1  christos 
   1545   1.1.1.4  christos 	if (!xfr->shuttingdown || xfr->refcount != 0 || xfr->connects != 0 ||
   1546   1.1.1.4  christos 	    xfr->sends != 0 || xfr->recvs != 0)
   1547   1.1.1.4  christos 	{
   1548       1.1  christos 		return;
   1549   1.1.1.4  christos 	}
   1550       1.1  christos 
   1551   1.1.1.4  christos 	INSIST(!xfr->shuttingdown || xfr->shutdown_result != ISC_R_UNSET);
   1552       1.1  christos 
   1553       1.1  christos 	/* If we're called through dns_xfrin_detach() and are not
   1554       1.1  christos 	 * shutting down, we can't know what the transfer status is as
   1555       1.1  christos 	 * we are only called when the last reference is lost.
   1556       1.1  christos 	 */
   1557   1.1.1.4  christos 	result_str = (xfr->shuttingdown
   1558   1.1.1.4  christos 			      ? isc_result_totext(xfr->shutdown_result)
   1559   1.1.1.4  christos 			      : "unknown");
   1560       1.1  christos 	xfrin_log(xfr, ISC_LOG_INFO, "Transfer status: %s", result_str);
   1561       1.1  christos 
   1562       1.1  christos 	/*
   1563       1.1  christos 	 * Calculate the length of time the transfer took,
   1564       1.1  christos 	 * and print a log message with the bytes and rate.
   1565       1.1  christos 	 */
   1566       1.1  christos 	isc_time_now(&xfr->end);
   1567       1.1  christos 	msecs = isc_time_microdiff(&xfr->end, &xfr->start) / 1000;
   1568   1.1.1.4  christos 	if (msecs == 0) {
   1569       1.1  christos 		msecs = 1;
   1570   1.1.1.4  christos 	}
   1571       1.1  christos 	persec = (xfr->nbytes * 1000) / msecs;
   1572       1.1  christos 	xfrin_log(xfr, ISC_LOG_INFO,
   1573       1.1  christos 		  "Transfer completed: %d messages, %d records, "
   1574   1.1.1.2  christos 		  "%" PRIu64 " bytes, "
   1575   1.1.1.6  christos 		  "%u.%03u secs (%u bytes/sec) (serial %u)",
   1576       1.1  christos 		  xfr->nmsg, xfr->nrecs, xfr->nbytes,
   1577   1.1.1.4  christos 		  (unsigned int)(msecs / 1000), (unsigned int)(msecs % 1000),
   1578   1.1.1.6  christos 		  (unsigned int)persec, xfr->end_serial);
   1579       1.1  christos 
   1580   1.1.1.4  christos 	if (xfr->socket != NULL) {
   1581       1.1  christos 		isc_socket_detach(&xfr->socket);
   1582   1.1.1.4  christos 	}
   1583       1.1  christos 
   1584   1.1.1.4  christos 	if (xfr->timer != NULL) {
   1585       1.1  christos 		isc_timer_detach(&xfr->timer);
   1586   1.1.1.4  christos 	}
   1587       1.1  christos 
   1588   1.1.1.4  christos 	if (xfr->task != NULL) {
   1589       1.1  christos 		isc_task_detach(&xfr->task);
   1590   1.1.1.4  christos 	}
   1591       1.1  christos 
   1592   1.1.1.4  christos 	if (xfr->tsigkey != NULL) {
   1593       1.1  christos 		dns_tsigkey_detach(&xfr->tsigkey);
   1594   1.1.1.4  christos 	}
   1595       1.1  christos 
   1596   1.1.1.4  christos 	if (xfr->lasttsig != NULL) {
   1597       1.1  christos 		isc_buffer_free(&xfr->lasttsig);
   1598   1.1.1.4  christos 	}
   1599       1.1  christos 
   1600       1.1  christos 	dns_diff_clear(&xfr->diff);
   1601       1.1  christos 
   1602   1.1.1.4  christos 	if (xfr->ixfr.journal != NULL) {
   1603       1.1  christos 		dns_journal_destroy(&xfr->ixfr.journal);
   1604   1.1.1.4  christos 	}
   1605       1.1  christos 
   1606   1.1.1.4  christos 	if (xfr->axfr.add_private != NULL) {
   1607       1.1  christos 		(void)dns_db_endload(xfr->db, &xfr->axfr);
   1608   1.1.1.4  christos 	}
   1609       1.1  christos 
   1610   1.1.1.4  christos 	if (xfr->tcpmsg_valid) {
   1611       1.1  christos 		dns_tcpmsg_invalidate(&xfr->tcpmsg);
   1612   1.1.1.4  christos 	}
   1613       1.1  christos 
   1614   1.1.1.4  christos 	if (xfr->tsigctx != NULL) {
   1615       1.1  christos 		dst_context_destroy(&xfr->tsigctx);
   1616   1.1.1.4  christos 	}
   1617       1.1  christos 
   1618   1.1.1.4  christos 	if ((xfr->name.attributes & DNS_NAMEATTR_DYNAMIC) != 0) {
   1619       1.1  christos 		dns_name_free(&xfr->name, xfr->mctx);
   1620   1.1.1.4  christos 	}
   1621       1.1  christos 
   1622   1.1.1.4  christos 	if (xfr->ver != NULL) {
   1623   1.1.1.2  christos 		dns_db_closeversion(xfr->db, &xfr->ver, false);
   1624   1.1.1.4  christos 	}
   1625       1.1  christos 
   1626   1.1.1.4  christos 	if (xfr->db != NULL) {
   1627       1.1  christos 		dns_db_detach(&xfr->db);
   1628   1.1.1.4  christos 	}
   1629       1.1  christos 
   1630   1.1.1.3  christos 	if (xfr->zone != NULL) {
   1631   1.1.1.4  christos 		if (!xfr->zone_had_db && xfr->shuttingdown &&
   1632   1.1.1.3  christos 		    xfr->shutdown_result == ISC_R_SUCCESS &&
   1633   1.1.1.3  christos 		    dns_zone_gettype(xfr->zone) == dns_zone_mirror)
   1634   1.1.1.3  christos 		{
   1635   1.1.1.3  christos 			dns_zone_log(xfr->zone, ISC_LOG_INFO,
   1636   1.1.1.3  christos 				     "mirror zone is now in use");
   1637   1.1.1.3  christos 		}
   1638   1.1.1.3  christos 		xfrin_log(xfr, ISC_LOG_DEBUG(99), "freeing transfer context");
   1639   1.1.1.3  christos 		/*
   1640   1.1.1.3  christos 		 * xfr->zone must not be detached before xfrin_log() is called.
   1641   1.1.1.3  christos 		 */
   1642       1.1  christos 		dns_zone_idetach(&xfr->zone);
   1643   1.1.1.3  christos 	}
   1644       1.1  christos 
   1645   1.1.1.8  christos 	if (xfr->firstsoa_data != NULL) {
   1646   1.1.1.8  christos 		isc_mem_free(xfr->mctx, xfr->firstsoa_data);
   1647   1.1.1.8  christos 	}
   1648   1.1.1.8  christos 
   1649       1.1  christos 	isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
   1650       1.1  christos }
   1651       1.1  christos 
   1652       1.1  christos /*
   1653       1.1  christos  * Log incoming zone transfer messages in a format like
   1654       1.1  christos  * transfer of <zone> from <address>: <message>
   1655       1.1  christos  */
   1656       1.1  christos static void
   1657       1.1  christos xfrin_logv(int level, const char *zonetext, const isc_sockaddr_t *masteraddr,
   1658   1.1.1.4  christos 	   const char *fmt, va_list ap) {
   1659       1.1  christos 	char mastertext[ISC_SOCKADDR_FORMATSIZE];
   1660       1.1  christos 	char msgtext[2048];
   1661       1.1  christos 
   1662       1.1  christos 	isc_sockaddr_format(masteraddr, mastertext, sizeof(mastertext));
   1663       1.1  christos 	vsnprintf(msgtext, sizeof(msgtext), fmt, ap);
   1664       1.1  christos 
   1665   1.1.1.4  christos 	isc_log_write(dns_lctx, DNS_LOGCATEGORY_XFER_IN, DNS_LOGMODULE_XFER_IN,
   1666   1.1.1.4  christos 		      level, "transfer of '%s' from %s: %s", zonetext,
   1667   1.1.1.4  christos 		      mastertext, msgtext);
   1668       1.1  christos }
   1669       1.1  christos 
   1670       1.1  christos /*
   1671       1.1  christos  * Logging function for use when a xfrin_ctx_t has not yet been created.
   1672       1.1  christos  */
   1673       1.1  christos 
   1674       1.1  christos static void
   1675       1.1  christos xfrin_log1(int level, const char *zonetext, const isc_sockaddr_t *masteraddr,
   1676   1.1.1.4  christos 	   const char *fmt, ...) {
   1677       1.1  christos 	va_list ap;
   1678       1.1  christos 
   1679   1.1.1.5  christos 	if (!isc_log_wouldlog(dns_lctx, level)) {
   1680       1.1  christos 		return;
   1681   1.1.1.4  christos 	}
   1682       1.1  christos 
   1683       1.1  christos 	va_start(ap, fmt);
   1684       1.1  christos 	xfrin_logv(level, zonetext, masteraddr, fmt, ap);
   1685       1.1  christos 	va_end(ap);
   1686       1.1  christos }
   1687       1.1  christos 
   1688       1.1  christos /*
   1689       1.1  christos  * Logging function for use when there is a xfrin_ctx_t.
   1690       1.1  christos  */
   1691       1.1  christos 
   1692       1.1  christos static void
   1693   1.1.1.4  christos xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...) {
   1694       1.1  christos 	va_list ap;
   1695   1.1.1.4  christos 	char zonetext[DNS_NAME_MAXTEXT + 32];
   1696       1.1  christos 
   1697   1.1.1.5  christos 	if (!isc_log_wouldlog(dns_lctx, level)) {
   1698       1.1  christos 		return;
   1699   1.1.1.4  christos 	}
   1700       1.1  christos 
   1701       1.1  christos 	dns_zone_name(xfr->zone, zonetext, sizeof(zonetext));
   1702       1.1  christos 
   1703       1.1  christos 	va_start(ap, fmt);
   1704       1.1  christos 	xfrin_logv(level, zonetext, &xfr->masteraddr, fmt, ap);
   1705       1.1  christos 	va_end(ap);
   1706       1.1  christos }
   1707