1 1.19 christos /* $NetBSD: xfrin.c,v 1.20 2026/01/29 18:37:50 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.11 christos * SPDX-License-Identifier: MPL-2.0 7 1.11 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.7 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.3 christos #include <inttypes.h> 19 1.3 christos #include <stdbool.h> 20 1.3 christos 21 1.16 christos #include <isc/async.h> 22 1.16 christos #include <isc/atomic.h> 23 1.1 christos #include <isc/mem.h> 24 1.1 christos #include <isc/random.h> 25 1.14 christos #include <isc/result.h> 26 1.16 christos #include <isc/string.h> 27 1.1 christos #include <isc/util.h> 28 1.16 christos #include <isc/work.h> 29 1.1 christos 30 1.1 christos #include <dns/callbacks.h> 31 1.1 christos #include <dns/catz.h> 32 1.1 christos #include <dns/db.h> 33 1.1 christos #include <dns/diff.h> 34 1.16 christos #include <dns/dispatch.h> 35 1.1 christos #include <dns/journal.h> 36 1.1 christos #include <dns/log.h> 37 1.1 christos #include <dns/message.h> 38 1.16 christos #include <dns/peer.h> 39 1.1 christos #include <dns/rdataclass.h> 40 1.1 christos #include <dns/rdatalist.h> 41 1.1 christos #include <dns/rdataset.h> 42 1.1 christos #include <dns/result.h> 43 1.1 christos #include <dns/soa.h> 44 1.16 christos #include <dns/trace.h> 45 1.14 christos #include <dns/transport.h> 46 1.1 christos #include <dns/tsig.h> 47 1.1 christos #include <dns/view.h> 48 1.1 christos #include <dns/xfrin.h> 49 1.1 christos #include <dns/zone.h> 50 1.1 christos 51 1.1 christos #include <dst/dst.h> 52 1.1 christos 53 1.16 christos #include "probes.h" 54 1.16 christos 55 1.1 christos /* 56 1.1 christos * Incoming AXFR and IXFR. 57 1.1 christos */ 58 1.1 christos 59 1.1 christos /*% 60 1.1 christos * The states of the *XFR state machine. We handle both IXFR and AXFR 61 1.1 christos * with a single integrated state machine because they cannot be distinguished 62 1.1 christos * immediately - an AXFR response to an IXFR request can only be detected 63 1.1 christos * when the first two (2) response RRs have already been received. 64 1.1 christos */ 65 1.1 christos typedef enum { 66 1.1 christos XFRST_SOAQUERY, 67 1.1 christos XFRST_GOTSOA, 68 1.16 christos XFRST_ZONEXFRREQUEST, 69 1.1 christos XFRST_FIRSTDATA, 70 1.1 christos XFRST_IXFR_DELSOA, 71 1.1 christos XFRST_IXFR_DEL, 72 1.1 christos XFRST_IXFR_ADDSOA, 73 1.1 christos XFRST_IXFR_ADD, 74 1.1 christos XFRST_IXFR_END, 75 1.1 christos XFRST_AXFR, 76 1.1 christos XFRST_AXFR_END 77 1.1 christos } xfrin_state_t; 78 1.1 christos 79 1.17 christos #ifdef _LP64 80 1.17 christos #define ISC_XFRIN_LOAD(a, t) atomic_load_relaxed(a) 81 1.17 christos #define ISC_XFRIN_STORE(a, b) atomic_store_relaxed(a, b) 82 1.17 christos #define ISC_XFRIN_ADD(a, b) atomic_fetch_add_relaxed(a, b) 83 1.17 christos #else 84 1.17 christos static isc_mutex_t xfrin_lock = PTHREAD_MUTEX_INITIALIZER; 85 1.17 christos #define ISC_XFRIN_LOAD(a, t) \ 86 1.17 christos ({ \ 87 1.17 christos isc_mutex_lock(&xfrin_lock); \ 88 1.17 christos t x = *(a); \ 89 1.17 christos isc_mutex_unlock(&xfrin_lock); \ 90 1.17 christos x; \ 91 1.17 christos }) 92 1.17 christos #define ISC_XFRIN_STORE(a, b) \ 93 1.17 christos ({ \ 94 1.17 christos isc_mutex_lock(&xfrin_lock); \ 95 1.17 christos *(a) = (b); \ 96 1.17 christos isc_mutex_unlock(&xfrin_lock); \ 97 1.17 christos }) 98 1.17 christos #define ISC_XFRIN_ADD(a, b) \ 99 1.17 christos ({ \ 100 1.17 christos isc_mutex_lock(&xfrin_lock); \ 101 1.17 christos *(a) += (b); \ 102 1.17 christos isc_mutex_unlock(&xfrin_lock); \ 103 1.17 christos }) 104 1.17 christos #endif 105 1.17 christos 106 1.17 christos 107 1.1 christos /*% 108 1.1 christos * Incoming zone transfer context. 109 1.1 christos */ 110 1.1 christos 111 1.16 christos struct dns_xfrin { 112 1.5 christos unsigned int magic; 113 1.5 christos isc_mem_t *mctx; 114 1.5 christos dns_zone_t *zone; 115 1.16 christos dns_view_t *view; 116 1.5 christos 117 1.14 christos isc_refcount_t references; 118 1.14 christos 119 1.14 christos atomic_bool shuttingdown; 120 1.5 christos 121 1.5 christos isc_result_t shutdown_result; 122 1.1 christos 123 1.5 christos dns_name_t name; /*%< Name of zone to transfer */ 124 1.5 christos dns_rdataclass_t rdclass; 125 1.1 christos 126 1.5 christos dns_messageid_t id; 127 1.1 christos 128 1.1 christos /*% 129 1.1 christos * Requested transfer type (dns_rdatatype_axfr or 130 1.1 christos * dns_rdatatype_ixfr). The actual transfer type 131 1.1 christos * may differ due to IXFR->AXFR fallback. 132 1.1 christos */ 133 1.5 christos dns_rdatatype_t reqtype; 134 1.1 christos 135 1.14 christos isc_sockaddr_t primaryaddr; 136 1.5 christos isc_sockaddr_t sourceaddr; 137 1.14 christos 138 1.16 christos dns_dispatch_t *disp; 139 1.16 christos dns_dispentry_t *dispentry; 140 1.1 christos 141 1.1 christos /*% Buffer for IXFR/AXFR request message */ 142 1.5 christos isc_buffer_t qbuffer; 143 1.5 christos unsigned char qbuffer_data[512]; 144 1.1 christos 145 1.4 christos /*% 146 1.4 christos * Whether the zone originally had a database attached at the time this 147 1.14 christos * transfer context was created. Used by xfrin_destroy() when making 148 1.4 christos * logging decisions. 149 1.4 christos */ 150 1.5 christos bool zone_had_db; 151 1.4 christos 152 1.5 christos dns_db_t *db; 153 1.5 christos dns_dbversion_t *ver; 154 1.5 christos dns_diff_t diff; /*%< Pending database changes */ 155 1.5 christos 156 1.16 christos /* Diff queue */ 157 1.16 christos bool diff_running; 158 1.16 christos struct __cds_wfcq_head diff_head; 159 1.16 christos struct cds_wfcq_tail diff_tail; 160 1.16 christos 161 1.16 christos _Atomic xfrin_state_t state; 162 1.16 christos uint32_t expireopt; 163 1.16 christos bool edns, expireoptset; 164 1.16 christos atomic_bool is_ixfr; 165 1.5 christos 166 1.16 christos /* 167 1.16 christos * Following variable were made atomic only for loading the values for 168 1.16 christos * the statistics channel, thus all accesses can be **relaxed** because 169 1.16 christos * all store and load operations that affect XFR are done on the same 170 1.16 christos * thread and only the statistics channel thread could perform a load 171 1.16 christos * operation from a different thread and it's ok to not be precise in 172 1.16 christos * the statistics. 173 1.16 christos */ 174 1.16 christos atomic_uint nmsg; /*%< Number of messages recvd */ 175 1.16 christos atomic_uint nrecs; /*%< Number of records recvd */ 176 1.17 christos #ifdef _LP64 177 1.16 christos atomic_uint_fast64_t nbytes; /*%< Number of bytes received */ 178 1.16 christos _Atomic(isc_time_t) start; /*%< Start time of the transfer */ 179 1.18 christos atomic_uint_fast64_t rate_bytes_per_second; 180 1.17 christos #else 181 1.17 christos atomic_uint_fast32_t nbytes; /*%< Number of bytes received */ 182 1.17 christos isc_time_t start; /*%< Start time of the transfer */ 183 1.18 christos atomic_uint_fast32_t rate_bytes_per_second; 184 1.17 christos #endif 185 1.16 christos _Atomic(dns_transport_type_t) soa_transport_type; 186 1.16 christos atomic_uint_fast32_t end_serial; 187 1.5 christos 188 1.5 christos unsigned int maxrecords; /*%< The maximum number of 189 1.5 christos * records set for the zone */ 190 1.18 christos uint64_t nbytes_saved; /*%< For enforcing the minimum transfer rate */ 191 1.5 christos 192 1.5 christos dns_tsigkey_t *tsigkey; /*%< Key used to create TSIG */ 193 1.5 christos isc_buffer_t *lasttsig; /*%< The last TSIG */ 194 1.5 christos dst_context_t *tsigctx; /*%< TSIG verification context */ 195 1.5 christos unsigned int sincetsig; /*%< recvd since the last TSIG */ 196 1.14 christos 197 1.14 christos dns_transport_t *transport; 198 1.14 christos 199 1.5 christos dns_xfrindone_t done; 200 1.1 christos 201 1.1 christos /*% 202 1.1 christos * AXFR- and IXFR-specific data. Only one is used at a time 203 1.1 christos * according to the is_ixfr flag, so this could be a union, 204 1.1 christos * but keeping them separate makes it a bit simpler to clean 205 1.1 christos * things up when destroying the context. 206 1.1 christos */ 207 1.5 christos dns_rdatacallbacks_t axfr; 208 1.1 christos 209 1.1 christos struct { 210 1.5 christos uint32_t request_serial; 211 1.5 christos uint32_t current_serial; 212 1.5 christos dns_journal_t *journal; 213 1.1 christos } ixfr; 214 1.10 christos 215 1.10 christos dns_rdata_t firstsoa; 216 1.10 christos unsigned char *firstsoa_data; 217 1.14 christos 218 1.14 christos isc_tlsctx_cache_t *tlsctx_cache; 219 1.14 christos 220 1.16 christos isc_loop_t *loop; 221 1.16 christos 222 1.18 christos isc_timer_t *min_rate_timer; 223 1.14 christos isc_timer_t *max_time_timer; 224 1.14 christos isc_timer_t *max_idle_timer; 225 1.16 christos 226 1.16 christos char info[DNS_NAME_MAXTEXT + 32]; 227 1.1 christos }; 228 1.1 christos 229 1.5 christos #define XFRIN_MAGIC ISC_MAGIC('X', 'f', 'r', 'I') 230 1.5 christos #define VALID_XFRIN(x) ISC_MAGIC_VALID(x, XFRIN_MAGIC) 231 1.1 christos 232 1.16 christos #define XFRIN_WORK_MAGIC ISC_MAGIC('X', 'f', 'r', 'W') 233 1.16 christos #define VALID_XFRIN_WORK(x) ISC_MAGIC_VALID(x, XFRIN_WORK_MAGIC) 234 1.16 christos 235 1.16 christos typedef struct xfrin_work { 236 1.16 christos unsigned int magic; 237 1.16 christos isc_result_t result; 238 1.16 christos dns_xfrin_t *xfr; 239 1.16 christos } xfrin_work_t; 240 1.16 christos 241 1.1 christos /**************************************************************************/ 242 1.1 christos /* 243 1.1 christos * Forward declarations. 244 1.1 christos */ 245 1.1 christos 246 1.14 christos static void 247 1.16 christos xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_loop_t *loop, 248 1.5 christos dns_name_t *zonename, dns_rdataclass_t rdclass, 249 1.14 christos dns_rdatatype_t reqtype, const isc_sockaddr_t *primaryaddr, 250 1.14 christos const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey, 251 1.16 christos dns_transport_type_t soa_transport_type, 252 1.14 christos dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, 253 1.16 christos dns_xfrin_t **xfrp); 254 1.1 christos 255 1.5 christos static isc_result_t 256 1.16 christos axfr_init(dns_xfrin_t *xfr); 257 1.5 christos static isc_result_t 258 1.16 christos axfr_putdata(dns_xfrin_t *xfr, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl, 259 1.16 christos dns_rdata_t *rdata); 260 1.16 christos static void 261 1.16 christos axfr_commit(dns_xfrin_t *xfr); 262 1.5 christos static isc_result_t 263 1.16 christos axfr_finalize(dns_xfrin_t *xfr); 264 1.5 christos 265 1.5 christos static isc_result_t 266 1.16 christos ixfr_init(dns_xfrin_t *xfr); 267 1.5 christos static isc_result_t 268 1.16 christos ixfr_putdata(dns_xfrin_t *xfr, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl, 269 1.16 christos dns_rdata_t *rdata); 270 1.5 christos static isc_result_t 271 1.16 christos ixfr_commit(dns_xfrin_t *xfr); 272 1.5 christos 273 1.5 christos static isc_result_t 274 1.16 christos xfr_rr(dns_xfrin_t *xfr, dns_name_t *name, uint32_t ttl, dns_rdata_t *rdata); 275 1.5 christos 276 1.5 christos static isc_result_t 277 1.16 christos xfrin_start(dns_xfrin_t *xfr); 278 1.5 christos 279 1.5 christos static void 280 1.16 christos xfrin_connect_done(isc_result_t result, isc_region_t *region, void *arg); 281 1.5 christos static isc_result_t 282 1.16 christos xfrin_send_request(dns_xfrin_t *xfr); 283 1.5 christos static void 284 1.16 christos xfrin_send_done(isc_result_t eresult, isc_region_t *region, void *arg); 285 1.16 christos static void 286 1.16 christos xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg); 287 1.16 christos 288 1.5 christos static void 289 1.16 christos xfrin_end(dns_xfrin_t *xfr, isc_result_t result); 290 1.14 christos 291 1.5 christos static void 292 1.16 christos xfrin_destroy(dns_xfrin_t *xfr); 293 1.5 christos 294 1.5 christos static void 295 1.16 christos xfrin_timedout(void *); 296 1.14 christos static void 297 1.16 christos xfrin_idledout(void *); 298 1.1 christos static void 299 1.18 christos xfrin_minratecheck(void *); 300 1.18 christos static void 301 1.16 christos xfrin_fail(dns_xfrin_t *xfr, isc_result_t result, const char *msg); 302 1.1 christos static isc_result_t 303 1.1 christos render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf); 304 1.1 christos 305 1.1 christos static void 306 1.16 christos xfrin_log(dns_xfrin_t *xfr, int level, const char *fmt, ...) 307 1.5 christos ISC_FORMAT_PRINTF(3, 4); 308 1.1 christos 309 1.1 christos /**************************************************************************/ 310 1.1 christos /* 311 1.1 christos * AXFR handling 312 1.1 christos */ 313 1.1 christos 314 1.1 christos static isc_result_t 315 1.16 christos axfr_init(dns_xfrin_t *xfr) { 316 1.1 christos isc_result_t result; 317 1.1 christos 318 1.16 christos atomic_store(&xfr->is_ixfr, false); 319 1.1 christos 320 1.5 christos if (xfr->db != NULL) { 321 1.1 christos dns_db_detach(&xfr->db); 322 1.5 christos } 323 1.1 christos 324 1.15 christos CHECK(dns_zone_makedb(xfr->zone, &xfr->db)); 325 1.15 christos 326 1.15 christos dns_zone_rpz_enable_db(xfr->zone, xfr->db); 327 1.15 christos dns_zone_catz_enable_db(xfr->zone, xfr->db); 328 1.15 christos 329 1.1 christos dns_rdatacallbacks_init(&xfr->axfr); 330 1.1 christos CHECK(dns_db_beginload(xfr->db, &xfr->axfr)); 331 1.1 christos result = ISC_R_SUCCESS; 332 1.20 christos cleanup: 333 1.16 christos return result; 334 1.1 christos } 335 1.1 christos 336 1.16 christos static void 337 1.16 christos axfr_apply(void *arg); 338 1.16 christos 339 1.1 christos static isc_result_t 340 1.16 christos axfr_putdata(dns_xfrin_t *xfr, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl, 341 1.16 christos dns_rdata_t *rdata) { 342 1.1 christos isc_result_t result; 343 1.1 christos 344 1.1 christos dns_difftuple_t *tuple = NULL; 345 1.1 christos 346 1.5 christos if (rdata->rdclass != xfr->rdclass) { 347 1.16 christos return DNS_R_BADCLASS; 348 1.5 christos } 349 1.1 christos 350 1.1 christos CHECK(dns_zone_checknames(xfr->zone, name, rdata)); 351 1.16 christos 352 1.16 christos if (dns_diff_size(&xfr->diff) > 128 && 353 1.16 christos dns_diff_is_boundary(&xfr->diff, name)) 354 1.16 christos { 355 1.16 christos xfrin_work_t work = (xfrin_work_t){ 356 1.16 christos .magic = XFRIN_WORK_MAGIC, 357 1.16 christos .result = ISC_R_UNSET, 358 1.16 christos .xfr = xfr, 359 1.16 christos }; 360 1.16 christos axfr_apply((void *)&work); 361 1.16 christos CHECK(work.result); 362 1.16 christos } 363 1.16 christos 364 1.5 christos CHECK(dns_difftuple_create(xfr->diff.mctx, op, name, ttl, rdata, 365 1.5 christos &tuple)); 366 1.1 christos dns_diff_append(&xfr->diff, &tuple); 367 1.16 christos 368 1.1 christos result = ISC_R_SUCCESS; 369 1.20 christos cleanup: 370 1.16 christos return result; 371 1.1 christos } 372 1.1 christos 373 1.1 christos /* 374 1.1 christos * Store a set of AXFR RRs in the database. 375 1.1 christos */ 376 1.16 christos static void 377 1.16 christos axfr_apply(void *arg) { 378 1.16 christos xfrin_work_t *work = arg; 379 1.16 christos REQUIRE(VALID_XFRIN_WORK(work)); 380 1.16 christos 381 1.16 christos dns_xfrin_t *xfr = work->xfr; 382 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 383 1.16 christos 384 1.16 christos isc_result_t result = ISC_R_SUCCESS; 385 1.3 christos uint64_t records; 386 1.1 christos 387 1.16 christos if (atomic_load(&xfr->shuttingdown)) { 388 1.20 christos CHECK(ISC_R_SHUTTINGDOWN); 389 1.16 christos } 390 1.16 christos 391 1.16 christos CHECK(dns_diff_load(&xfr->diff, &xfr->axfr)); 392 1.1 christos if (xfr->maxrecords != 0U) { 393 1.1 christos result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL); 394 1.1 christos if (result == ISC_R_SUCCESS && records > xfr->maxrecords) { 395 1.20 christos CHECK(DNS_R_TOOMANYRECORDS); 396 1.1 christos } 397 1.1 christos } 398 1.16 christos 399 1.20 christos cleanup: 400 1.16 christos dns_diff_clear(&xfr->diff); 401 1.16 christos work->result = result; 402 1.1 christos } 403 1.1 christos 404 1.16 christos static void 405 1.16 christos axfr_apply_done(void *arg) { 406 1.16 christos xfrin_work_t *work = arg; 407 1.16 christos REQUIRE(VALID_XFRIN_WORK(work)); 408 1.16 christos 409 1.16 christos dns_xfrin_t *xfr = work->xfr; 410 1.16 christos isc_result_t result = work->result; 411 1.16 christos 412 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 413 1.16 christos 414 1.16 christos if (atomic_load(&xfr->shuttingdown)) { 415 1.16 christos result = ISC_R_SHUTTINGDOWN; 416 1.16 christos } 417 1.1 christos 418 1.16 christos if (result == ISC_R_SUCCESS) { 419 1.16 christos CHECK(dns_db_endload(xfr->db, &xfr->axfr)); 420 1.16 christos CHECK(dns_zone_verifydb(xfr->zone, xfr->db, NULL)); 421 1.16 christos CHECK(axfr_finalize(xfr)); 422 1.16 christos } else { 423 1.16 christos (void)dns_db_endload(xfr->db, &xfr->axfr); 424 1.16 christos } 425 1.1 christos 426 1.20 christos cleanup: 427 1.16 christos xfr->diff_running = false; 428 1.16 christos 429 1.16 christos isc_mem_put(xfr->mctx, work, sizeof(*work)); 430 1.16 christos 431 1.16 christos if (result == ISC_R_SUCCESS) { 432 1.16 christos if (atomic_load(&xfr->state) == XFRST_AXFR_END) { 433 1.16 christos xfrin_end(xfr, result); 434 1.16 christos } 435 1.16 christos } else { 436 1.16 christos xfrin_fail(xfr, result, "failed while processing responses"); 437 1.16 christos } 438 1.16 christos 439 1.16 christos dns_xfrin_detach(&xfr); 440 1.16 christos } 441 1.16 christos 442 1.16 christos static void 443 1.16 christos axfr_commit(dns_xfrin_t *xfr) { 444 1.16 christos REQUIRE(!xfr->diff_running); 445 1.16 christos 446 1.16 christos xfrin_work_t *work = isc_mem_get(xfr->mctx, sizeof(*work)); 447 1.16 christos *work = (xfrin_work_t){ 448 1.16 christos .magic = XFRIN_WORK_MAGIC, 449 1.16 christos .result = ISC_R_UNSET, 450 1.16 christos .xfr = dns_xfrin_ref(xfr), 451 1.16 christos }; 452 1.16 christos xfr->diff_running = true; 453 1.16 christos isc_work_enqueue(xfr->loop, axfr_apply, axfr_apply_done, work); 454 1.1 christos } 455 1.1 christos 456 1.1 christos static isc_result_t 457 1.16 christos axfr_finalize(dns_xfrin_t *xfr) { 458 1.1 christos isc_result_t result; 459 1.1 christos 460 1.16 christos LIBDNS_XFRIN_AXFR_FINALIZE_BEGIN(xfr, xfr->info); 461 1.16 christos result = dns_zone_replacedb(xfr->zone, xfr->db, true); 462 1.16 christos LIBDNS_XFRIN_AXFR_FINALIZE_END(xfr, xfr->info, result); 463 1.1 christos 464 1.16 christos return result; 465 1.1 christos } 466 1.1 christos 467 1.1 christos /**************************************************************************/ 468 1.1 christos /* 469 1.1 christos * IXFR handling 470 1.1 christos */ 471 1.1 christos 472 1.16 christos typedef struct ixfr_apply_data { 473 1.16 christos dns_diff_t diff; /*%< Pending database changes */ 474 1.16 christos struct cds_wfcq_node wfcq_node; 475 1.16 christos } ixfr_apply_data_t; 476 1.16 christos 477 1.1 christos static isc_result_t 478 1.16 christos ixfr_init(dns_xfrin_t *xfr) { 479 1.1 christos isc_result_t result; 480 1.14 christos char *journalfile = NULL; 481 1.1 christos 482 1.1 christos if (xfr->reqtype != dns_rdatatype_ixfr) { 483 1.14 christos xfrin_log(xfr, ISC_LOG_NOTICE, 484 1.1 christos "got incremental response to AXFR request"); 485 1.16 christos return DNS_R_FORMERR; 486 1.1 christos } 487 1.1 christos 488 1.16 christos atomic_store(&xfr->is_ixfr, true); 489 1.1 christos INSIST(xfr->db != NULL); 490 1.1 christos 491 1.1 christos journalfile = dns_zone_getjournal(xfr->zone); 492 1.5 christos if (journalfile != NULL) { 493 1.1 christos CHECK(dns_journal_open(xfr->mctx, journalfile, 494 1.1 christos DNS_JOURNAL_CREATE, &xfr->ixfr.journal)); 495 1.5 christos } 496 1.1 christos 497 1.1 christos result = ISC_R_SUCCESS; 498 1.20 christos cleanup: 499 1.16 christos return result; 500 1.1 christos } 501 1.1 christos 502 1.1 christos static isc_result_t 503 1.16 christos ixfr_putdata(dns_xfrin_t *xfr, dns_diffop_t op, dns_name_t *name, dns_ttl_t ttl, 504 1.16 christos dns_rdata_t *rdata) { 505 1.1 christos isc_result_t result; 506 1.1 christos dns_difftuple_t *tuple = NULL; 507 1.1 christos 508 1.5 christos if (rdata->rdclass != xfr->rdclass) { 509 1.16 christos return DNS_R_BADCLASS; 510 1.5 christos } 511 1.1 christos 512 1.5 christos if (op == DNS_DIFFOP_ADD) { 513 1.1 christos CHECK(dns_zone_checknames(xfr->zone, name, rdata)); 514 1.5 christos } 515 1.5 christos CHECK(dns_difftuple_create(xfr->diff.mctx, op, name, ttl, rdata, 516 1.5 christos &tuple)); 517 1.1 christos dns_diff_append(&xfr->diff, &tuple); 518 1.16 christos result = ISC_R_SUCCESS; 519 1.20 christos cleanup: 520 1.16 christos return result; 521 1.16 christos } 522 1.16 christos 523 1.16 christos static isc_result_t 524 1.16 christos ixfr_begin_transaction(dns_xfrin_t *xfr) { 525 1.16 christos isc_result_t result = ISC_R_SUCCESS; 526 1.16 christos 527 1.16 christos if (xfr->ixfr.journal != NULL) { 528 1.16 christos CHECK(dns_journal_begin_transaction(xfr->ixfr.journal)); 529 1.16 christos } 530 1.20 christos cleanup: 531 1.16 christos return result; 532 1.16 christos } 533 1.16 christos 534 1.16 christos static isc_result_t 535 1.16 christos ixfr_end_transaction(dns_xfrin_t *xfr) { 536 1.16 christos isc_result_t result = ISC_R_SUCCESS; 537 1.16 christos 538 1.16 christos CHECK(dns_zone_verifydb(xfr->zone, xfr->db, xfr->ver)); 539 1.16 christos /* XXX enter ready-to-commit state here */ 540 1.16 christos if (xfr->ixfr.journal != NULL) { 541 1.16 christos CHECK(dns_journal_commit(xfr->ixfr.journal)); 542 1.5 christos } 543 1.20 christos cleanup: 544 1.16 christos return result; 545 1.1 christos } 546 1.1 christos 547 1.1 christos static isc_result_t 548 1.16 christos ixfr_apply_one(dns_xfrin_t *xfr, ixfr_apply_data_t *data) { 549 1.16 christos isc_result_t result = ISC_R_SUCCESS; 550 1.3 christos uint64_t records; 551 1.1 christos 552 1.16 christos CHECK(ixfr_begin_transaction(xfr)); 553 1.16 christos 554 1.16 christos CHECK(dns_diff_apply(&data->diff, xfr->db, xfr->ver)); 555 1.1 christos if (xfr->maxrecords != 0U) { 556 1.1 christos result = dns_db_getsize(xfr->db, xfr->ver, &records, NULL); 557 1.1 christos if (result == ISC_R_SUCCESS && records > xfr->maxrecords) { 558 1.20 christos CHECK(DNS_R_TOOMANYRECORDS); 559 1.1 christos } 560 1.1 christos } 561 1.1 christos if (xfr->ixfr.journal != NULL) { 562 1.16 christos CHECK(dns_journal_writediff(xfr->ixfr.journal, &data->diff)); 563 1.1 christos } 564 1.16 christos 565 1.16 christos result = ixfr_end_transaction(xfr); 566 1.16 christos 567 1.16 christos return result; 568 1.20 christos cleanup: 569 1.16 christos /* We need to end the transaction, but keep the previous error */ 570 1.16 christos (void)ixfr_end_transaction(xfr); 571 1.16 christos 572 1.16 christos return result; 573 1.1 christos } 574 1.1 christos 575 1.16 christos static void 576 1.16 christos ixfr_apply(void *arg) { 577 1.16 christos xfrin_work_t *work = arg; 578 1.16 christos dns_xfrin_t *xfr = work->xfr; 579 1.16 christos isc_result_t result = ISC_R_SUCCESS; 580 1.16 christos 581 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 582 1.16 christos REQUIRE(VALID_XFRIN_WORK(work)); 583 1.16 christos 584 1.16 christos struct __cds_wfcq_head diff_head; 585 1.16 christos struct cds_wfcq_tail diff_tail; 586 1.16 christos 587 1.16 christos /* Initialize local wfcqueue */ 588 1.16 christos __cds_wfcq_init(&diff_head, &diff_tail); 589 1.16 christos 590 1.16 christos enum cds_wfcq_ret ret = __cds_wfcq_splice_blocking( 591 1.16 christos &diff_head, &diff_tail, &xfr->diff_head, &xfr->diff_tail); 592 1.16 christos INSIST(ret == CDS_WFCQ_RET_DEST_EMPTY); 593 1.16 christos 594 1.16 christos struct cds_wfcq_node *node, *next; 595 1.16 christos __cds_wfcq_for_each_blocking_safe(&diff_head, &diff_tail, node, next) { 596 1.16 christos ixfr_apply_data_t *data = 597 1.16 christos caa_container_of(node, ixfr_apply_data_t, wfcq_node); 598 1.16 christos 599 1.16 christos if (atomic_load(&xfr->shuttingdown)) { 600 1.16 christos result = ISC_R_SHUTTINGDOWN; 601 1.16 christos } 602 1.1 christos 603 1.16 christos /* Apply only until first failure */ 604 1.16 christos if (result == ISC_R_SUCCESS) { 605 1.16 christos /* This also checks for shuttingdown condition */ 606 1.16 christos result = ixfr_apply_one(xfr, data); 607 1.5 christos } 608 1.16 christos 609 1.16 christos /* We need to clear and free all data chunks */ 610 1.16 christos dns_diff_clear(&data->diff); 611 1.16 christos isc_mem_put(xfr->mctx, data, sizeof(*data)); 612 1.16 christos } 613 1.16 christos 614 1.16 christos work->result = result; 615 1.16 christos } 616 1.16 christos 617 1.16 christos static void 618 1.16 christos ixfr_apply_done(void *arg) { 619 1.16 christos xfrin_work_t *work = arg; 620 1.16 christos REQUIRE(VALID_XFRIN_WORK(work)); 621 1.16 christos 622 1.16 christos dns_xfrin_t *xfr = work->xfr; 623 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 624 1.16 christos 625 1.16 christos isc_result_t result = work->result; 626 1.16 christos 627 1.16 christos if (atomic_load(&xfr->shuttingdown)) { 628 1.16 christos result = ISC_R_SHUTTINGDOWN; 629 1.16 christos } 630 1.16 christos 631 1.20 christos CHECK(result); 632 1.16 christos 633 1.16 christos /* Reschedule */ 634 1.16 christos if (!cds_wfcq_empty(&xfr->diff_head, &xfr->diff_tail)) { 635 1.16 christos isc_work_enqueue(xfr->loop, ixfr_apply, ixfr_apply_done, work); 636 1.16 christos return; 637 1.16 christos } 638 1.16 christos 639 1.20 christos cleanup: 640 1.16 christos xfr->diff_running = false; 641 1.16 christos 642 1.16 christos isc_mem_put(xfr->mctx, work, sizeof(*work)); 643 1.16 christos 644 1.16 christos if (result == ISC_R_SUCCESS) { 645 1.3 christos dns_db_closeversion(xfr->db, &xfr->ver, true); 646 1.1 christos dns_zone_markdirty(xfr->zone); 647 1.16 christos 648 1.16 christos if (atomic_load(&xfr->state) == XFRST_IXFR_END) { 649 1.16 christos xfrin_end(xfr, result); 650 1.16 christos } 651 1.16 christos } else { 652 1.16 christos dns_db_closeversion(xfr->db, &xfr->ver, false); 653 1.16 christos 654 1.16 christos xfrin_fail(xfr, result, "failed while processing responses"); 655 1.16 christos } 656 1.16 christos 657 1.16 christos dns_xfrin_detach(&xfr); 658 1.16 christos } 659 1.16 christos 660 1.16 christos /* 661 1.16 christos * Apply a set of IXFR changes to the database. 662 1.16 christos */ 663 1.16 christos static isc_result_t 664 1.16 christos ixfr_commit(dns_xfrin_t *xfr) { 665 1.16 christos isc_result_t result = ISC_R_SUCCESS; 666 1.16 christos ixfr_apply_data_t *data = isc_mem_get(xfr->mctx, sizeof(*data)); 667 1.16 christos 668 1.16 christos *data = (ixfr_apply_data_t){ 0 }; 669 1.16 christos cds_wfcq_node_init(&data->wfcq_node); 670 1.16 christos 671 1.16 christos if (xfr->ver == NULL) { 672 1.16 christos CHECK(dns_db_newversion(xfr->db, &xfr->ver)); 673 1.1 christos } 674 1.16 christos 675 1.16 christos dns_diff_init(xfr->mctx, &data->diff); 676 1.16 christos /* FIXME: Should we add dns_diff_move() */ 677 1.16 christos ISC_LIST_MOVE(data->diff.tuples, xfr->diff.tuples); 678 1.16 christos 679 1.16 christos (void)cds_wfcq_enqueue(&xfr->diff_head, &xfr->diff_tail, 680 1.16 christos &data->wfcq_node); 681 1.16 christos 682 1.16 christos if (!xfr->diff_running) { 683 1.16 christos xfrin_work_t *work = isc_mem_get(xfr->mctx, sizeof(*work)); 684 1.16 christos *work = (xfrin_work_t){ 685 1.16 christos .magic = XFRIN_WORK_MAGIC, 686 1.16 christos .result = ISC_R_UNSET, 687 1.16 christos .xfr = dns_xfrin_ref(xfr), 688 1.16 christos }; 689 1.16 christos xfr->diff_running = true; 690 1.16 christos isc_work_enqueue(xfr->loop, ixfr_apply, ixfr_apply_done, work); 691 1.16 christos } 692 1.16 christos 693 1.20 christos cleanup: 694 1.16 christos return result; 695 1.1 christos } 696 1.1 christos 697 1.1 christos /**************************************************************************/ 698 1.1 christos /* 699 1.1 christos * Common AXFR/IXFR protocol code 700 1.1 christos */ 701 1.1 christos 702 1.1 christos /* 703 1.1 christos * Handle a single incoming resource record according to the current 704 1.1 christos * state. 705 1.1 christos */ 706 1.1 christos static isc_result_t 707 1.16 christos xfr_rr(dns_xfrin_t *xfr, dns_name_t *name, uint32_t ttl, dns_rdata_t *rdata) { 708 1.1 christos isc_result_t result; 709 1.16 christos uint_fast32_t end_serial; 710 1.1 christos 711 1.16 christos atomic_fetch_add_relaxed(&xfr->nrecs, 1); 712 1.1 christos 713 1.1 christos if (rdata->type == dns_rdatatype_none || 714 1.12 christos dns_rdatatype_ismeta(rdata->type)) 715 1.12 christos { 716 1.14 christos char buf[64]; 717 1.14 christos dns_rdatatype_format(rdata->type, buf, sizeof(buf)); 718 1.14 christos xfrin_log(xfr, ISC_LOG_NOTICE, 719 1.14 christos "Unexpected %s record in zone transfer", buf); 720 1.20 christos CHECK(DNS_R_FORMERR); 721 1.5 christos } 722 1.1 christos 723 1.9 christos /* 724 1.9 christos * Immediately reject the entire transfer if the RR that is currently 725 1.9 christos * being processed is an SOA record that is not placed at the zone 726 1.9 christos * apex. 727 1.9 christos */ 728 1.9 christos if (rdata->type == dns_rdatatype_soa && 729 1.12 christos !dns_name_equal(&xfr->name, name)) 730 1.12 christos { 731 1.9 christos char namebuf[DNS_NAME_FORMATSIZE]; 732 1.9 christos dns_name_format(name, namebuf, sizeof(namebuf)); 733 1.9 christos xfrin_log(xfr, ISC_LOG_DEBUG(3), "SOA name mismatch: '%s'", 734 1.9 christos namebuf); 735 1.20 christos CHECK(DNS_R_NOTZONETOP); 736 1.9 christos } 737 1.9 christos 738 1.5 christos redo: 739 1.16 christos switch (atomic_load(&xfr->state)) { 740 1.1 christos case XFRST_SOAQUERY: 741 1.1 christos if (rdata->type != dns_rdatatype_soa) { 742 1.14 christos xfrin_log(xfr, ISC_LOG_NOTICE, 743 1.1 christos "non-SOA response to SOA query"); 744 1.20 christos CHECK(DNS_R_FORMERR); 745 1.1 christos } 746 1.16 christos end_serial = dns_soa_getserial(rdata); 747 1.16 christos atomic_store_relaxed(&xfr->end_serial, end_serial); 748 1.16 christos if (!DNS_SERIAL_GT(end_serial, xfr->ixfr.request_serial) && 749 1.5 christos !dns_zone_isforced(xfr->zone)) 750 1.5 christos { 751 1.1 christos xfrin_log(xfr, ISC_LOG_DEBUG(3), 752 1.1 christos "requested serial %u, " 753 1.16 christos "primary has %" PRIuFAST32 ", not updating", 754 1.16 christos xfr->ixfr.request_serial, end_serial); 755 1.20 christos CHECK(DNS_R_UPTODATE); 756 1.1 christos } 757 1.16 christos atomic_store(&xfr->state, XFRST_GOTSOA); 758 1.1 christos break; 759 1.1 christos 760 1.1 christos case XFRST_GOTSOA: 761 1.1 christos /* 762 1.1 christos * Skip other records in the answer section. 763 1.1 christos */ 764 1.1 christos break; 765 1.1 christos 766 1.16 christos case XFRST_ZONEXFRREQUEST: 767 1.1 christos if (rdata->type != dns_rdatatype_soa) { 768 1.14 christos xfrin_log(xfr, ISC_LOG_NOTICE, 769 1.1 christos "first RR in zone transfer must be SOA"); 770 1.20 christos CHECK(DNS_R_FORMERR); 771 1.1 christos } 772 1.1 christos /* 773 1.1 christos * Remember the serial number in the initial SOA. 774 1.1 christos * We need it to recognize the end of an IXFR. 775 1.1 christos */ 776 1.16 christos end_serial = dns_soa_getserial(rdata); 777 1.16 christos atomic_store_relaxed(&xfr->end_serial, end_serial); 778 1.1 christos if (xfr->reqtype == dns_rdatatype_ixfr && 779 1.16 christos !DNS_SERIAL_GT(end_serial, xfr->ixfr.request_serial) && 780 1.5 christos !dns_zone_isforced(xfr->zone)) 781 1.1 christos { 782 1.1 christos /* 783 1.1 christos * This must be the single SOA record that is 784 1.14 christos * sent when the current version on the primary 785 1.1 christos * is not newer than the version in the request. 786 1.1 christos */ 787 1.1 christos xfrin_log(xfr, ISC_LOG_DEBUG(3), 788 1.1 christos "requested serial %u, " 789 1.16 christos "primary has %" PRIuFAST32 ", not updating", 790 1.16 christos xfr->ixfr.request_serial, end_serial); 791 1.20 christos CHECK(DNS_R_UPTODATE); 792 1.1 christos } 793 1.10 christos xfr->firstsoa = *rdata; 794 1.10 christos if (xfr->firstsoa_data != NULL) { 795 1.10 christos isc_mem_free(xfr->mctx, xfr->firstsoa_data); 796 1.10 christos } 797 1.10 christos xfr->firstsoa_data = isc_mem_allocate(xfr->mctx, rdata->length); 798 1.10 christos memcpy(xfr->firstsoa_data, rdata->data, rdata->length); 799 1.10 christos xfr->firstsoa.data = xfr->firstsoa_data; 800 1.16 christos atomic_store(&xfr->state, XFRST_FIRSTDATA); 801 1.1 christos break; 802 1.1 christos 803 1.1 christos case XFRST_FIRSTDATA: 804 1.1 christos /* 805 1.1 christos * If the transfer begins with one SOA record, it is an AXFR, 806 1.1 christos * if it begins with two SOAs, it is an IXFR. 807 1.1 christos */ 808 1.1 christos if (xfr->reqtype == dns_rdatatype_ixfr && 809 1.1 christos rdata->type == dns_rdatatype_soa && 810 1.5 christos xfr->ixfr.request_serial == dns_soa_getserial(rdata)) 811 1.5 christos { 812 1.1 christos xfrin_log(xfr, ISC_LOG_DEBUG(3), 813 1.1 christos "got incremental response"); 814 1.1 christos CHECK(ixfr_init(xfr)); 815 1.16 christos atomic_store(&xfr->state, XFRST_IXFR_DELSOA); 816 1.1 christos } else { 817 1.1 christos xfrin_log(xfr, ISC_LOG_DEBUG(3), 818 1.1 christos "got nonincremental response"); 819 1.1 christos CHECK(axfr_init(xfr)); 820 1.16 christos atomic_store(&xfr->state, XFRST_AXFR); 821 1.1 christos } 822 1.1 christos goto redo; 823 1.1 christos 824 1.1 christos case XFRST_IXFR_DELSOA: 825 1.1 christos INSIST(rdata->type == dns_rdatatype_soa); 826 1.1 christos CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata)); 827 1.16 christos atomic_store(&xfr->state, XFRST_IXFR_DEL); 828 1.1 christos break; 829 1.1 christos 830 1.1 christos case XFRST_IXFR_DEL: 831 1.1 christos if (rdata->type == dns_rdatatype_soa) { 832 1.3 christos uint32_t soa_serial = dns_soa_getserial(rdata); 833 1.16 christos atomic_store(&xfr->state, XFRST_IXFR_ADDSOA); 834 1.1 christos xfr->ixfr.current_serial = soa_serial; 835 1.1 christos goto redo; 836 1.1 christos } 837 1.1 christos CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata)); 838 1.1 christos break; 839 1.1 christos 840 1.1 christos case XFRST_IXFR_ADDSOA: 841 1.1 christos INSIST(rdata->type == dns_rdatatype_soa); 842 1.1 christos CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata)); 843 1.16 christos atomic_store(&xfr->state, XFRST_IXFR_ADD); 844 1.1 christos break; 845 1.1 christos 846 1.1 christos case XFRST_IXFR_ADD: 847 1.1 christos if (rdata->type == dns_rdatatype_soa) { 848 1.3 christos uint32_t soa_serial = dns_soa_getserial(rdata); 849 1.16 christos if (soa_serial == atomic_load_relaxed(&xfr->end_serial)) 850 1.16 christos { 851 1.1 christos CHECK(ixfr_commit(xfr)); 852 1.16 christos atomic_store(&xfr->state, XFRST_IXFR_END); 853 1.1 christos break; 854 1.1 christos } else if (soa_serial != xfr->ixfr.current_serial) { 855 1.14 christos xfrin_log(xfr, ISC_LOG_NOTICE, 856 1.1 christos "IXFR out of sync: " 857 1.1 christos "expected serial %u, got %u", 858 1.1 christos xfr->ixfr.current_serial, soa_serial); 859 1.20 christos CHECK(DNS_R_FORMERR); 860 1.1 christos } else { 861 1.1 christos CHECK(ixfr_commit(xfr)); 862 1.16 christos atomic_store(&xfr->state, XFRST_IXFR_DELSOA); 863 1.1 christos goto redo; 864 1.1 christos } 865 1.1 christos } 866 1.1 christos if (rdata->type == dns_rdatatype_ns && 867 1.12 christos dns_name_iswildcard(name)) 868 1.12 christos { 869 1.20 christos CHECK(DNS_R_INVALIDNS); 870 1.5 christos } 871 1.1 christos CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata)); 872 1.1 christos break; 873 1.1 christos 874 1.1 christos case XFRST_AXFR: 875 1.1 christos /* 876 1.1 christos * Old BINDs sent cross class A records for non IN classes. 877 1.1 christos */ 878 1.1 christos if (rdata->type == dns_rdatatype_a && 879 1.1 christos rdata->rdclass != xfr->rdclass && 880 1.1 christos xfr->rdclass != dns_rdataclass_in) 881 1.5 christos { 882 1.1 christos break; 883 1.5 christos } 884 1.1 christos CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata)); 885 1.1 christos if (rdata->type == dns_rdatatype_soa) { 886 1.10 christos /* 887 1.10 christos * Use dns_rdata_compare instead of memcmp to 888 1.10 christos * allow for case differences. 889 1.10 christos */ 890 1.10 christos if (dns_rdata_compare(rdata, &xfr->firstsoa) != 0) { 891 1.14 christos xfrin_log(xfr, ISC_LOG_NOTICE, 892 1.10 christos "start and ending SOA records " 893 1.10 christos "mismatch"); 894 1.20 christos CHECK(DNS_R_FORMERR); 895 1.10 christos } 896 1.16 christos axfr_commit(xfr); 897 1.16 christos atomic_store(&xfr->state, XFRST_AXFR_END); 898 1.1 christos break; 899 1.1 christos } 900 1.1 christos break; 901 1.1 christos case XFRST_AXFR_END: 902 1.1 christos case XFRST_IXFR_END: 903 1.20 christos CHECK(DNS_R_EXTRADATA); 904 1.20 christos break; 905 1.1 christos default: 906 1.11 christos UNREACHABLE(); 907 1.1 christos } 908 1.1 christos result = ISC_R_SUCCESS; 909 1.20 christos cleanup: 910 1.16 christos return result; 911 1.1 christos } 912 1.1 christos 913 1.16 christos void 914 1.1 christos dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype, 915 1.14 christos const isc_sockaddr_t *primaryaddr, 916 1.14 christos const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey, 917 1.16 christos dns_transport_type_t soa_transport_type, 918 1.14 christos dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, 919 1.16 christos isc_mem_t *mctx, dns_xfrin_t **xfrp) { 920 1.1 christos dns_name_t *zonename = dns_zone_getorigin(zone); 921 1.16 christos dns_xfrin_t *xfr = NULL; 922 1.1 christos dns_db_t *db = NULL; 923 1.16 christos isc_loop_t *loop = NULL; 924 1.1 christos 925 1.1 christos REQUIRE(xfrp != NULL && *xfrp == NULL); 926 1.14 christos REQUIRE(isc_sockaddr_getport(primaryaddr) != 0); 927 1.16 christos REQUIRE(zone != NULL); 928 1.16 christos REQUIRE(dns_zone_getview(zone) != NULL); 929 1.16 christos 930 1.16 christos loop = dns_zone_getloop(zone); 931 1.1 christos 932 1.1 christos (void)dns_zone_getdb(zone, &db); 933 1.1 christos 934 1.5 christos if (xfrtype == dns_rdatatype_soa || xfrtype == dns_rdatatype_ixfr) { 935 1.1 christos REQUIRE(db != NULL); 936 1.5 christos } 937 1.1 christos 938 1.16 christos xfrin_create(mctx, zone, db, loop, zonename, dns_zone_getclass(zone), 939 1.16 christos xfrtype, primaryaddr, sourceaddr, tsigkey, 940 1.16 christos soa_transport_type, transport, tlsctx_cache, &xfr); 941 1.1 christos 942 1.4 christos if (db != NULL) { 943 1.4 christos xfr->zone_had_db = true; 944 1.16 christos dns_db_detach(&db); 945 1.4 christos } 946 1.4 christos 947 1.16 christos *xfrp = xfr; 948 1.16 christos } 949 1.16 christos 950 1.16 christos isc_result_t 951 1.16 christos dns_xfrin_start(dns_xfrin_t *xfr, dns_xfrindone_t done) { 952 1.16 christos isc_result_t result; 953 1.14 christos 954 1.16 christos REQUIRE(xfr != NULL); 955 1.16 christos REQUIRE(xfr->zone != NULL); 956 1.16 christos REQUIRE(done != NULL); 957 1.14 christos 958 1.16 christos xfr->done = done; 959 1.1 christos 960 1.14 christos result = xfrin_start(xfr); 961 1.14 christos if (result != ISC_R_SUCCESS) { 962 1.16 christos xfr->done = NULL; 963 1.16 christos xfrin_fail(xfr, result, "zone transfer start failed"); 964 1.5 christos } 965 1.1 christos 966 1.16 christos return result; 967 1.16 christos } 968 1.16 christos 969 1.16 christos static void 970 1.16 christos xfrin_timedout(void *xfr) { 971 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 972 1.16 christos 973 1.16 christos xfrin_fail(xfr, ISC_R_TIMEDOUT, "maximum transfer time exceeded"); 974 1.16 christos } 975 1.16 christos 976 1.16 christos static void 977 1.16 christos xfrin_idledout(void *xfr) { 978 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 979 1.16 christos 980 1.16 christos xfrin_fail(xfr, ISC_R_TIMEDOUT, "maximum idle time exceeded"); 981 1.16 christos } 982 1.16 christos 983 1.18 christos static void 984 1.18 christos xfrin_minratecheck(void *arg) { 985 1.18 christos dns_xfrin_t *xfr = arg; 986 1.18 christos 987 1.18 christos REQUIRE(VALID_XFRIN(xfr)); 988 1.18 christos 989 1.19 christos const uint64_t nbytes = ISC_XFRIN_LOAD(&xfr->nbytes, uint64_t); 990 1.18 christos const uint64_t min = dns_zone_getminxfrratebytesin(xfr->zone); 991 1.18 christos uint64_t rate = nbytes - xfr->nbytes_saved; 992 1.18 christos 993 1.18 christos if (rate < min) { 994 1.18 christos isc_timer_stop(xfr->min_rate_timer); 995 1.18 christos xfrin_fail(xfr, ISC_R_TIMEDOUT, 996 1.18 christos "minimum transfer rate reached"); 997 1.18 christos } else { 998 1.18 christos xfr->nbytes_saved = nbytes; 999 1.18 christos 1000 1.18 christos /* 1001 1.18 christos * Calculate and store for the statistics channel the transfer 1002 1.18 christos * rate in bytes-per-second for the latest interval. 1003 1.18 christos */ 1004 1.18 christos rate /= dns_zone_getminxfrratesecondsin(xfr->zone); 1005 1.19 christos ISC_XFRIN_STORE(&xfr->rate_bytes_per_second, rate); 1006 1.18 christos } 1007 1.18 christos } 1008 1.18 christos 1009 1.16 christos isc_time_t 1010 1.16 christos dns_xfrin_getstarttime(dns_xfrin_t *xfr) { 1011 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 1012 1.16 christos 1013 1.17 christos return ISC_XFRIN_LOAD(&xfr->start, isc_time_t); 1014 1.16 christos } 1015 1.16 christos 1016 1.16 christos void 1017 1.16 christos dns_xfrin_getstate(const dns_xfrin_t *xfr, const char **statestr, 1018 1.16 christos bool *is_first_data_received, bool *is_ixfr) { 1019 1.16 christos xfrin_state_t state; 1020 1.16 christos 1021 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 1022 1.16 christos REQUIRE(statestr != NULL && *statestr == NULL); 1023 1.16 christos REQUIRE(is_ixfr != NULL); 1024 1.16 christos 1025 1.16 christos state = atomic_load(&xfr->state); 1026 1.16 christos *statestr = ""; 1027 1.16 christos *is_first_data_received = (state > XFRST_FIRSTDATA); 1028 1.16 christos *is_ixfr = atomic_load(&xfr->is_ixfr); 1029 1.16 christos 1030 1.16 christos switch (state) { 1031 1.16 christos case XFRST_SOAQUERY: 1032 1.16 christos *statestr = "SOA Query"; 1033 1.16 christos break; 1034 1.16 christos case XFRST_GOTSOA: 1035 1.16 christos *statestr = "Got SOA"; 1036 1.16 christos break; 1037 1.16 christos case XFRST_ZONEXFRREQUEST: 1038 1.16 christos *statestr = "Zone Transfer Request"; 1039 1.16 christos break; 1040 1.16 christos case XFRST_FIRSTDATA: 1041 1.16 christos *statestr = "First Data"; 1042 1.16 christos break; 1043 1.16 christos case XFRST_IXFR_DELSOA: 1044 1.16 christos case XFRST_IXFR_DEL: 1045 1.16 christos case XFRST_IXFR_ADDSOA: 1046 1.16 christos case XFRST_IXFR_ADD: 1047 1.16 christos *statestr = "Receiving IXFR Data"; 1048 1.16 christos break; 1049 1.16 christos case XFRST_IXFR_END: 1050 1.16 christos *statestr = "Finalizing IXFR"; 1051 1.16 christos break; 1052 1.16 christos case XFRST_AXFR: 1053 1.16 christos *statestr = "Receiving AXFR Data"; 1054 1.16 christos break; 1055 1.16 christos case XFRST_AXFR_END: 1056 1.16 christos *statestr = "Finalizing AXFR"; 1057 1.16 christos break; 1058 1.5 christos } 1059 1.16 christos } 1060 1.14 christos 1061 1.16 christos uint32_t 1062 1.16 christos dns_xfrin_getendserial(dns_xfrin_t *xfr) { 1063 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 1064 1.16 christos 1065 1.16 christos return atomic_load_relaxed(&xfr->end_serial); 1066 1.16 christos } 1067 1.16 christos 1068 1.16 christos void 1069 1.16 christos dns_xfrin_getstats(dns_xfrin_t *xfr, unsigned int *nmsgp, unsigned int *nrecsp, 1070 1.18 christos uint64_t *nbytesp, uint64_t *ratep) { 1071 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 1072 1.16 christos REQUIRE(nmsgp != NULL && nrecsp != NULL && nbytesp != NULL); 1073 1.16 christos 1074 1.19 christos uint64_t rate = ISC_XFRIN_LOAD(&xfr->rate_bytes_per_second, uint64_t); 1075 1.18 christos if (rate == 0) { 1076 1.18 christos /* 1077 1.18 christos * Likely the first 'min-transfer-rate-in <bytes> <minutes>' 1078 1.18 christos * minutes interval hasn't passed yet. Calculate the overall 1079 1.18 christos * average transfer rate instead. 1080 1.18 christos */ 1081 1.18 christos isc_time_t now = isc_time_now(); 1082 1.19 christos isc_time_t start = ISC_XFRIN_LOAD(&xfr->start, isc_time_t); 1083 1.18 christos uint64_t sec = isc_time_microdiff(&now, &start) / US_PER_SEC; 1084 1.18 christos if (sec > 0) { 1085 1.19 christos rate = ISC_XFRIN_LOAD(&xfr->nbytes, uint64_t) / sec; 1086 1.18 christos } 1087 1.18 christos } 1088 1.18 christos 1089 1.16 christos SET_IF_NOT_NULL(nmsgp, atomic_load_relaxed(&xfr->nmsg)); 1090 1.16 christos SET_IF_NOT_NULL(nrecsp, atomic_load_relaxed(&xfr->nrecs)); 1091 1.17 christos SET_IF_NOT_NULL(nbytesp, ISC_XFRIN_LOAD(&xfr->nbytes, uint64_t)); 1092 1.18 christos SET_IF_NOT_NULL(ratep, rate); 1093 1.16 christos } 1094 1.16 christos 1095 1.16 christos const isc_sockaddr_t * 1096 1.16 christos dns_xfrin_getsourceaddr(const dns_xfrin_t *xfr) { 1097 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 1098 1.14 christos 1099 1.16 christos return &xfr->sourceaddr; 1100 1.1 christos } 1101 1.1 christos 1102 1.16 christos const isc_sockaddr_t * 1103 1.16 christos dns_xfrin_getprimaryaddr(const dns_xfrin_t *xfr) { 1104 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 1105 1.14 christos 1106 1.16 christos return &xfr->primaryaddr; 1107 1.16 christos } 1108 1.14 christos 1109 1.16 christos dns_transport_type_t 1110 1.16 christos dns_xfrin_gettransporttype(const dns_xfrin_t *xfr) { 1111 1.14 christos REQUIRE(VALID_XFRIN(xfr)); 1112 1.14 christos 1113 1.16 christos if (xfr->transport != NULL) { 1114 1.16 christos return dns_transport_get_type(xfr->transport); 1115 1.16 christos } 1116 1.16 christos 1117 1.16 christos return DNS_TRANSPORT_TCP; 1118 1.14 christos } 1119 1.14 christos 1120 1.16 christos dns_transport_type_t 1121 1.16 christos dns_xfrin_getsoatransporttype(dns_xfrin_t *xfr) { 1122 1.14 christos REQUIRE(VALID_XFRIN(xfr)); 1123 1.14 christos 1124 1.16 christos return atomic_load_relaxed(&xfr->soa_transport_type); 1125 1.14 christos } 1126 1.14 christos 1127 1.16 christos const dns_name_t * 1128 1.16 christos dns_xfrin_gettsigkeyname(const dns_xfrin_t *xfr) { 1129 1.14 christos REQUIRE(VALID_XFRIN(xfr)); 1130 1.14 christos 1131 1.16 christos if (xfr->tsigkey == NULL || xfr->tsigkey->key == NULL) { 1132 1.16 christos return NULL; 1133 1.16 christos } 1134 1.16 christos 1135 1.16 christos return dst_key_name(xfr->tsigkey->key); 1136 1.1 christos } 1137 1.1 christos 1138 1.16 christos static void 1139 1.16 christos xfrin_shutdown(void *arg) { 1140 1.16 christos dns_xfrin_t *xfr = arg; 1141 1.16 christos 1142 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 1143 1.14 christos 1144 1.16 christos xfrin_fail(xfr, ISC_R_SHUTTINGDOWN, "shut down"); 1145 1.16 christos dns_xfrin_detach(&xfr); 1146 1.1 christos } 1147 1.1 christos 1148 1.1 christos void 1149 1.16 christos dns_xfrin_shutdown(dns_xfrin_t *xfr) { 1150 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 1151 1.14 christos 1152 1.16 christos if (xfr->loop != isc_loop()) { 1153 1.16 christos dns_xfrin_ref(xfr); 1154 1.16 christos isc_async_run(xfr->loop, xfrin_shutdown, xfr); 1155 1.16 christos } else { 1156 1.16 christos xfrin_fail(xfr, ISC_R_SHUTTINGDOWN, "shut down"); 1157 1.14 christos } 1158 1.1 christos } 1159 1.1 christos 1160 1.16 christos #if DNS_XFRIN_TRACE 1161 1.16 christos ISC_REFCOUNT_TRACE_IMPL(dns_xfrin, xfrin_destroy); 1162 1.16 christos #else 1163 1.16 christos ISC_REFCOUNT_IMPL(dns_xfrin, xfrin_destroy); 1164 1.16 christos #endif 1165 1.16 christos 1166 1.1 christos static void 1167 1.16 christos xfrin_cancelio(dns_xfrin_t *xfr) { 1168 1.16 christos if (xfr->dispentry != NULL) { 1169 1.16 christos dns_dispatch_done(&xfr->dispentry); 1170 1.16 christos } 1171 1.16 christos if (xfr->disp != NULL) { 1172 1.16 christos dns_dispatch_detach(&xfr->disp); 1173 1.1 christos } 1174 1.1 christos } 1175 1.1 christos 1176 1.1 christos static void 1177 1.16 christos xfrin_reset(dns_xfrin_t *xfr) { 1178 1.1 christos REQUIRE(VALID_XFRIN(xfr)); 1179 1.1 christos 1180 1.1 christos xfrin_log(xfr, ISC_LOG_INFO, "resetting"); 1181 1.1 christos 1182 1.5 christos if (xfr->lasttsig != NULL) { 1183 1.1 christos isc_buffer_free(&xfr->lasttsig); 1184 1.5 christos } 1185 1.1 christos 1186 1.1 christos dns_diff_clear(&xfr->diff); 1187 1.1 christos 1188 1.5 christos if (xfr->ixfr.journal != NULL) { 1189 1.1 christos dns_journal_destroy(&xfr->ixfr.journal); 1190 1.5 christos } 1191 1.1 christos 1192 1.5 christos if (xfr->axfr.add_private != NULL) { 1193 1.1 christos (void)dns_db_endload(xfr->db, &xfr->axfr); 1194 1.5 christos } 1195 1.1 christos 1196 1.5 christos if (xfr->ver != NULL) { 1197 1.3 christos dns_db_closeversion(xfr->db, &xfr->ver, false); 1198 1.5 christos } 1199 1.1 christos } 1200 1.1 christos 1201 1.1 christos static void 1202 1.16 christos xfrin_fail(dns_xfrin_t *xfr, isc_result_t result, const char *msg) { 1203 1.16 christos REQUIRE(VALID_XFRIN(xfr)); 1204 1.16 christos 1205 1.16 christos dns_xfrin_ref(xfr); 1206 1.16 christos 1207 1.14 christos /* Make sure only the first xfrin_fail() trumps */ 1208 1.14 christos if (atomic_compare_exchange_strong(&xfr->shuttingdown, &(bool){ false }, 1209 1.14 christos true)) 1210 1.14 christos { 1211 1.16 christos if (result != DNS_R_UPTODATE) { 1212 1.14 christos xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s", msg, 1213 1.14 christos isc_result_totext(result)); 1214 1.16 christos if (atomic_load(&xfr->is_ixfr) && 1215 1.16 christos result != ISC_R_CANCELED && 1216 1.16 christos result != ISC_R_SHUTTINGDOWN) 1217 1.16 christos { 1218 1.16 christos /* 1219 1.16 christos * Pass special result code to force AXFR retry 1220 1.14 christos */ 1221 1.14 christos result = DNS_R_BADIXFR; 1222 1.14 christos } 1223 1.14 christos } 1224 1.16 christos 1225 1.14 christos xfrin_cancelio(xfr); 1226 1.16 christos 1227 1.16 christos xfrin_end(xfr, result); 1228 1.1 christos } 1229 1.16 christos 1230 1.16 christos dns_xfrin_detach(&xfr); 1231 1.1 christos } 1232 1.1 christos 1233 1.14 christos static void 1234 1.16 christos xfrin_create(isc_mem_t *mctx, dns_zone_t *zone, dns_db_t *db, isc_loop_t *loop, 1235 1.5 christos dns_name_t *zonename, dns_rdataclass_t rdclass, 1236 1.14 christos dns_rdatatype_t reqtype, const isc_sockaddr_t *primaryaddr, 1237 1.14 christos const isc_sockaddr_t *sourceaddr, dns_tsigkey_t *tsigkey, 1238 1.16 christos dns_transport_type_t soa_transport_type, 1239 1.14 christos dns_transport_t *transport, isc_tlsctx_cache_t *tlsctx_cache, 1240 1.16 christos dns_xfrin_t **xfrp) { 1241 1.16 christos dns_xfrin_t *xfr = NULL; 1242 1.1 christos 1243 1.1 christos xfr = isc_mem_get(mctx, sizeof(*xfr)); 1244 1.16 christos *xfr = (dns_xfrin_t){ 1245 1.16 christos .shutdown_result = ISC_R_UNSET, 1246 1.16 christos .rdclass = rdclass, 1247 1.16 christos .reqtype = reqtype, 1248 1.16 christos .maxrecords = dns_zone_getmaxrecords(zone), 1249 1.16 christos .primaryaddr = *primaryaddr, 1250 1.16 christos .sourceaddr = *sourceaddr, 1251 1.16 christos .soa_transport_type = soa_transport_type, 1252 1.16 christos .firstsoa = DNS_RDATA_INIT, 1253 1.16 christos .edns = true, 1254 1.16 christos .references = 1, 1255 1.16 christos .magic = XFRIN_MAGIC, 1256 1.16 christos }; 1257 1.14 christos 1258 1.16 christos isc_loop_attach(loop, &xfr->loop); 1259 1.1 christos isc_mem_attach(mctx, &xfr->mctx); 1260 1.1 christos dns_zone_iattach(zone, &xfr->zone); 1261 1.16 christos dns_view_weakattach(dns_zone_getview(zone), &xfr->view); 1262 1.14 christos dns_name_init(&xfr->name, NULL); 1263 1.1 christos 1264 1.16 christos __cds_wfcq_init(&xfr->diff_head, &xfr->diff_tail); 1265 1.14 christos 1266 1.16 christos atomic_init(&xfr->is_ixfr, false); 1267 1.1 christos 1268 1.5 christos if (db != NULL) { 1269 1.1 christos dns_db_attach(db, &xfr->db); 1270 1.5 christos } 1271 1.14 christos 1272 1.1 christos dns_diff_init(xfr->mctx, &xfr->diff); 1273 1.1 christos 1274 1.5 christos if (reqtype == dns_rdatatype_soa) { 1275 1.16 christos atomic_init(&xfr->state, XFRST_SOAQUERY); 1276 1.5 christos } else { 1277 1.16 christos atomic_init(&xfr->state, XFRST_ZONEXFRREQUEST); 1278 1.5 christos } 1279 1.1 christos 1280 1.17 christos ISC_XFRIN_STORE(&xfr->start, isc_time_now()); 1281 1.1 christos 1282 1.5 christos if (tsigkey != NULL) { 1283 1.1 christos dns_tsigkey_attach(tsigkey, &xfr->tsigkey); 1284 1.5 christos } 1285 1.1 christos 1286 1.14 christos if (transport != NULL) { 1287 1.14 christos dns_transport_attach(transport, &xfr->transport); 1288 1.14 christos } 1289 1.1 christos 1290 1.5 christos dns_name_dup(zonename, mctx, &xfr->name); 1291 1.1 christos 1292 1.14 christos INSIST(isc_sockaddr_pf(primaryaddr) == isc_sockaddr_pf(sourceaddr)); 1293 1.1 christos isc_sockaddr_setport(&xfr->sourceaddr, 0); 1294 1.1 christos 1295 1.1 christos /* 1296 1.5 christos * Reserve 2 bytes for TCP length at the beginning of the buffer. 1297 1.1 christos */ 1298 1.1 christos isc_buffer_init(&xfr->qbuffer, &xfr->qbuffer_data[2], 1299 1.1 christos sizeof(xfr->qbuffer_data) - 2); 1300 1.1 christos 1301 1.14 christos isc_tlsctx_cache_attach(tlsctx_cache, &xfr->tlsctx_cache); 1302 1.14 christos 1303 1.16 christos dns_zone_name(xfr->zone, xfr->info, sizeof(xfr->info)); 1304 1.14 christos 1305 1.1 christos *xfrp = xfr; 1306 1.14 christos } 1307 1.14 christos 1308 1.14 christos static isc_result_t 1309 1.16 christos xfrin_start(dns_xfrin_t *xfr) { 1310 1.14 christos isc_result_t result = ISC_R_FAILURE; 1311 1.16 christos isc_interval_t interval; 1312 1.16 christos 1313 1.16 christos dns_xfrin_ref(xfr); 1314 1.16 christos 1315 1.16 christos /* If this is a retry, we need to cancel the previous dispentry */ 1316 1.16 christos xfrin_cancelio(xfr); 1317 1.14 christos 1318 1.16 christos dns_dispatchmgr_t *dispmgr = dns_view_getdispatchmgr(xfr->view); 1319 1.16 christos if (dispmgr == NULL) { 1320 1.20 christos CHECK(ISC_R_SHUTTINGDOWN); 1321 1.16 christos } else { 1322 1.16 christos result = dns_dispatch_createtcp( 1323 1.16 christos dispmgr, &xfr->sourceaddr, &xfr->primaryaddr, 1324 1.16 christos xfr->transport, DNS_DISPATCHOPT_UNSHARED, &xfr->disp); 1325 1.16 christos dns_dispatchmgr_detach(&dispmgr); 1326 1.20 christos CHECK(result); 1327 1.14 christos } 1328 1.14 christos 1329 1.16 christos LIBDNS_XFRIN_START(xfr, xfr->info); 1330 1.14 christos 1331 1.14 christos /* 1332 1.16 christos * If the transfer is started when the 'state' is XFRST_SOAQUERY, it 1333 1.16 christos * means the SOA query will be performed by xfrin. A transfer could also 1334 1.16 christos * be initiated starting from the XFRST_ZONEXFRREQUEST state, which 1335 1.16 christos * means that the SOA query was already performed by other means (e.g. 1336 1.16 christos * by zone.c:soa_query()), or that it's a transfer without a preceding 1337 1.16 christos * SOA request, and 'soa_transport_type' is already correctly 1338 1.16 christos * set by the creator of the xfrin. 1339 1.14 christos */ 1340 1.16 christos if (atomic_load(&xfr->state) == XFRST_SOAQUERY) { 1341 1.16 christos /* 1342 1.16 christos * The "SOA before" mode is used, where the SOA request is 1343 1.16 christos * using the same transport as the XFR. 1344 1.16 christos */ 1345 1.16 christos atomic_store_relaxed(&xfr->soa_transport_type, 1346 1.16 christos dns_xfrin_gettransporttype(xfr)); 1347 1.5 christos } 1348 1.1 christos 1349 1.16 christos CHECK(dns_dispatch_add( 1350 1.16 christos xfr->disp, xfr->loop, 0, 0, &xfr->primaryaddr, xfr->transport, 1351 1.16 christos xfr->tlsctx_cache, xfrin_connect_done, xfrin_send_done, 1352 1.16 christos xfrin_recv_done, xfr, &xfr->id, &xfr->dispentry)); 1353 1.1 christos 1354 1.16 christos /* Set the maximum timer */ 1355 1.16 christos if (xfr->max_time_timer == NULL) { 1356 1.16 christos isc_timer_create(dns_zone_getloop(xfr->zone), xfrin_timedout, 1357 1.16 christos xfr, &xfr->max_time_timer); 1358 1.14 christos } 1359 1.14 christos isc_interval_set(&interval, dns_zone_getmaxxfrin(xfr->zone), 0); 1360 1.16 christos isc_timer_start(xfr->max_time_timer, isc_timertype_once, &interval); 1361 1.14 christos 1362 1.14 christos /* Set the idle timer */ 1363 1.16 christos if (xfr->max_idle_timer == NULL) { 1364 1.16 christos isc_timer_create(dns_zone_getloop(xfr->zone), xfrin_idledout, 1365 1.16 christos xfr, &xfr->max_idle_timer); 1366 1.16 christos } 1367 1.14 christos isc_interval_set(&interval, dns_zone_getidlein(xfr->zone), 0); 1368 1.16 christos isc_timer_start(xfr->max_idle_timer, isc_timertype_once, &interval); 1369 1.14 christos 1370 1.18 christos /* Set the minimum transfer rate checking timer */ 1371 1.18 christos if (xfr->min_rate_timer == NULL) { 1372 1.18 christos isc_timer_create(dns_zone_getloop(xfr->zone), 1373 1.18 christos xfrin_minratecheck, xfr, &xfr->min_rate_timer); 1374 1.18 christos } 1375 1.18 christos isc_interval_set(&interval, dns_zone_getminxfrratesecondsin(xfr->zone), 1376 1.18 christos 0); 1377 1.18 christos isc_timer_start(xfr->min_rate_timer, isc_timertype_ticker, &interval); 1378 1.18 christos 1379 1.14 christos /* 1380 1.16 christos * The connect has to be the last thing that is called before returning, 1381 1.16 christos * as it can end synchronously and destroy the xfr object. 1382 1.14 christos */ 1383 1.16 christos CHECK(dns_dispatch_connect(xfr->dispentry)); 1384 1.14 christos 1385 1.16 christos return ISC_R_SUCCESS; 1386 1.14 christos 1387 1.20 christos cleanup: 1388 1.16 christos xfrin_cancelio(xfr); 1389 1.16 christos dns_xfrin_detach(&xfr); 1390 1.16 christos 1391 1.16 christos return result; 1392 1.1 christos } 1393 1.1 christos 1394 1.1 christos /* XXX the resolver could use this, too */ 1395 1.1 christos 1396 1.1 christos static isc_result_t 1397 1.1 christos render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf) { 1398 1.1 christos dns_compress_t cctx; 1399 1.1 christos isc_result_t result; 1400 1.1 christos 1401 1.16 christos dns_compress_init(&cctx, mctx, 0); 1402 1.1 christos CHECK(dns_message_renderbegin(msg, &cctx, buf)); 1403 1.1 christos CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0)); 1404 1.1 christos CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0)); 1405 1.1 christos CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0)); 1406 1.1 christos CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0)); 1407 1.1 christos CHECK(dns_message_renderend(msg)); 1408 1.1 christos result = ISC_R_SUCCESS; 1409 1.20 christos cleanup: 1410 1.16 christos dns_compress_invalidate(&cctx); 1411 1.16 christos return result; 1412 1.1 christos } 1413 1.1 christos 1414 1.1 christos /* 1415 1.1 christos * A connection has been established. 1416 1.1 christos */ 1417 1.1 christos static void 1418 1.16 christos xfrin_connect_done(isc_result_t result, isc_region_t *region ISC_ATTR_UNUSED, 1419 1.16 christos void *arg) { 1420 1.16 christos dns_xfrin_t *xfr = (dns_xfrin_t *)arg; 1421 1.16 christos char addrtext[ISC_SOCKADDR_FORMATSIZE]; 1422 1.1 christos char signerbuf[DNS_NAME_FORMATSIZE]; 1423 1.1 christos const char *signer = "", *sep = ""; 1424 1.14 christos dns_zonemgr_t *zmgr = NULL; 1425 1.1 christos 1426 1.1 christos REQUIRE(VALID_XFRIN(xfr)); 1427 1.1 christos 1428 1.14 christos if (atomic_load(&xfr->shuttingdown)) { 1429 1.14 christos result = ISC_R_SHUTTINGDOWN; 1430 1.14 christos } 1431 1.1 christos 1432 1.16 christos LIBDNS_XFRIN_CONNECTED(xfr, xfr->info, result); 1433 1.16 christos 1434 1.14 christos if (result != ISC_R_SUCCESS) { 1435 1.14 christos xfrin_fail(xfr, result, "failed to connect"); 1436 1.20 christos goto cleanup; 1437 1.14 christos } 1438 1.1 christos 1439 1.16 christos result = dns_dispatch_checkperm(xfr->disp); 1440 1.14 christos if (result != ISC_R_SUCCESS) { 1441 1.14 christos xfrin_fail(xfr, result, "connected but unable to transfer"); 1442 1.20 christos goto cleanup; 1443 1.1 christos } 1444 1.1 christos 1445 1.1 christos zmgr = dns_zone_getmgr(xfr->zone); 1446 1.1 christos if (zmgr != NULL) { 1447 1.14 christos dns_zonemgr_unreachabledel(zmgr, &xfr->primaryaddr, 1448 1.14 christos &xfr->sourceaddr); 1449 1.1 christos } 1450 1.1 christos 1451 1.1 christos if (xfr->tsigkey != NULL && xfr->tsigkey->key != NULL) { 1452 1.5 christos dns_name_format(dst_key_name(xfr->tsigkey->key), signerbuf, 1453 1.5 christos sizeof(signerbuf)); 1454 1.1 christos sep = " TSIG "; 1455 1.1 christos signer = signerbuf; 1456 1.1 christos } 1457 1.1 christos 1458 1.16 christos isc_sockaddr_format(&xfr->primaryaddr, addrtext, sizeof(addrtext)); 1459 1.16 christos xfrin_log(xfr, ISC_LOG_INFO, "connected using %s%s%s", addrtext, sep, 1460 1.5 christos signer); 1461 1.1 christos 1462 1.14 christos result = xfrin_send_request(xfr); 1463 1.14 christos if (result != ISC_R_SUCCESS) { 1464 1.14 christos xfrin_fail(xfr, result, "connected but unable to send"); 1465 1.16 christos goto detach; 1466 1.14 christos } 1467 1.1 christos 1468 1.16 christos return; 1469 1.16 christos 1470 1.20 christos cleanup: 1471 1.14 christos switch (result) { 1472 1.14 christos case ISC_R_NETDOWN: 1473 1.14 christos case ISC_R_HOSTDOWN: 1474 1.14 christos case ISC_R_NETUNREACH: 1475 1.14 christos case ISC_R_HOSTUNREACH: 1476 1.14 christos case ISC_R_CONNREFUSED: 1477 1.14 christos case ISC_R_TIMEDOUT: 1478 1.14 christos /* 1479 1.14 christos * Add the server to unreachable primaries table if 1480 1.14 christos * the server has a permanent networking error or 1481 1.14 christos * the connection attempt as timed out. 1482 1.14 christos */ 1483 1.14 christos zmgr = dns_zone_getmgr(xfr->zone); 1484 1.14 christos if (zmgr != NULL) { 1485 1.16 christos isc_time_t now = isc_time_now(); 1486 1.14 christos 1487 1.14 christos dns_zonemgr_unreachableadd(zmgr, &xfr->primaryaddr, 1488 1.14 christos &xfr->sourceaddr, &now); 1489 1.14 christos } 1490 1.14 christos break; 1491 1.14 christos default: 1492 1.14 christos /* Retry sooner than in 10 minutes */ 1493 1.14 christos break; 1494 1.5 christos } 1495 1.14 christos 1496 1.16 christos detach: 1497 1.14 christos dns_xfrin_detach(&xfr); 1498 1.1 christos } 1499 1.1 christos 1500 1.1 christos /* 1501 1.1 christos * Convert a tuple into a dns_name_t suitable for inserting 1502 1.1 christos * into the given dns_message_t. 1503 1.1 christos */ 1504 1.16 christos static void 1505 1.5 christos tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target) { 1506 1.1 christos dns_rdata_t *rdata = NULL; 1507 1.1 christos dns_rdatalist_t *rdl = NULL; 1508 1.1 christos dns_rdataset_t *rds = NULL; 1509 1.1 christos dns_name_t *name = NULL; 1510 1.1 christos 1511 1.1 christos REQUIRE(target != NULL && *target == NULL); 1512 1.1 christos 1513 1.16 christos dns_message_gettemprdata(msg, &rdata); 1514 1.1 christos dns_rdata_init(rdata); 1515 1.1 christos dns_rdata_clone(&tuple->rdata, rdata); 1516 1.1 christos 1517 1.16 christos dns_message_gettemprdatalist(msg, &rdl); 1518 1.1 christos dns_rdatalist_init(rdl); 1519 1.1 christos rdl->type = tuple->rdata.type; 1520 1.1 christos rdl->rdclass = tuple->rdata.rdclass; 1521 1.1 christos rdl->ttl = tuple->ttl; 1522 1.1 christos ISC_LIST_APPEND(rdl->rdata, rdata, link); 1523 1.1 christos 1524 1.16 christos dns_message_gettemprdataset(msg, &rds); 1525 1.16 christos dns_rdatalist_tordataset(rdl, rds); 1526 1.1 christos 1527 1.16 christos dns_message_gettempname(msg, &name); 1528 1.1 christos dns_name_clone(&tuple->name, name); 1529 1.1 christos ISC_LIST_APPEND(name->list, rds, link); 1530 1.1 christos 1531 1.1 christos *target = name; 1532 1.16 christos } 1533 1.1 christos 1534 1.16 christos static const char * 1535 1.16 christos request_type(dns_xfrin_t *xfr) { 1536 1.16 christos switch (xfr->reqtype) { 1537 1.16 christos case dns_rdatatype_soa: 1538 1.16 christos return "SOA"; 1539 1.16 christos case dns_rdatatype_axfr: 1540 1.16 christos return "AXFR"; 1541 1.16 christos case dns_rdatatype_ixfr: 1542 1.16 christos return "IXFR"; 1543 1.16 christos default: 1544 1.16 christos ISC_UNREACHABLE(); 1545 1.16 christos } 1546 1.16 christos } 1547 1.1 christos 1548 1.16 christos static isc_result_t 1549 1.16 christos add_opt(dns_message_t *message, uint16_t udpsize, bool reqnsid, 1550 1.16 christos bool reqexpire) { 1551 1.16 christos isc_result_t result; 1552 1.16 christos dns_rdataset_t *rdataset = NULL; 1553 1.16 christos dns_ednsopt_t ednsopts[DNS_EDNSOPTIONS]; 1554 1.16 christos int count = 0; 1555 1.16 christos 1556 1.16 christos /* Set EDNS options if applicable. */ 1557 1.16 christos if (reqnsid) { 1558 1.16 christos INSIST(count < DNS_EDNSOPTIONS); 1559 1.16 christos ednsopts[count].code = DNS_OPT_NSID; 1560 1.16 christos ednsopts[count].length = 0; 1561 1.16 christos ednsopts[count].value = NULL; 1562 1.16 christos count++; 1563 1.16 christos } 1564 1.16 christos if (reqexpire) { 1565 1.16 christos INSIST(count < DNS_EDNSOPTIONS); 1566 1.16 christos ednsopts[count].code = DNS_OPT_EXPIRE; 1567 1.16 christos ednsopts[count].length = 0; 1568 1.16 christos ednsopts[count].value = NULL; 1569 1.16 christos count++; 1570 1.1 christos } 1571 1.16 christos result = dns_message_buildopt(message, &rdataset, 0, udpsize, 0, 1572 1.16 christos ednsopts, count); 1573 1.16 christos if (result != ISC_R_SUCCESS) { 1574 1.16 christos return result; 1575 1.5 christos } 1576 1.1 christos 1577 1.16 christos return dns_message_setopt(message, rdataset); 1578 1.1 christos } 1579 1.1 christos 1580 1.1 christos /* 1581 1.1 christos * Build an *XFR request and send its length prefix. 1582 1.1 christos */ 1583 1.1 christos static isc_result_t 1584 1.16 christos xfrin_send_request(dns_xfrin_t *xfr) { 1585 1.1 christos isc_result_t result; 1586 1.1 christos isc_region_t region; 1587 1.1 christos dns_rdataset_t *qrdataset = NULL; 1588 1.1 christos dns_message_t *msg = NULL; 1589 1.1 christos dns_difftuple_t *soatuple = NULL; 1590 1.1 christos dns_name_t *qname = NULL; 1591 1.1 christos dns_dbversion_t *ver = NULL; 1592 1.1 christos dns_name_t *msgsoaname = NULL; 1593 1.16 christos bool edns = xfr->edns; 1594 1.16 christos bool reqnsid = xfr->view->requestnsid; 1595 1.16 christos bool reqexpire = dns_zone_getrequestexpire(xfr->zone); 1596 1.16 christos uint16_t udpsize = dns_view_getudpsize(xfr->view); 1597 1.16 christos 1598 1.16 christos LIBDNS_XFRIN_RECV_SEND_REQUEST(xfr, xfr->info); 1599 1.1 christos 1600 1.1 christos /* Create the request message */ 1601 1.16 christos dns_message_create(xfr->mctx, NULL, NULL, DNS_MESSAGE_INTENTRENDER, 1602 1.16 christos &msg); 1603 1.1 christos CHECK(dns_message_settsigkey(msg, xfr->tsigkey)); 1604 1.1 christos 1605 1.1 christos /* Create a name for the question section. */ 1606 1.16 christos dns_message_gettempname(msg, &qname); 1607 1.1 christos dns_name_clone(&xfr->name, qname); 1608 1.1 christos 1609 1.1 christos /* Formulate the question and attach it to the question name. */ 1610 1.16 christos dns_message_gettemprdataset(msg, &qrdataset); 1611 1.1 christos dns_rdataset_makequestion(qrdataset, xfr->rdclass, xfr->reqtype); 1612 1.1 christos ISC_LIST_APPEND(qname->list, qrdataset, link); 1613 1.1 christos qrdataset = NULL; 1614 1.1 christos 1615 1.1 christos dns_message_addname(msg, qname, DNS_SECTION_QUESTION); 1616 1.1 christos qname = NULL; 1617 1.1 christos 1618 1.1 christos if (xfr->reqtype == dns_rdatatype_ixfr) { 1619 1.1 christos /* Get the SOA and add it to the authority section. */ 1620 1.1 christos dns_db_currentversion(xfr->db, &ver); 1621 1.1 christos CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx, 1622 1.1 christos DNS_DIFFOP_EXISTS, &soatuple)); 1623 1.1 christos xfr->ixfr.request_serial = dns_soa_getserial(&soatuple->rdata); 1624 1.1 christos xfr->ixfr.current_serial = xfr->ixfr.request_serial; 1625 1.1 christos xfrin_log(xfr, ISC_LOG_DEBUG(3), 1626 1.1 christos "requesting IXFR for serial %u", 1627 1.1 christos xfr->ixfr.request_serial); 1628 1.1 christos 1629 1.16 christos tuple2msgname(soatuple, msg, &msgsoaname); 1630 1.1 christos dns_message_addname(msg, msgsoaname, DNS_SECTION_AUTHORITY); 1631 1.5 christos } else if (xfr->reqtype == dns_rdatatype_soa) { 1632 1.1 christos CHECK(dns_db_getsoaserial(xfr->db, NULL, 1633 1.1 christos &xfr->ixfr.request_serial)); 1634 1.5 christos } 1635 1.1 christos 1636 1.16 christos if (edns && xfr->view->peers != NULL) { 1637 1.16 christos dns_peer_t *peer = NULL; 1638 1.16 christos isc_netaddr_t primaryip; 1639 1.16 christos isc_netaddr_fromsockaddr(&primaryip, &xfr->primaryaddr); 1640 1.16 christos result = dns_peerlist_peerbyaddr(xfr->view->peers, &primaryip, 1641 1.16 christos &peer); 1642 1.16 christos if (result == ISC_R_SUCCESS) { 1643 1.16 christos (void)dns_peer_getsupportedns(peer, &edns); 1644 1.16 christos (void)dns_peer_getudpsize(peer, &udpsize); 1645 1.16 christos (void)dns_peer_getrequestnsid(peer, &reqnsid); 1646 1.16 christos (void)dns_peer_getrequestexpire(peer, &reqexpire); 1647 1.16 christos } 1648 1.16 christos } 1649 1.16 christos 1650 1.16 christos if (edns) { 1651 1.16 christos CHECK(add_opt(msg, udpsize, reqnsid, reqexpire)); 1652 1.16 christos } 1653 1.16 christos 1654 1.16 christos atomic_store_relaxed(&xfr->nmsg, 0); 1655 1.16 christos atomic_store_relaxed(&xfr->nrecs, 0); 1656 1.17 christos ISC_XFRIN_STORE(&xfr->nbytes, 0); 1657 1.17 christos ISC_XFRIN_STORE(&xfr->start, isc_time_now()); 1658 1.16 christos 1659 1.18 christos xfr->nbytes_saved = 0; 1660 1.18 christos 1661 1.1 christos msg->id = xfr->id; 1662 1.5 christos if (xfr->tsigctx != NULL) { 1663 1.1 christos dst_context_destroy(&xfr->tsigctx); 1664 1.5 christos } 1665 1.1 christos 1666 1.1 christos CHECK(render(msg, xfr->mctx, &xfr->qbuffer)); 1667 1.1 christos 1668 1.1 christos /* 1669 1.1 christos * Free the last tsig, if there is one. 1670 1.1 christos */ 1671 1.5 christos if (xfr->lasttsig != NULL) { 1672 1.1 christos isc_buffer_free(&xfr->lasttsig); 1673 1.5 christos } 1674 1.1 christos 1675 1.1 christos /* 1676 1.1 christos * Save the query TSIG and don't let message_destroy free it. 1677 1.1 christos */ 1678 1.1 christos CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig)); 1679 1.1 christos 1680 1.1 christos isc_buffer_usedregion(&xfr->qbuffer, ®ion); 1681 1.1 christos INSIST(region.length <= 65535); 1682 1.1 christos 1683 1.16 christos dns_xfrin_ref(xfr); 1684 1.16 christos dns_dispatch_send(xfr->dispentry, ®ion); 1685 1.16 christos xfrin_log(xfr, ISC_LOG_DEBUG(3), "sending %s request, QID %d", 1686 1.16 christos request_type(xfr), xfr->id); 1687 1.1 christos 1688 1.20 christos cleanup: 1689 1.16 christos dns_message_detach(&msg); 1690 1.5 christos if (soatuple != NULL) { 1691 1.1 christos dns_difftuple_free(&soatuple); 1692 1.5 christos } 1693 1.5 christos if (ver != NULL) { 1694 1.3 christos dns_db_closeversion(xfr->db, &ver, false); 1695 1.5 christos } 1696 1.14 christos 1697 1.16 christos return result; 1698 1.1 christos } 1699 1.1 christos 1700 1.1 christos static void 1701 1.16 christos xfrin_send_done(isc_result_t result, isc_region_t *region, void *arg) { 1702 1.16 christos dns_xfrin_t *xfr = (dns_xfrin_t *)arg; 1703 1.16 christos 1704 1.16 christos UNUSED(region); 1705 1.1 christos 1706 1.1 christos REQUIRE(VALID_XFRIN(xfr)); 1707 1.1 christos 1708 1.14 christos if (atomic_load(&xfr->shuttingdown)) { 1709 1.14 christos result = ISC_R_SHUTTINGDOWN; 1710 1.14 christos } 1711 1.1 christos 1712 1.16 christos LIBDNS_XFRIN_SENT(xfr, xfr->info, result); 1713 1.16 christos 1714 1.14 christos CHECK(result); 1715 1.1 christos 1716 1.1 christos xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request data"); 1717 1.1 christos 1718 1.20 christos cleanup: 1719 1.5 christos if (result != ISC_R_SUCCESS) { 1720 1.1 christos xfrin_fail(xfr, result, "failed sending request data"); 1721 1.5 christos } 1722 1.14 christos 1723 1.16 christos dns_xfrin_detach(&xfr); 1724 1.16 christos } 1725 1.16 christos 1726 1.16 christos static void 1727 1.16 christos get_edns_expire(dns_xfrin_t *xfr, dns_message_t *msg) { 1728 1.16 christos isc_result_t result; 1729 1.16 christos dns_rdata_t rdata = DNS_RDATA_INIT; 1730 1.16 christos isc_buffer_t optbuf; 1731 1.16 christos uint16_t optcode; 1732 1.16 christos uint16_t optlen; 1733 1.16 christos 1734 1.16 christos result = dns_rdataset_first(msg->opt); 1735 1.16 christos if (result == ISC_R_SUCCESS) { 1736 1.16 christos dns_rdataset_current(msg->opt, &rdata); 1737 1.16 christos isc_buffer_init(&optbuf, rdata.data, rdata.length); 1738 1.16 christos isc_buffer_add(&optbuf, rdata.length); 1739 1.16 christos while (isc_buffer_remaininglength(&optbuf) >= 4) { 1740 1.16 christos optcode = isc_buffer_getuint16(&optbuf); 1741 1.16 christos optlen = isc_buffer_getuint16(&optbuf); 1742 1.16 christos /* 1743 1.16 christos * A EDNS EXPIRE response has a length of 4. 1744 1.16 christos */ 1745 1.16 christos if (optcode != DNS_OPT_EXPIRE || optlen != 4) { 1746 1.16 christos isc_buffer_forward(&optbuf, optlen); 1747 1.16 christos continue; 1748 1.16 christos } 1749 1.16 christos xfr->expireopt = isc_buffer_getuint32(&optbuf); 1750 1.16 christos xfr->expireoptset = true; 1751 1.16 christos dns_zone_log(xfr->zone, ISC_LOG_DEBUG(1), 1752 1.16 christos "got EDNS EXPIRE of %u", xfr->expireopt); 1753 1.16 christos break; 1754 1.16 christos } 1755 1.16 christos } 1756 1.16 christos } 1757 1.16 christos 1758 1.16 christos static void 1759 1.16 christos xfrin_end(dns_xfrin_t *xfr, isc_result_t result) { 1760 1.16 christos /* Inform the caller. */ 1761 1.16 christos if (xfr->done != NULL) { 1762 1.16 christos LIBDNS_XFRIN_DONE_CALLBACK_BEGIN(xfr, xfr->info, result); 1763 1.16 christos (xfr->done)(xfr->zone, 1764 1.16 christos xfr->expireoptset ? &xfr->expireopt : NULL, result); 1765 1.16 christos xfr->done = NULL; 1766 1.16 christos LIBDNS_XFRIN_DONE_CALLBACK_END(xfr, xfr->info, result); 1767 1.16 christos } 1768 1.16 christos 1769 1.16 christos atomic_store(&xfr->shuttingdown, true); 1770 1.16 christos 1771 1.16 christos if (xfr->max_time_timer != NULL) { 1772 1.16 christos isc_timer_stop(xfr->max_time_timer); 1773 1.16 christos isc_timer_destroy(&xfr->max_time_timer); 1774 1.16 christos } 1775 1.16 christos if (xfr->max_idle_timer != NULL) { 1776 1.16 christos isc_timer_stop(xfr->max_idle_timer); 1777 1.16 christos isc_timer_destroy(&xfr->max_idle_timer); 1778 1.16 christos } 1779 1.18 christos if (xfr->min_rate_timer != NULL) { 1780 1.18 christos isc_timer_stop(xfr->min_rate_timer); 1781 1.18 christos isc_timer_destroy(&xfr->min_rate_timer); 1782 1.18 christos } 1783 1.16 christos 1784 1.16 christos if (xfr->shutdown_result == ISC_R_UNSET) { 1785 1.16 christos xfr->shutdown_result = result; 1786 1.16 christos } 1787 1.1 christos } 1788 1.1 christos 1789 1.1 christos static void 1790 1.16 christos xfrin_recv_done(isc_result_t result, isc_region_t *region, void *arg) { 1791 1.16 christos dns_xfrin_t *xfr = (dns_xfrin_t *)arg; 1792 1.1 christos dns_message_t *msg = NULL; 1793 1.14 christos dns_name_t *name = NULL; 1794 1.1 christos const dns_name_t *tsigowner = NULL; 1795 1.14 christos isc_buffer_t buffer; 1796 1.1 christos 1797 1.1 christos REQUIRE(VALID_XFRIN(xfr)); 1798 1.1 christos 1799 1.14 christos if (atomic_load(&xfr->shuttingdown)) { 1800 1.14 christos result = ISC_R_SHUTTINGDOWN; 1801 1.1 christos } 1802 1.1 christos 1803 1.14 christos /* Stop the idle timer */ 1804 1.16 christos isc_timer_stop(xfr->max_idle_timer); 1805 1.16 christos 1806 1.16 christos LIBDNS_XFRIN_RECV_START(xfr, xfr->info, result); 1807 1.1 christos 1808 1.14 christos CHECK(result); 1809 1.1 christos 1810 1.14 christos xfrin_log(xfr, ISC_LOG_DEBUG(7), "received %u bytes", region->length); 1811 1.1 christos 1812 1.16 christos dns_message_create(xfr->mctx, NULL, NULL, DNS_MESSAGE_INTENTPARSE, 1813 1.16 christos &msg); 1814 1.1 christos 1815 1.1 christos CHECK(dns_message_settsigkey(msg, xfr->tsigkey)); 1816 1.16 christos dns_message_setquerytsig(msg, xfr->lasttsig); 1817 1.1 christos 1818 1.1 christos msg->tsigctx = xfr->tsigctx; 1819 1.1 christos xfr->tsigctx = NULL; 1820 1.1 christos 1821 1.1 christos dns_message_setclass(msg, xfr->rdclass); 1822 1.1 christos 1823 1.16 christos msg->tcp_continuation = (atomic_load_relaxed(&xfr->nmsg) > 0) ? 1 : 0; 1824 1.1 christos 1825 1.14 christos isc_buffer_init(&buffer, region->base, region->length); 1826 1.14 christos isc_buffer_add(&buffer, region->length); 1827 1.14 christos 1828 1.14 christos result = dns_message_parse(msg, &buffer, 1829 1.1 christos DNS_MESSAGEPARSE_PRESERVEORDER); 1830 1.5 christos if (result == ISC_R_SUCCESS) { 1831 1.16 christos dns_message_logpacket( 1832 1.16 christos msg, "received message from", &xfr->primaryaddr, 1833 1.16 christos DNS_LOGCATEGORY_XFER_IN, DNS_LOGMODULE_XFER_IN, 1834 1.16 christos ISC_LOG_DEBUG(10), xfr->mctx); 1835 1.5 christos } else { 1836 1.1 christos xfrin_log(xfr, ISC_LOG_DEBUG(10), "dns_message_parse: %s", 1837 1.14 christos isc_result_totext(result)); 1838 1.5 christos } 1839 1.1 christos 1840 1.16 christos LIBDNS_XFRIN_RECV_PARSED(xfr, xfr->info, result); 1841 1.16 christos 1842 1.1 christos if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror || 1843 1.16 christos msg->opcode != dns_opcode_query || msg->rdclass != xfr->rdclass) 1844 1.5 christos { 1845 1.16 christos if (result == ISC_R_SUCCESS && 1846 1.16 christos msg->rcode == dns_rcode_formerr && xfr->edns && 1847 1.16 christos (atomic_load(&xfr->state) == XFRST_SOAQUERY || 1848 1.16 christos atomic_load(&xfr->state) == XFRST_ZONEXFRREQUEST)) 1849 1.16 christos { 1850 1.16 christos xfr->edns = false; 1851 1.16 christos dns_message_detach(&msg); 1852 1.16 christos xfrin_reset(xfr); 1853 1.16 christos goto try_again; 1854 1.16 christos } else if (result == ISC_R_SUCCESS && 1855 1.16 christos msg->rcode != dns_rcode_noerror) 1856 1.5 christos { 1857 1.14 christos result = dns_result_fromrcode(msg->rcode); 1858 1.5 christos } else if (result == ISC_R_SUCCESS && 1859 1.12 christos msg->opcode != dns_opcode_query) 1860 1.12 christos { 1861 1.1 christos result = DNS_R_UNEXPECTEDOPCODE; 1862 1.5 christos } else if (result == ISC_R_SUCCESS && 1863 1.12 christos msg->rdclass != xfr->rdclass) 1864 1.12 christos { 1865 1.1 christos result = DNS_R_BADCLASS; 1866 1.5 christos } else if (result == ISC_R_SUCCESS || result == DNS_R_NOERROR) { 1867 1.1 christos result = DNS_R_UNEXPECTEDID; 1868 1.5 christos } 1869 1.14 christos 1870 1.1 christos if (xfr->reqtype == dns_rdatatype_axfr || 1871 1.12 christos xfr->reqtype == dns_rdatatype_soa) 1872 1.12 christos { 1873 1.20 christos goto cleanup; 1874 1.5 christos } 1875 1.14 christos 1876 1.1 christos xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR", 1877 1.5 christos isc_result_totext(result)); 1878 1.5 christos try_axfr: 1879 1.16 christos LIBDNS_XFRIN_RECV_TRY_AXFR(xfr, xfr->info, result); 1880 1.7 christos dns_message_detach(&msg); 1881 1.1 christos xfrin_reset(xfr); 1882 1.1 christos xfr->reqtype = dns_rdatatype_soa; 1883 1.16 christos atomic_store(&xfr->state, XFRST_SOAQUERY); 1884 1.16 christos try_again: 1885 1.14 christos result = xfrin_start(xfr); 1886 1.14 christos if (result != ISC_R_SUCCESS) { 1887 1.14 christos xfrin_fail(xfr, result, "failed setting up socket"); 1888 1.14 christos } 1889 1.16 christos dns_xfrin_detach(&xfr); 1890 1.1 christos return; 1891 1.14 christos } 1892 1.14 christos 1893 1.14 christos /* 1894 1.14 christos * The question section should exist for SOA and in the first 1895 1.14 christos * message of a AXFR or IXFR response. The question section 1896 1.14 christos * may exist in the 2nd and subsequent messages in a AXFR or 1897 1.14 christos * IXFR response. If the question section exists it should 1898 1.14 christos * match the question that was sent. 1899 1.14 christos */ 1900 1.14 christos if (msg->counts[DNS_SECTION_QUESTION] > 1) { 1901 1.14 christos xfrin_log(xfr, ISC_LOG_NOTICE, "too many questions (%u)", 1902 1.14 christos msg->counts[DNS_SECTION_QUESTION]); 1903 1.20 christos CHECK(DNS_R_FORMERR); 1904 1.14 christos } 1905 1.14 christos 1906 1.16 christos if ((atomic_load(&xfr->state) == XFRST_SOAQUERY || 1907 1.16 christos atomic_load(&xfr->state) == XFRST_ZONEXFRREQUEST) && 1908 1.14 christos msg->counts[DNS_SECTION_QUESTION] != 1) 1909 1.14 christos { 1910 1.14 christos xfrin_log(xfr, ISC_LOG_NOTICE, "missing question section"); 1911 1.20 christos CHECK(DNS_R_FORMERR); 1912 1.14 christos } 1913 1.14 christos 1914 1.14 christos for (result = dns_message_firstname(msg, DNS_SECTION_QUESTION); 1915 1.14 christos result == ISC_R_SUCCESS; 1916 1.14 christos result = dns_message_nextname(msg, DNS_SECTION_QUESTION)) 1917 1.14 christos { 1918 1.14 christos dns_rdataset_t *rds = NULL; 1919 1.14 christos 1920 1.16 christos LIBDNS_XFRIN_RECV_QUESTION(xfr, xfr->info, msg); 1921 1.16 christos 1922 1.14 christos name = NULL; 1923 1.14 christos dns_message_currentname(msg, DNS_SECTION_QUESTION, &name); 1924 1.14 christos if (!dns_name_equal(name, &xfr->name)) { 1925 1.14 christos xfrin_log(xfr, ISC_LOG_NOTICE, 1926 1.14 christos "question name mismatch"); 1927 1.20 christos CHECK(DNS_R_FORMERR); 1928 1.14 christos } 1929 1.14 christos rds = ISC_LIST_HEAD(name->list); 1930 1.14 christos INSIST(rds != NULL); 1931 1.14 christos if (rds->type != xfr->reqtype) { 1932 1.14 christos xfrin_log(xfr, ISC_LOG_NOTICE, 1933 1.14 christos "question type mismatch"); 1934 1.20 christos CHECK(DNS_R_FORMERR); 1935 1.14 christos } 1936 1.14 christos if (rds->rdclass != xfr->rdclass) { 1937 1.14 christos xfrin_log(xfr, ISC_LOG_NOTICE, 1938 1.14 christos "question class mismatch"); 1939 1.20 christos CHECK(DNS_R_FORMERR); 1940 1.14 christos } 1941 1.14 christos } 1942 1.14 christos if (result != ISC_R_NOMORE) { 1943 1.20 christos goto cleanup; 1944 1.1 christos } 1945 1.1 christos 1946 1.1 christos /* 1947 1.1 christos * Does the server know about IXFR? If it doesn't we will get 1948 1.1 christos * a message with a empty answer section or a potentially a CNAME / 1949 1.1 christos * DNAME, the later is handled by xfr_rr() which will return FORMERR 1950 1.1 christos * if the first RR in the answer section is not a SOA record. 1951 1.1 christos */ 1952 1.1 christos if (xfr->reqtype == dns_rdatatype_ixfr && 1953 1.16 christos atomic_load(&xfr->state) == XFRST_ZONEXFRREQUEST && 1954 1.5 christos msg->counts[DNS_SECTION_ANSWER] == 0) 1955 1.5 christos { 1956 1.1 christos xfrin_log(xfr, ISC_LOG_DEBUG(3), 1957 1.1 christos "empty answer section, retrying with AXFR"); 1958 1.1 christos goto try_axfr; 1959 1.1 christos } 1960 1.1 christos 1961 1.1 christos if (xfr->reqtype == dns_rdatatype_soa && 1962 1.12 christos (msg->flags & DNS_MESSAGEFLAG_AA) == 0) 1963 1.12 christos { 1964 1.20 christos CHECK(DNS_R_NOTAUTHORITATIVE); 1965 1.1 christos } 1966 1.1 christos 1967 1.16 christos result = dns_message_checksig(msg, xfr->view); 1968 1.1 christos if (result != ISC_R_SUCCESS) { 1969 1.1 christos xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s", 1970 1.5 christos isc_result_totext(result)); 1971 1.20 christos goto cleanup; 1972 1.1 christos } 1973 1.1 christos 1974 1.1 christos for (result = dns_message_firstname(msg, DNS_SECTION_ANSWER); 1975 1.1 christos result == ISC_R_SUCCESS; 1976 1.1 christos result = dns_message_nextname(msg, DNS_SECTION_ANSWER)) 1977 1.1 christos { 1978 1.14 christos dns_rdataset_t *rds = NULL; 1979 1.1 christos 1980 1.16 christos LIBDNS_XFRIN_RECV_ANSWER(xfr, xfr->info, msg); 1981 1.16 christos 1982 1.1 christos name = NULL; 1983 1.1 christos dns_message_currentname(msg, DNS_SECTION_ANSWER, &name); 1984 1.5 christos for (rds = ISC_LIST_HEAD(name->list); rds != NULL; 1985 1.1 christos rds = ISC_LIST_NEXT(rds, link)) 1986 1.1 christos { 1987 1.1 christos for (result = dns_rdataset_first(rds); 1988 1.1 christos result == ISC_R_SUCCESS; 1989 1.1 christos result = dns_rdataset_next(rds)) 1990 1.1 christos { 1991 1.1 christos dns_rdata_t rdata = DNS_RDATA_INIT; 1992 1.1 christos dns_rdataset_current(rds, &rdata); 1993 1.1 christos CHECK(xfr_rr(xfr, name, rds->ttl, &rdata)); 1994 1.1 christos } 1995 1.1 christos } 1996 1.1 christos } 1997 1.16 christos if (result == ISC_R_NOMORE) { 1998 1.16 christos result = ISC_R_SUCCESS; 1999 1.5 christos } 2000 1.16 christos CHECK(result); 2001 1.1 christos 2002 1.1 christos if (dns_message_gettsig(msg, &tsigowner) != NULL) { 2003 1.1 christos /* 2004 1.1 christos * Reset the counter. 2005 1.1 christos */ 2006 1.1 christos xfr->sincetsig = 0; 2007 1.1 christos 2008 1.1 christos /* 2009 1.1 christos * Free the last tsig, if there is one. 2010 1.1 christos */ 2011 1.5 christos if (xfr->lasttsig != NULL) { 2012 1.1 christos isc_buffer_free(&xfr->lasttsig); 2013 1.5 christos } 2014 1.1 christos 2015 1.1 christos /* 2016 1.1 christos * Update the last tsig pointer. 2017 1.1 christos */ 2018 1.5 christos CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig)); 2019 1.1 christos } else if (dns_message_gettsigkey(msg) != NULL) { 2020 1.1 christos xfr->sincetsig++; 2021 1.16 christos if (xfr->sincetsig > 100 || 2022 1.16 christos atomic_load_relaxed(&xfr->nmsg) == 0 || 2023 1.16 christos atomic_load(&xfr->state) == XFRST_AXFR_END || 2024 1.16 christos atomic_load(&xfr->state) == XFRST_IXFR_END) 2025 1.1 christos { 2026 1.20 christos CHECK(DNS_R_EXPECTEDTSIG); 2027 1.1 christos } 2028 1.1 christos } 2029 1.1 christos 2030 1.1 christos /* 2031 1.16 christos * Update the number of messages and bytes received. 2032 1.1 christos */ 2033 1.16 christos atomic_fetch_add_relaxed(&xfr->nmsg, 1); 2034 1.17 christos ISC_XFRIN_ADD(&xfr->nbytes, buffer.used); 2035 1.1 christos 2036 1.1 christos /* 2037 1.1 christos * Take the context back. 2038 1.1 christos */ 2039 1.1 christos INSIST(xfr->tsigctx == NULL); 2040 1.1 christos xfr->tsigctx = msg->tsigctx; 2041 1.1 christos msg->tsigctx = NULL; 2042 1.1 christos 2043 1.16 christos if (!xfr->expireoptset && msg->opt != NULL) { 2044 1.16 christos get_edns_expire(xfr, msg); 2045 1.16 christos } 2046 1.16 christos 2047 1.16 christos switch (atomic_load(&xfr->state)) { 2048 1.1 christos case XFRST_GOTSOA: 2049 1.1 christos xfr->reqtype = dns_rdatatype_axfr; 2050 1.16 christos atomic_store(&xfr->state, XFRST_ZONEXFRREQUEST); 2051 1.16 christos CHECK(xfrin_start(xfr)); 2052 1.1 christos break; 2053 1.1 christos case XFRST_AXFR_END: 2054 1.1 christos case XFRST_IXFR_END: 2055 1.16 christos /* We are at the end, cancel the timers and IO */ 2056 1.18 christos isc_timer_stop(xfr->min_rate_timer); 2057 1.16 christos isc_timer_stop(xfr->max_idle_timer); 2058 1.16 christos isc_timer_stop(xfr->max_time_timer); 2059 1.16 christos xfrin_cancelio(xfr); 2060 1.1 christos break; 2061 1.1 christos default: 2062 1.1 christos /* 2063 1.1 christos * Read the next message. 2064 1.1 christos */ 2065 1.14 christos dns_message_detach(&msg); 2066 1.20 christos CHECK(dns_dispatch_getnext(xfr->dispentry)); 2067 1.16 christos 2068 1.14 christos isc_interval_t interval; 2069 1.14 christos isc_interval_set(&interval, dns_zone_getidlein(xfr->zone), 0); 2070 1.16 christos isc_timer_start(xfr->max_idle_timer, isc_timertype_once, 2071 1.16 christos &interval); 2072 1.16 christos 2073 1.16 christos LIBDNS_XFRIN_READ(xfr, xfr->info, result); 2074 1.14 christos return; 2075 1.1 christos } 2076 1.1 christos 2077 1.20 christos cleanup: 2078 1.5 christos if (result != ISC_R_SUCCESS) { 2079 1.1 christos xfrin_fail(xfr, result, "failed while receiving responses"); 2080 1.5 christos } 2081 1.1 christos 2082 1.14 christos if (msg != NULL) { 2083 1.14 christos dns_message_detach(&msg); 2084 1.14 christos } 2085 1.16 christos dns_xfrin_detach(&xfr); 2086 1.16 christos LIBDNS_XFRIN_RECV_DONE(xfr, xfr->info, result); 2087 1.1 christos } 2088 1.1 christos 2089 1.1 christos static void 2090 1.16 christos xfrin_destroy(dns_xfrin_t *xfr) { 2091 1.16 christos uint64_t msecs, persec; 2092 1.16 christos isc_time_t now = isc_time_now(); 2093 1.16 christos char expireopt[sizeof("4000000000")] = { 0 }; 2094 1.16 christos const char *sep = ""; 2095 1.1 christos 2096 1.1 christos REQUIRE(VALID_XFRIN(xfr)); 2097 1.1 christos 2098 1.14 christos /* Safe-guards */ 2099 1.14 christos REQUIRE(atomic_load(&xfr->shuttingdown)); 2100 1.1 christos 2101 1.14 christos INSIST(xfr->shutdown_result != ISC_R_UNSET); 2102 1.1 christos 2103 1.14 christos /* 2104 1.14 christos * If we're called through dns_xfrin_detach() and are not 2105 1.1 christos * shutting down, we can't know what the transfer status is as 2106 1.1 christos * we are only called when the last reference is lost. 2107 1.1 christos */ 2108 1.16 christos xfrin_log(xfr, ISC_LOG_INFO, "Transfer status: %s", 2109 1.16 christos isc_result_totext(xfr->shutdown_result)); 2110 1.1 christos 2111 1.1 christos /* 2112 1.1 christos * Calculate the length of time the transfer took, 2113 1.1 christos * and print a log message with the bytes and rate. 2114 1.1 christos */ 2115 1.17 christos isc_time_t start = ISC_XFRIN_LOAD(&xfr->start, isc_time_t); 2116 1.16 christos msecs = isc_time_microdiff(&now, &start) / 1000; 2117 1.5 christos if (msecs == 0) { 2118 1.1 christos msecs = 1; 2119 1.5 christos } 2120 1.17 christos persec = (ISC_XFRIN_LOAD(&xfr->nbytes, uint64_t) * 1000) / msecs; 2121 1.16 christos 2122 1.16 christos if (xfr->expireoptset) { 2123 1.16 christos sep = ", expire option "; 2124 1.16 christos snprintf(expireopt, sizeof(expireopt), "%u", xfr->expireopt); 2125 1.16 christos } 2126 1.16 christos 2127 1.1 christos xfrin_log(xfr, ISC_LOG_INFO, 2128 1.1 christos "Transfer completed: %d messages, %d records, " 2129 1.3 christos "%" PRIu64 " bytes, " 2130 1.16 christos "%u.%03u secs (%u bytes/sec) (serial %" PRIuFAST32 "%s%s)", 2131 1.16 christos atomic_load_relaxed(&xfr->nmsg), 2132 1.16 christos atomic_load_relaxed(&xfr->nrecs), 2133 1.17 christos ISC_XFRIN_LOAD(&xfr->nbytes, uint64_t), 2134 1.5 christos (unsigned int)(msecs / 1000), (unsigned int)(msecs % 1000), 2135 1.16 christos (unsigned int)persec, atomic_load_relaxed(&xfr->end_serial), 2136 1.16 christos sep, expireopt); 2137 1.1 christos 2138 1.16 christos /* Cleanup unprocessed IXFR data */ 2139 1.16 christos struct cds_wfcq_node *node, *next; 2140 1.16 christos __cds_wfcq_for_each_blocking_safe(&xfr->diff_head, &xfr->diff_tail, 2141 1.16 christos node, next) { 2142 1.16 christos ixfr_apply_data_t *data = 2143 1.16 christos caa_container_of(node, ixfr_apply_data_t, wfcq_node); 2144 1.16 christos /* We need to clear and free all data chunks */ 2145 1.16 christos dns_diff_clear(&data->diff); 2146 1.16 christos isc_mem_put(xfr->mctx, data, sizeof(*data)); 2147 1.5 christos } 2148 1.16 christos 2149 1.16 christos /* Cleanup unprocessed AXFR data */ 2150 1.16 christos dns_diff_clear(&xfr->diff); 2151 1.16 christos 2152 1.16 christos xfrin_cancelio(xfr); 2153 1.1 christos 2154 1.14 christos if (xfr->transport != NULL) { 2155 1.14 christos dns_transport_detach(&xfr->transport); 2156 1.5 christos } 2157 1.1 christos 2158 1.5 christos if (xfr->tsigkey != NULL) { 2159 1.1 christos dns_tsigkey_detach(&xfr->tsigkey); 2160 1.5 christos } 2161 1.1 christos 2162 1.5 christos if (xfr->lasttsig != NULL) { 2163 1.1 christos isc_buffer_free(&xfr->lasttsig); 2164 1.5 christos } 2165 1.1 christos 2166 1.5 christos if (xfr->ixfr.journal != NULL) { 2167 1.1 christos dns_journal_destroy(&xfr->ixfr.journal); 2168 1.5 christos } 2169 1.1 christos 2170 1.5 christos if (xfr->axfr.add_private != NULL) { 2171 1.1 christos (void)dns_db_endload(xfr->db, &xfr->axfr); 2172 1.5 christos } 2173 1.1 christos 2174 1.5 christos if (xfr->tsigctx != NULL) { 2175 1.1 christos dst_context_destroy(&xfr->tsigctx); 2176 1.5 christos } 2177 1.1 christos 2178 1.16 christos if (xfr->name.attributes.dynamic) { 2179 1.1 christos dns_name_free(&xfr->name, xfr->mctx); 2180 1.5 christos } 2181 1.1 christos 2182 1.5 christos if (xfr->ver != NULL) { 2183 1.3 christos dns_db_closeversion(xfr->db, &xfr->ver, false); 2184 1.5 christos } 2185 1.1 christos 2186 1.5 christos if (xfr->db != NULL) { 2187 1.1 christos dns_db_detach(&xfr->db); 2188 1.5 christos } 2189 1.1 christos 2190 1.4 christos if (xfr->zone != NULL) { 2191 1.14 christos if (!xfr->zone_had_db && 2192 1.4 christos xfr->shutdown_result == ISC_R_SUCCESS && 2193 1.4 christos dns_zone_gettype(xfr->zone) == dns_zone_mirror) 2194 1.4 christos { 2195 1.4 christos dns_zone_log(xfr->zone, ISC_LOG_INFO, 2196 1.4 christos "mirror zone is now in use"); 2197 1.4 christos } 2198 1.4 christos xfrin_log(xfr, ISC_LOG_DEBUG(99), "freeing transfer context"); 2199 1.4 christos /* 2200 1.4 christos * xfr->zone must not be detached before xfrin_log() is called. 2201 1.4 christos */ 2202 1.1 christos dns_zone_idetach(&xfr->zone); 2203 1.4 christos } 2204 1.1 christos 2205 1.16 christos if (xfr->view != NULL) { 2206 1.16 christos dns_view_weakdetach(&xfr->view); 2207 1.16 christos } 2208 1.16 christos 2209 1.10 christos if (xfr->firstsoa_data != NULL) { 2210 1.10 christos isc_mem_free(xfr->mctx, xfr->firstsoa_data); 2211 1.10 christos } 2212 1.10 christos 2213 1.14 christos if (xfr->tlsctx_cache != NULL) { 2214 1.14 christos isc_tlsctx_cache_detach(&xfr->tlsctx_cache); 2215 1.14 christos } 2216 1.14 christos 2217 1.16 christos INSIST(xfr->max_time_timer == NULL); 2218 1.16 christos INSIST(xfr->max_idle_timer == NULL); 2219 1.18 christos INSIST(xfr->min_rate_timer == NULL); 2220 1.16 christos 2221 1.16 christos isc_loop_detach(&xfr->loop); 2222 1.14 christos 2223 1.1 christos isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr)); 2224 1.1 christos } 2225 1.1 christos 2226 1.1 christos /* 2227 1.1 christos * Log incoming zone transfer messages in a format like 2228 1.1 christos * transfer of <zone> from <address>: <message> 2229 1.1 christos */ 2230 1.16 christos 2231 1.1 christos static void 2232 1.16 christos xfrin_log(dns_xfrin_t *xfr, int level, const char *fmt, ...) { 2233 1.16 christos va_list ap; 2234 1.14 christos char primarytext[ISC_SOCKADDR_FORMATSIZE]; 2235 1.1 christos char msgtext[2048]; 2236 1.1 christos 2237 1.6 christos if (!isc_log_wouldlog(dns_lctx, level)) { 2238 1.1 christos return; 2239 1.5 christos } 2240 1.1 christos 2241 1.16 christos isc_sockaddr_format(&xfr->primaryaddr, primarytext, 2242 1.16 christos sizeof(primarytext)); 2243 1.1 christos va_start(ap, fmt); 2244 1.16 christos vsnprintf(msgtext, sizeof(msgtext), fmt, ap); 2245 1.1 christos va_end(ap); 2246 1.1 christos 2247 1.16 christos isc_log_write(dns_lctx, DNS_LOGCATEGORY_XFER_IN, DNS_LOGMODULE_XFER_IN, 2248 1.16 christos level, "%p: transfer of '%s' from %s: %s", xfr, xfr->info, 2249 1.16 christos primarytext, msgtext); 2250 1.1 christos } 2251