Coverage Report

Created: 2026-10-28 06:55

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