Coverage Report

Created: 2026-01-09 06:42

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