ISC_LANG_BEGINDECLS
-isc_result_t
+void
dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
uint32_t ixfr_maxdiffs, const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
dns_transport_type_t soa_transport_type,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
- isc_mem_t *mctx, dns_xfrindone_t done, dns_xfrin_t **xfrp);
+ isc_mem_t *mctx, dns_xfrin_t **xfrp);
/*%<
- * Attempt to start an incoming zone transfer of 'zone'
- * from 'primaryaddr', creating a dns_xfrin_t object to
- * manage it. Attach '*xfrp' to the newly created object.
- *
- * Iff ISC_R_SUCCESS is returned, '*done' is called with
- * 'zone' and a result code as arguments when the transfer finishes.
+ * Create an incoming zone transfer object of 'zone' from
+ * 'primaryaddr'. Attach '*xfrp' to the newly created object.
*
* Requires:
*\li 'xfrp' != NULL and '*xfrp' == NULL.
*
- *\li 'done' != NULL.
- *
*\li 'primaryaddr' has a non-zero port number.
*
*\li 'zone' is a valid zone and is associated with a view.
* caller itself.
*/
+isc_result_t
+dns_xfrin_start(dns_xfrin_t *xfr, dns_xfrindone_t done);
+/*%<
+ * Attempt to start an incoming zone transfer of 'xfr->zone'
+ * using the previously created '*xfr' object.
+ *
+ * Iff ISC_R_SUCCESS is returned, '*done' is called with
+ * 'zone' and a result code as arguments when the transfer finishes.
+ *
+ * Requires:
+ *\li 'xfr' is a valid dns_xfrin_t object and is associated with a zone.
+ *
+ *\li 'done' != NULL.
+ *
+ */
+
isc_time_t
dns_xfrin_getstarttime(dns_xfrin_t *xfr);
/*%<
return (result);
}
-isc_result_t
+void
dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
uint32_t ixfr_maxdiffs, const isc_sockaddr_t *primaryaddr,
const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey,
dns_transport_type_t soa_transport_type,
dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache,
- isc_mem_t *mctx, dns_xfrindone_t done, dns_xfrin_t **xfrp) {
+ isc_mem_t *mctx, dns_xfrin_t **xfrp) {
dns_name_t *zonename = dns_zone_getorigin(zone);
dns_xfrin_t *xfr = NULL;
- isc_result_t result;
dns_db_t *db = NULL;
isc_loop_t *loop = NULL;
REQUIRE(xfrp != NULL && *xfrp == NULL);
- REQUIRE(done != NULL);
REQUIRE(isc_sockaddr_getport(primaryaddr) != 0);
- REQUIRE(zone != NULL);
- REQUIRE(dns_zone_getview(zone) != NULL);
loop = dns_zone_getloop(zone);
if (db != NULL) {
xfr->zone_had_db = true;
+ dns_db_detach(&db);
}
- xfr->done = done;
-
- /*
- * Set *xfrp now, before calling xfrin_start(), otherwise it's
- * possible the 'done' callback could be run before *xfrp
- * was attached.
- */
*xfrp = xfr;
+}
+
+isc_result_t
+dns_xfrin_start(dns_xfrin_t *xfr, dns_xfrindone_t done) {
+ isc_result_t result;
+
+ REQUIRE(xfr != NULL);
+ REQUIRE(xfr->zone != NULL);
+ REQUIRE(done != NULL);
+
+ xfr->done = done;
result = xfrin_start(xfr);
if (result != ISC_R_SUCCESS) {
xfr->done = NULL;
- xfrin_fail(xfr, result, "zone transfer setup failed");
- dns_xfrin_detach(xfrp);
- }
-
- if (db != NULL) {
- dns_db_detach(&db);
+ xfrin_fail(xfr, result, "zone transfer start failed");
}
return (result);
char *keydirectory;
dns_keyfileio_t *kfio;
dns_keystorelist_t *keystores;
+ dns_xfrin_t *xfr;
uint32_t maxrefresh;
uint32_t minrefresh;
isc_sockaddr_t xfrsource4;
isc_sockaddr_t xfrsource6;
isc_sockaddr_t sourceaddr;
- dns_xfrin_t *xfr; /* loop locked */
dns_tsigkey_t *tsigkey; /* key used for xfr */
dns_transport_t *transport; /* transport used for xfr */
/* Access Control Lists */
zone_settimer(zone, &now);
/*
- * If creating the transfer object failed, zone->xfr is NULL.
- * Otherwise, we are called as the done callback of a zone
- * transfer object that just entered its shutting-down
- * state. Since we are no longer responsible for shutting
+ * We are called as the done callback of a zone
+ * transfer object that just entered its shutting-down state or
+ * failed to start. Since we are no longer responsible for shutting
* it down, we can detach our reference.
*/
if (zone->xfr != NULL) {
const char *soa_before = "";
bool loaded;
isc_tlsctx_cache_t *zmgr_tlsctx_cache = NULL;
+ dns_xfrin_t *xfr = NULL;
if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {
zone_xfrdone(zone, NULL, ISC_R_CANCELED);
INSIST(isc_sockaddr_pf(&primaryaddr) == isc_sockaddr_pf(&sourceaddr));
- if (zone->xfr != NULL) {
- dns_xfrin_detach(&zone->xfr);
- }
-
zmgr_tlsctx_attach(zone->zmgr, &zmgr_tlsctx_cache);
- result = dns_xfrin_create(
- zone, xfrtype, ixfr_maxdiffs, &primaryaddr, &sourceaddr,
- zone->tsigkey, soa_transport_type, zone->transport,
- zmgr_tlsctx_cache, zone->mctx, zone_xfrdone, &zone->xfr);
+ dns_xfrin_create(zone, xfrtype, ixfr_maxdiffs, &primaryaddr,
+ &sourceaddr, zone->tsigkey, soa_transport_type,
+ zone->transport, zmgr_tlsctx_cache, zone->mctx, &xfr);
+ INSIST(xfr != NULL);
isc_tlsctx_cache_detach(&zmgr_tlsctx_cache);
+ LOCK_ZONE(zone);
+ if (zone->xfr != NULL) {
+ dns_xfrin_detach(&zone->xfr);
+ }
+ dns_xfrin_attach(xfr, &zone->xfr);
+ UNLOCK_ZONE(zone);
+
+ dns_xfrin_detach(&xfr);
+
/*
* Any failure in this function is handled like a failed
* zone transfer. This ensures that we get removed from
* zmgr->xfrin_in_progress.
*/
+ result = dns_xfrin_start(zone->xfr, zone_xfrdone);
if (result != ISC_R_SUCCESS) {
zone_xfrdone(zone, NULL, result);
return;