Coverage Report

Created: 2026-06-09 06:11

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