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