1 /*
2 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3 *
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 *
8 * See the COPYRIGHT file distributed with this work for additional
9 * information regarding copyright ownership.
10 */
11
12 #include <inttypes.h>
13 #include <stdbool.h>
14
15 #include <isc/formatcheck.h>
16 #include <isc/mem.h>
17 #include <isc/print.h>
18 #include <isc/stats.h>
19 #include <isc/timer.h>
20 #include <isc/util.h>
21
22 #include <dns/db.h>
23 #include <dns/dbiterator.h>
24 #include <dns/dlz.h>
25 #include <dns/fixedname.h>
26 #include <dns/journal.h>
27 #include <dns/message.h>
28 #include <dns/peer.h>
29 #include <dns/rdataclass.h>
30 #include <dns/rdatalist.h>
31 #include <dns/rdataset.h>
32 #include <dns/rdatasetiter.h>
33 #include <dns/result.h>
34 #include <dns/rriterator.h>
35 #include <dns/soa.h>
36 #include <dns/stats.h>
37 #include <dns/timer.h>
38 #include <dns/tsig.h>
39 #include <dns/view.h>
40 #include <dns/zone.h>
41 #include <dns/zt.h>
42
43 #include <ns/client.h>
44 #include <ns/log.h>
45 #include <ns/server.h>
46 #include <ns/stats.h>
47 #include <ns/xfrout.h>
48
49 /*! \file
50 * \brief
51 * Outgoing AXFR and IXFR.
52 */
53
54 /*
55 * TODO:
56 * - IXFR over UDP
57 */
58
59 #define XFROUT_COMMON_LOGARGS \
60 ns_lctx, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT
61
62 #define XFROUT_PROTOCOL_LOGARGS XFROUT_COMMON_LOGARGS, ISC_LOG_INFO
63
64 #define XFROUT_DEBUG_LOGARGS(n) XFROUT_COMMON_LOGARGS, ISC_LOG_DEBUG(n)
65
66 #define XFROUT_RR_LOGARGS XFROUT_COMMON_LOGARGS, XFROUT_RR_LOGLEVEL
67
68 #define XFROUT_RR_LOGLEVEL ISC_LOG_DEBUG(8)
69
70 /*%
71 * Fail unconditionally and log as a client error.
72 * The test against ISC_R_SUCCESS is there to keep the Solaris compiler
73 * from complaining about "end-of-loop code not reached".
74 */
75 #define FAILC(code, msg) \
76 do { \
77 result = (code); \
78 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
79 NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
80 "bad zone transfer request: %s (%s)", msg, \
81 isc_result_totext(code)); \
82 if (result != ISC_R_SUCCESS) \
83 goto failure; \
84 } while (0)
85
86 #define FAILQ(code, msg, question, rdclass) \
87 do { \
88 char _buf1[DNS_NAME_FORMATSIZE]; \
89 char _buf2[DNS_RDATACLASS_FORMATSIZE]; \
90 result = (code); \
91 dns_name_format(question, _buf1, sizeof(_buf1)); \
92 dns_rdataclass_format(rdclass, _buf2, sizeof(_buf2)); \
93 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, \
94 NS_LOGMODULE_XFER_OUT, ISC_LOG_INFO, \
95 "bad zone transfer request: '%s/%s': %s (%s)", \
96 _buf1, _buf2, msg, isc_result_totext(code)); \
97 if (result != ISC_R_SUCCESS) \
98 goto failure; \
99 } while (0)
100
101 #define CHECK(op) \
102 do { \
103 result = (op); \
104 if (result != ISC_R_SUCCESS) \
105 goto failure; \
106 } while (0)
107
108 /**************************************************************************/
109
110 static inline void
inc_stats(ns_client_t * client,dns_zone_t * zone,isc_statscounter_t counter)111 inc_stats(ns_client_t *client, dns_zone_t *zone, isc_statscounter_t counter) {
112 ns_stats_increment(client->sctx->nsstats, counter);
113 if (zone != NULL) {
114 isc_stats_t *zonestats = dns_zone_getrequeststats(zone);
115 if (zonestats != NULL) {
116 isc_stats_increment(zonestats, counter);
117 }
118 }
119 }
120
121 /**************************************************************************/
122
123 /*% Log an RR (for debugging) */
124
125 static void
log_rr(dns_name_t * name,dns_rdata_t * rdata,uint32_t ttl)126 log_rr(dns_name_t *name, dns_rdata_t *rdata, uint32_t ttl) {
127 isc_result_t result;
128 isc_buffer_t buf;
129 char mem[2000];
130 dns_rdatalist_t rdl;
131 dns_rdataset_t rds;
132 dns_rdata_t rd = DNS_RDATA_INIT;
133
134 dns_rdatalist_init(&rdl);
135 rdl.type = rdata->type;
136 rdl.rdclass = rdata->rdclass;
137 rdl.ttl = ttl;
138 if (rdata->type == dns_rdatatype_sig ||
139 rdata->type == dns_rdatatype_rrsig) {
140 rdl.covers = dns_rdata_covers(rdata);
141 } else {
142 rdl.covers = dns_rdatatype_none;
143 }
144 dns_rdataset_init(&rds);
145 dns_rdata_init(&rd);
146 dns_rdata_clone(rdata, &rd);
147 ISC_LIST_APPEND(rdl.rdata, &rd, link);
148 RUNTIME_CHECK(dns_rdatalist_tordataset(&rdl, &rds) == ISC_R_SUCCESS);
149
150 isc_buffer_init(&buf, mem, sizeof(mem));
151 result = dns_rdataset_totext(&rds, name, false, false, &buf);
152
153 /*
154 * We could use xfrout_log(), but that would produce
155 * very long lines with a repetitive prefix.
156 */
157 if (result == ISC_R_SUCCESS) {
158 /*
159 * Get rid of final newline.
160 */
161 INSIST(buf.used >= 1 &&
162 ((char *)buf.base)[buf.used - 1] == '\n');
163 buf.used--;
164
165 isc_log_write(XFROUT_RR_LOGARGS, "%.*s",
166 (int)isc_buffer_usedlength(&buf),
167 (char *)isc_buffer_base(&buf));
168 } else {
169 isc_log_write(XFROUT_RR_LOGARGS, "<RR too large to print>");
170 }
171 }
172
173 /**************************************************************************/
174 /*
175 * An 'rrstream_t' is a polymorphic iterator that returns
176 * a stream of resource records. There are multiple implementations,
177 * e.g. for generating AXFR and IXFR records streams.
178 */
179
180 typedef struct rrstream_methods rrstream_methods_t;
181
182 typedef struct rrstream {
183 isc_mem_t *mctx;
184 rrstream_methods_t *methods;
185 } rrstream_t;
186
187 struct rrstream_methods {
188 isc_result_t (*first)(rrstream_t *);
189 isc_result_t (*next)(rrstream_t *);
190 void (*current)(rrstream_t *, dns_name_t **, uint32_t *,
191 dns_rdata_t **);
192 void (*pause)(rrstream_t *);
193 void (*destroy)(rrstream_t **);
194 };
195
196 static void
rrstream_noop_pause(rrstream_t * rs)197 rrstream_noop_pause(rrstream_t *rs) {
198 UNUSED(rs);
199 }
200
201 /**************************************************************************/
202 /*
203 * An 'ixfr_rrstream_t' is an 'rrstream_t' that returns
204 * an IXFR-like RR stream from a journal file.
205 *
206 * The SOA at the beginning of each sequence of additions
207 * or deletions are included in the stream, but the extra
208 * SOAs at the beginning and end of the entire transfer are
209 * not included.
210 */
211
212 typedef struct ixfr_rrstream {
213 rrstream_t common;
214 dns_journal_t *journal;
215 } ixfr_rrstream_t;
216
217 /* Forward declarations. */
218 static void
219 ixfr_rrstream_destroy(rrstream_t **sp);
220
221 static rrstream_methods_t ixfr_rrstream_methods;
222
223 /*
224 * Returns: anything dns_journal_open() or dns_journal_iter_init()
225 * may return.
226 */
227
228 static isc_result_t
ixfr_rrstream_create(isc_mem_t * mctx,const char * journal_filename,uint32_t begin_serial,uint32_t end_serial,rrstream_t ** sp)229 ixfr_rrstream_create(isc_mem_t *mctx, const char *journal_filename,
230 uint32_t begin_serial, uint32_t end_serial,
231 rrstream_t **sp) {
232 ixfr_rrstream_t *s;
233 isc_result_t result;
234
235 INSIST(sp != NULL && *sp == NULL);
236
237 s = isc_mem_get(mctx, sizeof(*s));
238 s->common.mctx = NULL;
239 isc_mem_attach(mctx, &s->common.mctx);
240 s->common.methods = &ixfr_rrstream_methods;
241 s->journal = NULL;
242
243 CHECK(dns_journal_open(mctx, journal_filename, DNS_JOURNAL_READ,
244 &s->journal));
245 CHECK(dns_journal_iter_init(s->journal, begin_serial, end_serial));
246
247 *sp = (rrstream_t *)s;
248 return (ISC_R_SUCCESS);
249
250 failure:
251 ixfr_rrstream_destroy((rrstream_t **)(void *)&s);
252 return (result);
253 }
254
255 static isc_result_t
ixfr_rrstream_first(rrstream_t * rs)256 ixfr_rrstream_first(rrstream_t *rs) {
257 ixfr_rrstream_t *s = (ixfr_rrstream_t *)rs;
258 return (dns_journal_first_rr(s->journal));
259 }
260
261 static isc_result_t
ixfr_rrstream_next(rrstream_t * rs)262 ixfr_rrstream_next(rrstream_t *rs) {
263 ixfr_rrstream_t *s = (ixfr_rrstream_t *)rs;
264 return (dns_journal_next_rr(s->journal));
265 }
266
267 static void
ixfr_rrstream_current(rrstream_t * rs,dns_name_t ** name,uint32_t * ttl,dns_rdata_t ** rdata)268 ixfr_rrstream_current(rrstream_t *rs, dns_name_t **name, uint32_t *ttl,
269 dns_rdata_t **rdata) {
270 ixfr_rrstream_t *s = (ixfr_rrstream_t *)rs;
271 dns_journal_current_rr(s->journal, name, ttl, rdata);
272 }
273
274 static void
ixfr_rrstream_destroy(rrstream_t ** rsp)275 ixfr_rrstream_destroy(rrstream_t **rsp) {
276 ixfr_rrstream_t *s = (ixfr_rrstream_t *)*rsp;
277 if (s->journal != NULL) {
278 dns_journal_destroy(&s->journal);
279 }
280 isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
281 }
282
283 static rrstream_methods_t ixfr_rrstream_methods = {
284 ixfr_rrstream_first, ixfr_rrstream_next, ixfr_rrstream_current,
285 rrstream_noop_pause, ixfr_rrstream_destroy
286 };
287
288 /**************************************************************************/
289 /*
290 * An 'axfr_rrstream_t' is an 'rrstream_t' that returns
291 * an AXFR-like RR stream from a database.
292 *
293 * The SOAs at the beginning and end of the transfer are
294 * not included in the stream.
295 */
296
297 typedef struct axfr_rrstream {
298 rrstream_t common;
299 dns_rriterator_t it;
300 bool it_valid;
301 } axfr_rrstream_t;
302
303 /*
304 * Forward declarations.
305 */
306 static void
307 axfr_rrstream_destroy(rrstream_t **rsp);
308
309 static rrstream_methods_t axfr_rrstream_methods;
310
311 static isc_result_t
axfr_rrstream_create(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * ver,rrstream_t ** sp)312 axfr_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
313 rrstream_t **sp) {
314 axfr_rrstream_t *s;
315 isc_result_t result;
316
317 INSIST(sp != NULL && *sp == NULL);
318
319 s = isc_mem_get(mctx, sizeof(*s));
320 s->common.mctx = NULL;
321 isc_mem_attach(mctx, &s->common.mctx);
322 s->common.methods = &axfr_rrstream_methods;
323 s->it_valid = false;
324
325 CHECK(dns_rriterator_init(&s->it, db, ver, 0));
326 s->it_valid = true;
327
328 *sp = (rrstream_t *)s;
329 return (ISC_R_SUCCESS);
330
331 failure:
332 axfr_rrstream_destroy((rrstream_t **)(void *)&s);
333 return (result);
334 }
335
336 static isc_result_t
axfr_rrstream_first(rrstream_t * rs)337 axfr_rrstream_first(rrstream_t *rs) {
338 axfr_rrstream_t *s = (axfr_rrstream_t *)rs;
339 isc_result_t result;
340 result = dns_rriterator_first(&s->it);
341 if (result != ISC_R_SUCCESS) {
342 return (result);
343 }
344 /* Skip SOA records. */
345 for (;;) {
346 dns_name_t *name_dummy = NULL;
347 uint32_t ttl_dummy;
348 dns_rdata_t *rdata = NULL;
349 dns_rriterator_current(&s->it, &name_dummy, &ttl_dummy, NULL,
350 &rdata);
351 if (rdata->type != dns_rdatatype_soa) {
352 break;
353 }
354 result = dns_rriterator_next(&s->it);
355 if (result != ISC_R_SUCCESS) {
356 break;
357 }
358 }
359 return (result);
360 }
361
362 static isc_result_t
axfr_rrstream_next(rrstream_t * rs)363 axfr_rrstream_next(rrstream_t *rs) {
364 axfr_rrstream_t *s = (axfr_rrstream_t *)rs;
365 isc_result_t result;
366
367 /* Skip SOA records. */
368 for (;;) {
369 dns_name_t *name_dummy = NULL;
370 uint32_t ttl_dummy;
371 dns_rdata_t *rdata = NULL;
372 result = dns_rriterator_next(&s->it);
373 if (result != ISC_R_SUCCESS) {
374 break;
375 }
376 dns_rriterator_current(&s->it, &name_dummy, &ttl_dummy, NULL,
377 &rdata);
378 if (rdata->type != dns_rdatatype_soa) {
379 break;
380 }
381 }
382 return (result);
383 }
384
385 static void
axfr_rrstream_current(rrstream_t * rs,dns_name_t ** name,uint32_t * ttl,dns_rdata_t ** rdata)386 axfr_rrstream_current(rrstream_t *rs, dns_name_t **name, uint32_t *ttl,
387 dns_rdata_t **rdata) {
388 axfr_rrstream_t *s = (axfr_rrstream_t *)rs;
389 dns_rriterator_current(&s->it, name, ttl, NULL, rdata);
390 }
391
392 static void
axfr_rrstream_pause(rrstream_t * rs)393 axfr_rrstream_pause(rrstream_t *rs) {
394 axfr_rrstream_t *s = (axfr_rrstream_t *)rs;
395 dns_rriterator_pause(&s->it);
396 }
397
398 static void
axfr_rrstream_destroy(rrstream_t ** rsp)399 axfr_rrstream_destroy(rrstream_t **rsp) {
400 axfr_rrstream_t *s = (axfr_rrstream_t *)*rsp;
401 if (s->it_valid) {
402 dns_rriterator_destroy(&s->it);
403 }
404 isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
405 }
406
407 static rrstream_methods_t axfr_rrstream_methods = {
408 axfr_rrstream_first, axfr_rrstream_next, axfr_rrstream_current,
409 axfr_rrstream_pause, axfr_rrstream_destroy
410 };
411
412 /**************************************************************************/
413 /*
414 * An 'soa_rrstream_t' is a degenerate 'rrstream_t' that returns
415 * a single SOA record.
416 */
417
418 typedef struct soa_rrstream {
419 rrstream_t common;
420 dns_difftuple_t *soa_tuple;
421 } soa_rrstream_t;
422
423 /*
424 * Forward declarations.
425 */
426 static void
427 soa_rrstream_destroy(rrstream_t **rsp);
428
429 static rrstream_methods_t soa_rrstream_methods;
430
431 static isc_result_t
soa_rrstream_create(isc_mem_t * mctx,dns_db_t * db,dns_dbversion_t * ver,rrstream_t ** sp)432 soa_rrstream_create(isc_mem_t *mctx, dns_db_t *db, dns_dbversion_t *ver,
433 rrstream_t **sp) {
434 soa_rrstream_t *s;
435 isc_result_t result;
436
437 INSIST(sp != NULL && *sp == NULL);
438
439 s = isc_mem_get(mctx, sizeof(*s));
440 s->common.mctx = NULL;
441 isc_mem_attach(mctx, &s->common.mctx);
442 s->common.methods = &soa_rrstream_methods;
443 s->soa_tuple = NULL;
444
445 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
446 &s->soa_tuple));
447
448 *sp = (rrstream_t *)s;
449 return (ISC_R_SUCCESS);
450
451 failure:
452 soa_rrstream_destroy((rrstream_t **)(void *)&s);
453 return (result);
454 }
455
456 static isc_result_t
soa_rrstream_first(rrstream_t * rs)457 soa_rrstream_first(rrstream_t *rs) {
458 UNUSED(rs);
459 return (ISC_R_SUCCESS);
460 }
461
462 static isc_result_t
soa_rrstream_next(rrstream_t * rs)463 soa_rrstream_next(rrstream_t *rs) {
464 UNUSED(rs);
465 return (ISC_R_NOMORE);
466 }
467
468 static void
soa_rrstream_current(rrstream_t * rs,dns_name_t ** name,uint32_t * ttl,dns_rdata_t ** rdata)469 soa_rrstream_current(rrstream_t *rs, dns_name_t **name, uint32_t *ttl,
470 dns_rdata_t **rdata) {
471 soa_rrstream_t *s = (soa_rrstream_t *)rs;
472 *name = &s->soa_tuple->name;
473 *ttl = s->soa_tuple->ttl;
474 *rdata = &s->soa_tuple->rdata;
475 }
476
477 static void
soa_rrstream_destroy(rrstream_t ** rsp)478 soa_rrstream_destroy(rrstream_t **rsp) {
479 soa_rrstream_t *s = (soa_rrstream_t *)*rsp;
480 if (s->soa_tuple != NULL) {
481 dns_difftuple_free(&s->soa_tuple);
482 }
483 isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
484 }
485
486 static rrstream_methods_t soa_rrstream_methods = {
487 soa_rrstream_first, soa_rrstream_next, soa_rrstream_current,
488 rrstream_noop_pause, soa_rrstream_destroy
489 };
490
491 /**************************************************************************/
492 /*
493 * A 'compound_rrstream_t' objects owns a soa_rrstream
494 * and another rrstream, the "data stream". It returns
495 * a concatenated stream consisting of the soa_rrstream, then
496 * the data stream, then the soa_rrstream again.
497 *
498 * The component streams are owned by the compound_rrstream_t
499 * and are destroyed with it.
500 */
501
502 typedef struct compound_rrstream {
503 rrstream_t common;
504 rrstream_t *components[3];
505 int state;
506 isc_result_t result;
507 } compound_rrstream_t;
508
509 /*
510 * Forward declarations.
511 */
512 static void
513 compound_rrstream_destroy(rrstream_t **rsp);
514
515 static isc_result_t
516 compound_rrstream_next(rrstream_t *rs);
517
518 static rrstream_methods_t compound_rrstream_methods;
519
520 /*
521 * Requires:
522 * soa_stream != NULL && *soa_stream != NULL
523 * data_stream != NULL && *data_stream != NULL
524 * sp != NULL && *sp == NULL
525 *
526 * Ensures:
527 * *soa_stream == NULL
528 * *data_stream == NULL
529 * *sp points to a valid compound_rrstream_t
530 * The soa and data streams will be destroyed
531 * when the compound_rrstream_t is destroyed.
532 */
533 static isc_result_t
compound_rrstream_create(isc_mem_t * mctx,rrstream_t ** soa_stream,rrstream_t ** data_stream,rrstream_t ** sp)534 compound_rrstream_create(isc_mem_t *mctx, rrstream_t **soa_stream,
535 rrstream_t **data_stream, rrstream_t **sp) {
536 compound_rrstream_t *s;
537
538 INSIST(sp != NULL && *sp == NULL);
539
540 s = isc_mem_get(mctx, sizeof(*s));
541 s->common.mctx = NULL;
542 isc_mem_attach(mctx, &s->common.mctx);
543 s->common.methods = &compound_rrstream_methods;
544 s->components[0] = *soa_stream;
545 s->components[1] = *data_stream;
546 s->components[2] = *soa_stream;
547 s->state = -1;
548 s->result = ISC_R_FAILURE;
549
550 *data_stream = NULL;
551 *soa_stream = NULL;
552 *sp = (rrstream_t *)s;
553 return (ISC_R_SUCCESS);
554 }
555
556 static isc_result_t
compound_rrstream_first(rrstream_t * rs)557 compound_rrstream_first(rrstream_t *rs) {
558 compound_rrstream_t *s = (compound_rrstream_t *)rs;
559 s->state = 0;
560 do {
561 rrstream_t *curstream = s->components[s->state];
562 s->result = curstream->methods->first(curstream);
563 } while (s->result == ISC_R_NOMORE && s->state < 2);
564 return (s->result);
565 }
566
567 static isc_result_t
compound_rrstream_next(rrstream_t * rs)568 compound_rrstream_next(rrstream_t *rs) {
569 compound_rrstream_t *s = (compound_rrstream_t *)rs;
570 rrstream_t *curstream = s->components[s->state];
571 s->result = curstream->methods->next(curstream);
572 while (s->result == ISC_R_NOMORE) {
573 /*
574 * Make sure locks held by the current stream
575 * are released before we switch streams.
576 */
577 curstream->methods->pause(curstream);
578 if (s->state == 2) {
579 return (ISC_R_NOMORE);
580 }
581 s->state++;
582 curstream = s->components[s->state];
583 s->result = curstream->methods->first(curstream);
584 }
585 return (s->result);
586 }
587
588 static void
compound_rrstream_current(rrstream_t * rs,dns_name_t ** name,uint32_t * ttl,dns_rdata_t ** rdata)589 compound_rrstream_current(rrstream_t *rs, dns_name_t **name, uint32_t *ttl,
590 dns_rdata_t **rdata) {
591 compound_rrstream_t *s = (compound_rrstream_t *)rs;
592 rrstream_t *curstream;
593 INSIST(0 <= s->state && s->state < 3);
594 INSIST(s->result == ISC_R_SUCCESS);
595 curstream = s->components[s->state];
596 curstream->methods->current(curstream, name, ttl, rdata);
597 }
598
599 static void
compound_rrstream_pause(rrstream_t * rs)600 compound_rrstream_pause(rrstream_t *rs) {
601 compound_rrstream_t *s = (compound_rrstream_t *)rs;
602 rrstream_t *curstream;
603 INSIST(0 <= s->state && s->state < 3);
604 curstream = s->components[s->state];
605 curstream->methods->pause(curstream);
606 }
607
608 static void
compound_rrstream_destroy(rrstream_t ** rsp)609 compound_rrstream_destroy(rrstream_t **rsp) {
610 compound_rrstream_t *s = (compound_rrstream_t *)*rsp;
611 s->components[0]->methods->destroy(&s->components[0]);
612 s->components[1]->methods->destroy(&s->components[1]);
613 s->components[2] = NULL; /* Copy of components[0]. */
614 isc_mem_putanddetach(&s->common.mctx, s, sizeof(*s));
615 }
616
617 static rrstream_methods_t compound_rrstream_methods = {
618 compound_rrstream_first, compound_rrstream_next,
619 compound_rrstream_current, compound_rrstream_pause,
620 compound_rrstream_destroy
621 };
622
623 /**************************************************************************/
624
625 /*%
626 * Structure holding outgoing transfer statistics
627 */
628 struct xfr_stats {
629 uint64_t nmsg; /*%< Number of messages sent */
630 uint64_t nrecs; /*%< Number of records sent */
631 uint64_t nbytes; /*%< Number of bytes sent */
632 isc_time_t start; /*%< Start time of the transfer */
633 isc_time_t end; /*%< End time of the transfer */
634 };
635
636 /*%
637 * An 'xfrout_ctx_t' contains the state of an outgoing AXFR or IXFR
638 * in progress.
639 */
640 typedef struct {
641 isc_mem_t *mctx;
642 ns_client_t *client;
643 unsigned int id; /* ID of request */
644 dns_name_t *qname; /* Question name of request */
645 dns_rdatatype_t qtype; /* dns_rdatatype_{a,i}xfr */
646 dns_rdataclass_t qclass;
647 dns_zone_t *zone; /* (necessary for stats) */
648 dns_db_t *db;
649 dns_dbversion_t *ver;
650 isc_quota_t *quota;
651 rrstream_t *stream; /* The XFR RR stream */
652 bool question_added; /* QUESTION section sent? */
653 bool end_of_stream; /* EOS has been reached */
654 isc_buffer_t buf; /* Buffer for message owner
655 * names and rdatas */
656 isc_buffer_t txbuf; /* Transmit message buffer */
657 size_t cbytes; /* Length of current message */
658 void *txmem;
659 unsigned int txmemlen;
660 dns_tsigkey_t *tsigkey; /* Key used to create TSIG */
661 isc_buffer_t *lasttsig; /* the last TSIG */
662 bool verified_tsig; /* verified request MAC */
663 bool many_answers;
664 int sends; /* Send in progress */
665 bool shuttingdown;
666 bool poll;
667 const char *mnemonic; /* Style of transfer */
668 struct xfr_stats stats; /*%< Transfer statistics */
669 } xfrout_ctx_t;
670
671 static void
672 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
673 dns_name_t *qname, dns_rdatatype_t qtype,
674 dns_rdataclass_t qclass, dns_zone_t *zone, dns_db_t *db,
675 dns_dbversion_t *ver, isc_quota_t *quota, rrstream_t *stream,
676 dns_tsigkey_t *tsigkey, isc_buffer_t *lasttsig,
677 bool verified_tsig, unsigned int maxtime,
678 unsigned int idletime, bool many_answers,
679 xfrout_ctx_t **xfrp);
680
681 static void
682 sendstream(xfrout_ctx_t *xfr);
683
684 static void
685 xfrout_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg);
686
687 static void
688 xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg);
689
690 static void
691 xfrout_maybe_destroy(xfrout_ctx_t *xfr);
692
693 static void
694 xfrout_ctx_destroy(xfrout_ctx_t **xfrp);
695
696 static void
697 xfrout_client_shutdown(void *arg, isc_result_t result);
698
699 static void
700 xfrout_log1(ns_client_t *client, dns_name_t *zonename, dns_rdataclass_t rdclass,
701 int level, const char *fmt, ...) ISC_FORMAT_PRINTF(5, 6);
702
703 static void
704 xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...)
705 ISC_FORMAT_PRINTF(3, 4);
706
707 /**************************************************************************/
708
709 void
ns_xfr_start(ns_client_t * client,dns_rdatatype_t reqtype)710 ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
711 isc_result_t result;
712 dns_name_t *question_name;
713 dns_rdataset_t *question_rdataset;
714 dns_zone_t *zone = NULL, *raw = NULL, *mayberaw;
715 dns_db_t *db = NULL;
716 dns_dbversion_t *ver = NULL;
717 dns_rdataclass_t question_class;
718 rrstream_t *soa_stream = NULL;
719 rrstream_t *data_stream = NULL;
720 rrstream_t *stream = NULL;
721 dns_difftuple_t *current_soa_tuple = NULL;
722 dns_name_t *soa_name;
723 dns_rdataset_t *soa_rdataset;
724 dns_rdata_t soa_rdata = DNS_RDATA_INIT;
725 bool have_soa = false;
726 const char *mnemonic = NULL;
727 isc_mem_t *mctx = client->mctx;
728 dns_message_t *request = client->message;
729 xfrout_ctx_t *xfr = NULL;
730 isc_quota_t *quota = NULL;
731 dns_transfer_format_t format = client->view->transfer_format;
732 isc_netaddr_t na;
733 dns_peer_t *peer = NULL;
734 isc_buffer_t *tsigbuf = NULL;
735 char *journalfile;
736 char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
737 char keyname[DNS_NAME_FORMATSIZE];
738 bool is_poll = false;
739 bool is_dlz = false;
740 bool is_ixfr = false;
741 bool useviewacl = false;
742 uint32_t begin_serial = 0, current_serial;
743
744 switch (reqtype) {
745 case dns_rdatatype_axfr:
746 mnemonic = "AXFR";
747 break;
748 case dns_rdatatype_ixfr:
749 mnemonic = "IXFR";
750 break;
751 default:
752 INSIST(0);
753 ISC_UNREACHABLE();
754 }
755
756 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
757 ISC_LOG_DEBUG(6), "%s request", mnemonic);
758 /*
759 * Apply quota.
760 */
761 result = isc_quota_attach(&client->sctx->xfroutquota, "a);
762 if (result != ISC_R_SUCCESS) {
763 isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
764 "%s request denied: %s", mnemonic,
765 isc_result_totext(result));
766 goto failure;
767 }
768
769 /*
770 * Interpret the question section.
771 */
772 result = dns_message_firstname(request, DNS_SECTION_QUESTION);
773 INSIST(result == ISC_R_SUCCESS);
774
775 /*
776 * The question section must contain exactly one question, and
777 * it must be for AXFR/IXFR as appropriate.
778 */
779 question_name = NULL;
780 dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
781 question_rdataset = ISC_LIST_HEAD(question_name->list);
782 question_class = question_rdataset->rdclass;
783 INSIST(question_rdataset->type == reqtype);
784 if (ISC_LIST_NEXT(question_rdataset, link) != NULL) {
785 FAILC(DNS_R_FORMERR, "multiple questions");
786 }
787 result = dns_message_nextname(request, DNS_SECTION_QUESTION);
788 if (result != ISC_R_NOMORE) {
789 FAILC(DNS_R_FORMERR, "multiple questions");
790 }
791
792 result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
793 &zone);
794
795 if (result != ISC_R_SUCCESS || dns_zone_gettype(zone) == dns_zone_dlz) {
796 /*
797 * The normal zone table does not have a match, or this is
798 * marked in the zone table as a DLZ zone. Check the DLZ
799 * databases for a match.
800 */
801 if (!ISC_LIST_EMPTY(client->view->dlz_searched)) {
802 result = dns_dlzallowzonexfr(client->view,
803 question_name,
804 &client->peeraddr, &db);
805 if (result == ISC_R_DEFAULT) {
806 useviewacl = true;
807 result = ISC_R_SUCCESS;
808 }
809 if (result == ISC_R_NOPERM) {
810 char _buf1[DNS_NAME_FORMATSIZE];
811 char _buf2[DNS_RDATACLASS_FORMATSIZE];
812
813 result = DNS_R_REFUSED;
814 dns_name_format(question_name, _buf1,
815 sizeof(_buf1));
816 dns_rdataclass_format(question_class, _buf2,
817 sizeof(_buf2));
818 ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
819 NS_LOGMODULE_XFER_OUT,
820 ISC_LOG_ERROR,
821 "zone transfer '%s/%s' denied",
822 _buf1, _buf2);
823 goto failure;
824 }
825 if (result != ISC_R_SUCCESS) {
826 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
827 question_name, question_class);
828 }
829 is_dlz = true;
830 } else {
831 /*
832 * not DLZ and not in normal zone table, we are
833 * not authoritative
834 */
835 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
836 question_name, question_class);
837 }
838 } else {
839 /* zone table has a match */
840 switch (dns_zone_gettype(zone)) {
841 /*
842 * Master, slave, and mirror zones are OK for transfer.
843 */
844 case dns_zone_master:
845 case dns_zone_slave:
846 case dns_zone_mirror:
847 case dns_zone_dlz:
848 break;
849 default:
850 FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
851 question_name, question_class);
852 }
853 CHECK(dns_zone_getdb(zone, &db));
854 dns_db_currentversion(db, &ver);
855 }
856
857 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
858 "%s question section OK", mnemonic);
859
860 /*
861 * Check the authority section. Look for a SOA record with
862 * the same name and class as the question.
863 */
864 for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
865 result == ISC_R_SUCCESS;
866 result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
867 {
868 soa_name = NULL;
869 dns_message_currentname(request, DNS_SECTION_AUTHORITY,
870 &soa_name);
871
872 /*
873 * Ignore data whose owner name is not the zone apex.
874 */
875 if (!dns_name_equal(soa_name, question_name)) {
876 continue;
877 }
878
879 for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
880 soa_rdataset != NULL;
881 soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
882 {
883 /*
884 * Ignore non-SOA data.
885 */
886 if (soa_rdataset->type != dns_rdatatype_soa) {
887 continue;
888 }
889 if (soa_rdataset->rdclass != question_class) {
890 continue;
891 }
892
893 CHECK(dns_rdataset_first(soa_rdataset));
894 dns_rdataset_current(soa_rdataset, &soa_rdata);
895 result = dns_rdataset_next(soa_rdataset);
896 if (result == ISC_R_SUCCESS) {
897 FAILC(DNS_R_FORMERR, "IXFR authority section "
898 "has multiple SOAs");
899 }
900 have_soa = true;
901 goto got_soa;
902 }
903 }
904 got_soa:
905 if (result != ISC_R_NOMORE) {
906 CHECK(result);
907 }
908
909 xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
910 "%s authority section OK", mnemonic);
911
912 /*
913 * If not a DLZ zone or we are falling back to the view's transfer
914 * ACL, decide whether to allow this transfer.
915 */
916 if (!is_dlz || useviewacl) {
917 dns_acl_t *acl;
918
919 ns_client_aclmsg("zone transfer", question_name, reqtype,
920 client->view->rdclass, msg, sizeof(msg));
921 if (useviewacl) {
922 acl = client->view->transferacl;
923 } else {
924 acl = dns_zone_getxfracl(zone);
925 }
926 CHECK(ns_client_checkacl(client, NULL, msg, acl, true,
927 ISC_LOG_ERROR));
928 }
929
930 /*
931 * AXFR over UDP is not possible.
932 */
933 if (reqtype == dns_rdatatype_axfr &&
934 (client->attributes & NS_CLIENTATTR_TCP) == 0)
935 {
936 FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");
937 }
938
939 /*
940 * Look up the requesting server in the peer table.
941 */
942 isc_netaddr_fromsockaddr(&na, &client->peeraddr);
943 (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);
944
945 /*
946 * Decide on the transfer format (one-answer or many-answers).
947 */
948 if (peer != NULL) {
949 (void)dns_peer_gettransferformat(peer, &format);
950 }
951
952 /*
953 * Get a dynamically allocated copy of the current SOA.
954 */
955 if (is_dlz) {
956 dns_db_currentversion(db, &ver);
957 }
958
959 CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
960 ¤t_soa_tuple));
961
962 current_serial = dns_soa_getserial(¤t_soa_tuple->rdata);
963 if (reqtype == dns_rdatatype_ixfr) {
964 if (!have_soa) {
965 FAILC(DNS_R_FORMERR, "IXFR request missing SOA");
966 }
967
968 begin_serial = dns_soa_getserial(&soa_rdata);
969
970 /*
971 * RFC1995 says "If an IXFR query with the same or
972 * newer version number than that of the server
973 * is received, it is replied to with a single SOA
974 * record of the server's current version, just as
975 * in AXFR". The claim about AXFR is incorrect,
976 * but other than that, we do as the RFC says.
977 *
978 * Sending a single SOA record is also how we refuse
979 * IXFR over UDP (currently, we always do).
980 */
981 if (DNS_SERIAL_GE(begin_serial, current_serial) ||
982 (client->attributes & NS_CLIENTATTR_TCP) == 0)
983 {
984 CHECK(soa_rrstream_create(mctx, db, ver, &stream));
985 is_poll = true;
986 goto have_stream;
987 }
988
989 /*
990 * Outgoing IXFR may have been disabled for this peer
991 * or globally.
992 */
993 if ((client->attributes & NS_CLIENTATTR_TCP) != 0) {
994 bool provide_ixfr;
995
996 provide_ixfr = client->view->provideixfr;
997 if (peer != NULL) {
998 (void)dns_peer_getprovideixfr(peer,
999 &provide_ixfr);
1000 }
1001 if (!provide_ixfr) {
1002 xfrout_log1(client, question_name,
1003 question_class, ISC_LOG_DEBUG(4),
1004 "IXFR delta response disabled due "
1005 "to 'provide-ixfr no;' being set");
1006 mnemonic = "AXFR-style IXFR";
1007 goto axfr_fallback;
1008 }
1009 }
1010
1011 journalfile = is_dlz ? NULL : dns_zone_getjournal(zone);
1012 if (journalfile != NULL) {
1013 result = ixfr_rrstream_create(
1014 mctx, journalfile, begin_serial, current_serial,
1015 &data_stream);
1016 } else {
1017 result = ISC_R_NOTFOUND;
1018 }
1019 if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) {
1020 xfrout_log1(client, question_name, question_class,
1021 ISC_LOG_DEBUG(4),
1022 "IXFR version not in journal, "
1023 "falling back to AXFR");
1024 mnemonic = "AXFR-style IXFR";
1025 goto axfr_fallback;
1026 }
1027 CHECK(result);
1028 is_ixfr = true;
1029 } else {
1030 axfr_fallback:
1031 CHECK(axfr_rrstream_create(mctx, db, ver, &data_stream));
1032 }
1033
1034 /*
1035 * Bracket the data stream with SOAs.
1036 */
1037 CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
1038 CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
1039 &stream));
1040 soa_stream = NULL;
1041 data_stream = NULL;
1042
1043 have_stream:
1044 CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
1045 /*
1046 * Create the xfrout context object. This transfers the ownership
1047 * of "stream", "db", "ver", and "quota" to the xfrout context object.
1048 */
1049
1050 if (is_dlz) {
1051 xfrout_ctx_create(mctx, client, request->id, question_name,
1052 reqtype, question_class, zone, db, ver, quota,
1053 stream, dns_message_gettsigkey(request),
1054 tsigbuf, request->verified_sig, 3600, 3600,
1055 (format == dns_many_answers) ? true : false,
1056 &xfr);
1057 } else {
1058 xfrout_ctx_create(
1059 mctx, client, request->id, question_name, reqtype,
1060 question_class, zone, db, ver, quota, stream,
1061 dns_message_gettsigkey(request), tsigbuf,
1062 request->verified_sig, dns_zone_getmaxxfrout(zone),
1063 dns_zone_getidleout(zone),
1064 (format == dns_many_answers) ? true : false, &xfr);
1065 }
1066
1067 xfr->mnemonic = mnemonic;
1068 stream = NULL;
1069 quota = NULL;
1070
1071 CHECK(xfr->stream->methods->first(xfr->stream));
1072
1073 if (xfr->tsigkey != NULL) {
1074 dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
1075 } else {
1076 keyname[0] = '\0';
1077 }
1078 xfr->poll = is_poll;
1079 if (is_poll) {
1080 xfr->mnemonic = "IXFR poll response";
1081 xfrout_log1(client, question_name, question_class,
1082 ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
1083 (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
1084 } else if (is_ixfr) {
1085 xfrout_log1(client, question_name, question_class, ISC_LOG_INFO,
1086 "%s started%s%s (serial %u -> %u)", mnemonic,
1087 (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname,
1088 begin_serial, current_serial);
1089 } else {
1090 xfrout_log1(client, question_name, question_class, ISC_LOG_INFO,
1091 "%s started%s%s (serial %u)", mnemonic,
1092 (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname,
1093 current_serial);
1094 }
1095
1096 if (zone != NULL) {
1097 dns_zone_getraw(zone, &raw);
1098 mayberaw = (raw != NULL) ? raw : zone;
1099 if ((client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 &&
1100 (dns_zone_gettype(mayberaw) == dns_zone_slave ||
1101 dns_zone_gettype(mayberaw) == dns_zone_mirror))
1102 {
1103 isc_time_t expiretime;
1104 uint32_t secs;
1105 dns_zone_getexpiretime(zone, &expiretime);
1106 secs = isc_time_seconds(&expiretime);
1107 if (secs >= client->now && result == ISC_R_SUCCESS) {
1108 client->attributes |= NS_CLIENTATTR_HAVEEXPIRE;
1109 client->expire = secs - client->now;
1110 }
1111 }
1112 if (raw != NULL) {
1113 dns_zone_detach(&raw);
1114 }
1115 }
1116
1117 /*
1118 * Hand the context over to sendstream(). Set xfr to NULL;
1119 * sendstream() is responsible for either passing the
1120 * context on to a later event handler or destroying it.
1121 */
1122 sendstream(xfr);
1123 xfr = NULL;
1124
1125 result = ISC_R_SUCCESS;
1126
1127 failure:
1128 if (result == DNS_R_REFUSED) {
1129 inc_stats(client, zone, ns_statscounter_xfrrej);
1130 }
1131 if (quota != NULL) {
1132 isc_quota_detach("a);
1133 }
1134 if (current_soa_tuple != NULL) {
1135 dns_difftuple_free(¤t_soa_tuple);
1136 }
1137 if (stream != NULL) {
1138 stream->methods->destroy(&stream);
1139 }
1140 if (soa_stream != NULL) {
1141 soa_stream->methods->destroy(&soa_stream);
1142 }
1143 if (data_stream != NULL) {
1144 data_stream->methods->destroy(&data_stream);
1145 }
1146 if (ver != NULL) {
1147 dns_db_closeversion(db, &ver, false);
1148 }
1149 if (db != NULL) {
1150 dns_db_detach(&db);
1151 }
1152 if (zone != NULL) {
1153 dns_zone_detach(&zone);
1154 }
1155 /* XXX kludge */
1156 if (xfr != NULL) {
1157 xfrout_fail(xfr, result, "setting up zone transfer");
1158 } else if (result != ISC_R_SUCCESS) {
1159 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
1160 NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(3),
1161 "zone transfer setup failed");
1162 ns_client_error(client, result);
1163 isc_nmhandle_unref(client->handle);
1164 }
1165 }
1166
1167 static void
xfrout_ctx_create(isc_mem_t * mctx,ns_client_t * client,unsigned int id,dns_name_t * qname,dns_rdatatype_t qtype,dns_rdataclass_t qclass,dns_zone_t * zone,dns_db_t * db,dns_dbversion_t * ver,isc_quota_t * quota,rrstream_t * stream,dns_tsigkey_t * tsigkey,isc_buffer_t * lasttsig,bool verified_tsig,unsigned int maxtime,unsigned int idletime,bool many_answers,xfrout_ctx_t ** xfrp)1168 xfrout_ctx_create(isc_mem_t *mctx, ns_client_t *client, unsigned int id,
1169 dns_name_t *qname, dns_rdatatype_t qtype,
1170 dns_rdataclass_t qclass, dns_zone_t *zone, dns_db_t *db,
1171 dns_dbversion_t *ver, isc_quota_t *quota, rrstream_t *stream,
1172 dns_tsigkey_t *tsigkey, isc_buffer_t *lasttsig,
1173 bool verified_tsig, unsigned int maxtime,
1174 unsigned int idletime, bool many_answers,
1175 xfrout_ctx_t **xfrp) {
1176 xfrout_ctx_t *xfr;
1177 unsigned int len;
1178 void *mem;
1179
1180 REQUIRE(xfrp != NULL && *xfrp == NULL);
1181
1182 UNUSED(maxtime);
1183 UNUSED(idletime);
1184
1185 xfr = isc_mem_get(mctx, sizeof(*xfr));
1186 xfr->mctx = NULL;
1187 isc_mem_attach(mctx, &xfr->mctx);
1188 xfr->client = client;
1189 xfr->id = id;
1190 xfr->qname = qname;
1191 xfr->qtype = qtype;
1192 xfr->qclass = qclass;
1193 xfr->zone = NULL;
1194 xfr->db = NULL;
1195 xfr->ver = NULL;
1196 if (zone != NULL) { /* zone will be NULL if it's DLZ */
1197 dns_zone_attach(zone, &xfr->zone);
1198 }
1199 dns_db_attach(db, &xfr->db);
1200 dns_db_attachversion(db, ver, &xfr->ver);
1201 xfr->question_added = false;
1202 xfr->end_of_stream = false;
1203 xfr->tsigkey = tsigkey;
1204 xfr->lasttsig = lasttsig;
1205 xfr->verified_tsig = verified_tsig;
1206 xfr->many_answers = many_answers;
1207 xfr->sends = 0;
1208 xfr->shuttingdown = false;
1209 xfr->poll = false;
1210 xfr->mnemonic = NULL;
1211 xfr->buf.base = NULL;
1212 xfr->buf.length = 0;
1213 xfr->txmem = NULL;
1214 xfr->txmemlen = 0;
1215 xfr->stream = NULL;
1216 xfr->quota = NULL;
1217
1218 xfr->stats.nmsg = 0;
1219 xfr->stats.nrecs = 0;
1220 xfr->stats.nbytes = 0;
1221 isc_time_now(&xfr->stats.start);
1222
1223 /*
1224 * Allocate a temporary buffer for the uncompressed response
1225 * message data. The size should be no more than 65535 bytes
1226 * so that the compressed data will fit in a TCP message,
1227 * and no less than 65535 bytes so that an almost maximum-sized
1228 * RR will fit. Note that although 65535-byte RRs are allowed
1229 * in principle, they cannot be zone-transferred (at least not
1230 * if uncompressible), because the message and RR headers would
1231 * push the size of the TCP message over the 65536 byte limit.
1232 */
1233 len = 65535;
1234 mem = isc_mem_get(mctx, len);
1235 isc_buffer_init(&xfr->buf, mem, len);
1236
1237 /*
1238 * Allocate another temporary buffer for the compressed
1239 * response message.
1240 */
1241 len = NS_CLIENT_TCP_BUFFER_SIZE;
1242 mem = isc_mem_get(mctx, len);
1243 isc_buffer_init(&xfr->txbuf, (char *)mem, len);
1244 xfr->txmem = mem;
1245 xfr->txmemlen = len;
1246
1247 #if 0
1248 CHECK(dns_timer_setidle(xfr->client->timer,
1249 maxtime,idletime,false));
1250 #endif /* if 0 */
1251
1252 /*
1253 * Register a shutdown callback with the client, so that we
1254 * can stop the transfer immediately when the client task
1255 * gets a shutdown event.
1256 */
1257 xfr->client->shutdown = xfrout_client_shutdown;
1258 xfr->client->shutdown_arg = xfr;
1259 /*
1260 * These MUST be after the last "goto failure;" / CHECK to
1261 * prevent a double free by the caller.
1262 */
1263 xfr->quota = quota;
1264 xfr->stream = stream;
1265
1266 *xfrp = xfr;
1267 }
1268
1269 /*
1270 * Arrange to send as much as we can of "stream" without blocking.
1271 *
1272 * Requires:
1273 * The stream iterator is initialized and points at an RR,
1274 * or possibly at the end of the stream (that is, the
1275 * _first method of the iterator has been called).
1276 */
1277 static void
sendstream(xfrout_ctx_t * xfr)1278 sendstream(xfrout_ctx_t *xfr) {
1279 dns_message_t *tcpmsg = NULL;
1280 dns_message_t *msg = NULL; /* Client message if UDP, tcpmsg if TCP */
1281 isc_result_t result;
1282 dns_rdataset_t *qrdataset;
1283 dns_name_t *msgname = NULL;
1284 dns_rdata_t *msgrdata = NULL;
1285 dns_rdatalist_t *msgrdl = NULL;
1286 dns_rdataset_t *msgrds = NULL;
1287 dns_compress_t cctx;
1288 bool cleanup_cctx = false;
1289 bool is_tcp;
1290 int n_rrs;
1291
1292 isc_buffer_clear(&xfr->buf);
1293 isc_buffer_clear(&xfr->txbuf);
1294
1295 is_tcp = ((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0);
1296 if (!is_tcp) {
1297 /*
1298 * In the UDP case, we put the response data directly into
1299 * the client message.
1300 */
1301 msg = xfr->client->message;
1302 CHECK(dns_message_reply(msg, true));
1303 } else {
1304 /*
1305 * TCP. Build a response dns_message_t, temporarily storing
1306 * the raw, uncompressed owner names and RR data contiguously
1307 * in xfr->buf. We know that if the uncompressed data fits
1308 * in xfr->buf, the compressed data will surely fit in a TCP
1309 * message.
1310 */
1311
1312 CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER,
1313 &tcpmsg));
1314 msg = tcpmsg;
1315
1316 msg->id = xfr->id;
1317 msg->rcode = dns_rcode_noerror;
1318 msg->flags = DNS_MESSAGEFLAG_QR | DNS_MESSAGEFLAG_AA;
1319 if ((xfr->client->attributes & NS_CLIENTATTR_RA) != 0) {
1320 msg->flags |= DNS_MESSAGEFLAG_RA;
1321 }
1322 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
1323 CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
1324 if (xfr->lasttsig != NULL) {
1325 isc_buffer_free(&xfr->lasttsig);
1326 }
1327 msg->verified_sig = xfr->verified_tsig;
1328
1329 /*
1330 * Add a EDNS option to the message?
1331 */
1332 if ((xfr->client->attributes & NS_CLIENTATTR_WANTOPT) != 0) {
1333 dns_rdataset_t *opt = NULL;
1334
1335 CHECK(ns_client_addopt(xfr->client, msg, &opt));
1336 CHECK(dns_message_setopt(msg, opt));
1337 /*
1338 * Add to first message only.
1339 */
1340 xfr->client->attributes &= ~NS_CLIENTATTR_WANTNSID;
1341 xfr->client->attributes &= ~NS_CLIENTATTR_HAVEEXPIRE;
1342 }
1343
1344 /*
1345 * Account for reserved space.
1346 */
1347 if (xfr->tsigkey != NULL) {
1348 INSIST(msg->reserved != 0U);
1349 }
1350 isc_buffer_add(&xfr->buf, msg->reserved);
1351
1352 /*
1353 * Include a question section in the first message only.
1354 * BIND 8.2.1 will not recognize an IXFR if it does not
1355 * have a question section.
1356 */
1357 if (!xfr->question_added) {
1358 dns_name_t *qname = NULL;
1359 isc_region_t r;
1360
1361 /*
1362 * Reserve space for the 12-byte message header
1363 * and 4 bytes of question.
1364 */
1365 isc_buffer_add(&xfr->buf, 12 + 4);
1366
1367 qrdataset = NULL;
1368 result = dns_message_gettemprdataset(msg, &qrdataset);
1369 if (result != ISC_R_SUCCESS) {
1370 goto failure;
1371 }
1372 dns_rdataset_makequestion(qrdataset,
1373 xfr->client->message->rdclass,
1374 xfr->qtype);
1375
1376 result = dns_message_gettempname(msg, &qname);
1377 if (result != ISC_R_SUCCESS) {
1378 goto failure;
1379 }
1380 dns_name_init(qname, NULL);
1381 isc_buffer_availableregion(&xfr->buf, &r);
1382 INSIST(r.length >= xfr->qname->length);
1383 r.length = xfr->qname->length;
1384 isc_buffer_putmem(&xfr->buf, xfr->qname->ndata,
1385 xfr->qname->length);
1386 dns_name_fromregion(qname, &r);
1387 ISC_LIST_INIT(qname->list);
1388 ISC_LIST_APPEND(qname->list, qrdataset, link);
1389
1390 dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
1391 xfr->question_added = true;
1392 } else {
1393 /*
1394 * Reserve space for the 12-byte message header
1395 */
1396 isc_buffer_add(&xfr->buf, 12);
1397 msg->tcp_continuation = 1;
1398 }
1399 }
1400
1401 /*
1402 * Try to fit in as many RRs as possible, unless "one-answer"
1403 * format has been requested.
1404 */
1405 for (n_rrs = 0;; n_rrs++) {
1406 dns_name_t *name = NULL;
1407 uint32_t ttl;
1408 dns_rdata_t *rdata = NULL;
1409
1410 unsigned int size;
1411 isc_region_t r;
1412
1413 msgname = NULL;
1414 msgrdata = NULL;
1415 msgrdl = NULL;
1416 msgrds = NULL;
1417
1418 xfr->stream->methods->current(xfr->stream, &name, &ttl, &rdata);
1419 size = name->length + 10 + rdata->length;
1420 isc_buffer_availableregion(&xfr->buf, &r);
1421 if (size >= r.length) {
1422 /*
1423 * RR would not fit. If there are other RRs in the
1424 * buffer, send them now and leave this RR to the
1425 * next message. If this RR overflows the buffer
1426 * all by itself, fail.
1427 *
1428 * In theory some RRs might fit in a TCP message
1429 * when compressed even if they do not fit when
1430 * uncompressed, but surely we don't want
1431 * to send such monstrosities to an unsuspecting
1432 * slave.
1433 */
1434 if (n_rrs == 0) {
1435 xfrout_log(xfr, ISC_LOG_WARNING,
1436 "RR too large for zone transfer "
1437 "(%d bytes)",
1438 size);
1439 /* XXX DNS_R_RRTOOLARGE? */
1440 result = ISC_R_NOSPACE;
1441 goto failure;
1442 }
1443 break;
1444 }
1445
1446 if (isc_log_wouldlog(ns_lctx, XFROUT_RR_LOGLEVEL)) {
1447 log_rr(name, rdata, ttl); /* XXX */
1448 }
1449
1450 result = dns_message_gettempname(msg, &msgname);
1451 if (result != ISC_R_SUCCESS) {
1452 goto failure;
1453 }
1454 dns_name_init(msgname, NULL);
1455 isc_buffer_availableregion(&xfr->buf, &r);
1456 INSIST(r.length >= name->length);
1457 r.length = name->length;
1458 isc_buffer_putmem(&xfr->buf, name->ndata, name->length);
1459 dns_name_fromregion(msgname, &r);
1460
1461 /* Reserve space for RR header. */
1462 isc_buffer_add(&xfr->buf, 10);
1463
1464 result = dns_message_gettemprdata(msg, &msgrdata);
1465 if (result != ISC_R_SUCCESS) {
1466 goto failure;
1467 }
1468 isc_buffer_availableregion(&xfr->buf, &r);
1469 r.length = rdata->length;
1470 isc_buffer_putmem(&xfr->buf, rdata->data, rdata->length);
1471 dns_rdata_init(msgrdata);
1472 dns_rdata_fromregion(msgrdata, rdata->rdclass, rdata->type, &r);
1473
1474 result = dns_message_gettemprdatalist(msg, &msgrdl);
1475 if (result != ISC_R_SUCCESS) {
1476 goto failure;
1477 }
1478 msgrdl->type = rdata->type;
1479 msgrdl->rdclass = rdata->rdclass;
1480 msgrdl->ttl = ttl;
1481 if (rdata->type == dns_rdatatype_sig ||
1482 rdata->type == dns_rdatatype_rrsig) {
1483 msgrdl->covers = dns_rdata_covers(rdata);
1484 } else {
1485 msgrdl->covers = dns_rdatatype_none;
1486 }
1487 ISC_LIST_APPEND(msgrdl->rdata, msgrdata, link);
1488
1489 result = dns_message_gettemprdataset(msg, &msgrds);
1490 if (result != ISC_R_SUCCESS) {
1491 goto failure;
1492 }
1493 result = dns_rdatalist_tordataset(msgrdl, msgrds);
1494 INSIST(result == ISC_R_SUCCESS);
1495
1496 ISC_LIST_APPEND(msgname->list, msgrds, link);
1497
1498 dns_message_addname(msg, msgname, DNS_SECTION_ANSWER);
1499 msgname = NULL;
1500
1501 xfr->stats.nrecs++;
1502
1503 result = xfr->stream->methods->next(xfr->stream);
1504 if (result == ISC_R_NOMORE) {
1505 xfr->end_of_stream = true;
1506 break;
1507 }
1508 CHECK(result);
1509
1510 if (!xfr->many_answers) {
1511 break;
1512 }
1513 /*
1514 * At this stage, at least 1 RR has been rendered into
1515 * the message. Check if we want to clamp this message
1516 * here (TCP only).
1517 */
1518 if ((isc_buffer_usedlength(&xfr->buf) >=
1519 xfr->client->sctx->transfer_tcp_message_size) &&
1520 is_tcp)
1521 {
1522 break;
1523 }
1524 }
1525
1526 if (is_tcp) {
1527 isc_region_t used;
1528 CHECK(dns_compress_init(&cctx, -1, xfr->mctx));
1529 dns_compress_setsensitive(&cctx, true);
1530 cleanup_cctx = true;
1531 CHECK(dns_message_renderbegin(msg, &cctx, &xfr->txbuf));
1532 CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
1533 CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
1534 CHECK(dns_message_renderend(msg));
1535 dns_compress_invalidate(&cctx);
1536 cleanup_cctx = false;
1537
1538 isc_buffer_usedregion(&xfr->txbuf, &used);
1539
1540 xfrout_log(xfr, ISC_LOG_DEBUG(8),
1541 "sending TCP message of %d bytes", used.length);
1542
1543 CHECK(isc_nm_send(xfr->client->handle, &used, xfrout_senddone,
1544 xfr));
1545 xfr->sends++;
1546 xfr->cbytes = used.length;
1547 } else {
1548 xfrout_log(xfr, ISC_LOG_DEBUG(8), "sending IXFR UDP response");
1549 ns_client_send(xfr->client);
1550 xfr->stream->methods->pause(xfr->stream);
1551 isc_nmhandle_unref(xfr->client->handle);
1552 xfrout_ctx_destroy(&xfr);
1553 return;
1554 }
1555
1556 /* Advance lasttsig to be the last TSIG generated */
1557 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
1558
1559 failure:
1560 if (msgname != NULL) {
1561 if (msgrds != NULL) {
1562 if (dns_rdataset_isassociated(msgrds)) {
1563 dns_rdataset_disassociate(msgrds);
1564 }
1565 dns_message_puttemprdataset(msg, &msgrds);
1566 }
1567 if (msgrdl != NULL) {
1568 ISC_LIST_UNLINK(msgrdl->rdata, msgrdata, link);
1569 dns_message_puttemprdatalist(msg, &msgrdl);
1570 }
1571 if (msgrdata != NULL) {
1572 dns_message_puttemprdata(msg, &msgrdata);
1573 }
1574 dns_message_puttempname(msg, &msgname);
1575 }
1576
1577 if (tcpmsg != NULL) {
1578 dns_message_destroy(&tcpmsg);
1579 }
1580
1581 if (cleanup_cctx) {
1582 dns_compress_invalidate(&cctx);
1583 }
1584 /*
1585 * Make sure to release any locks held by database
1586 * iterators before returning from the event handler.
1587 */
1588 xfr->stream->methods->pause(xfr->stream);
1589
1590 if (result == ISC_R_SUCCESS) {
1591 return;
1592 }
1593
1594 xfrout_fail(xfr, result, "sending zone data");
1595 }
1596
1597 static void
xfrout_ctx_destroy(xfrout_ctx_t ** xfrp)1598 xfrout_ctx_destroy(xfrout_ctx_t **xfrp) {
1599 xfrout_ctx_t *xfr = *xfrp;
1600 *xfrp = NULL;
1601
1602 INSIST(xfr->sends == 0);
1603
1604 xfr->client->shutdown = NULL;
1605 xfr->client->shutdown_arg = NULL;
1606
1607 if (xfr->stream != NULL) {
1608 xfr->stream->methods->destroy(&xfr->stream);
1609 }
1610 if (xfr->buf.base != NULL) {
1611 isc_mem_put(xfr->mctx, xfr->buf.base, xfr->buf.length);
1612 }
1613 if (xfr->txmem != NULL) {
1614 isc_mem_put(xfr->mctx, xfr->txmem, xfr->txmemlen);
1615 }
1616 if (xfr->lasttsig != NULL) {
1617 isc_buffer_free(&xfr->lasttsig);
1618 }
1619 if (xfr->quota != NULL) {
1620 isc_quota_detach(&xfr->quota);
1621 }
1622 if (xfr->ver != NULL) {
1623 dns_db_closeversion(xfr->db, &xfr->ver, false);
1624 }
1625 if (xfr->zone != NULL) {
1626 dns_zone_detach(&xfr->zone);
1627 }
1628 if (xfr->db != NULL) {
1629 dns_db_detach(&xfr->db);
1630 }
1631
1632 isc_mem_putanddetach(&xfr->mctx, xfr, sizeof(*xfr));
1633 }
1634
1635 static void
xfrout_senddone(isc_nmhandle_t * handle,isc_result_t result,void * arg)1636 xfrout_senddone(isc_nmhandle_t *handle, isc_result_t result, void *arg) {
1637 xfrout_ctx_t *xfr = (xfrout_ctx_t *)arg;
1638
1639 REQUIRE((xfr->client->attributes & NS_CLIENTATTR_TCP) != 0);
1640
1641 INSIST(handle == xfr->client->handle);
1642
1643 xfr->sends--;
1644 INSIST(xfr->sends == 0);
1645
1646 /*
1647 * Update transfer statistics if sending succeeded, accounting for the
1648 * two-byte TCP length prefix included in the number of bytes sent.
1649 */
1650 if (result == ISC_R_SUCCESS) {
1651 xfr->stats.nmsg++;
1652 xfr->stats.nbytes += xfr->cbytes;
1653 }
1654
1655 #if 0
1656 (void)isc_timer_touch(xfr->client->timer);
1657 #endif /* if 0 */
1658
1659 if (xfr->shuttingdown) {
1660 xfrout_maybe_destroy(xfr);
1661 } else if (result != ISC_R_SUCCESS) {
1662 xfrout_fail(xfr, result, "send");
1663 } else if (!xfr->end_of_stream) {
1664 sendstream(xfr);
1665 } else {
1666 /* End of zone transfer stream. */
1667 uint64_t msecs, persec;
1668
1669 inc_stats(xfr->client, xfr->zone, ns_statscounter_xfrdone);
1670 isc_time_now(&xfr->stats.end);
1671 msecs = isc_time_microdiff(&xfr->stats.end, &xfr->stats.start);
1672 msecs /= 1000;
1673 if (msecs == 0) {
1674 msecs = 1;
1675 }
1676 persec = (xfr->stats.nbytes * 1000) / msecs;
1677 xfrout_log(xfr, xfr->poll ? ISC_LOG_DEBUG(1) : ISC_LOG_INFO,
1678 "%s ended: "
1679 "%" PRIu64 " messages, %" PRIu64 " records, "
1680 "%" PRIu64 " bytes, "
1681 "%u.%03u secs (%u bytes/sec)",
1682 xfr->mnemonic, xfr->stats.nmsg, xfr->stats.nrecs,
1683 xfr->stats.nbytes, (unsigned int)(msecs / 1000),
1684 (unsigned int)(msecs % 1000), (unsigned int)persec);
1685
1686 xfrout_ctx_destroy(&xfr);
1687 /* We're done, unreference the handle */
1688 isc_nmhandle_unref(handle);
1689 }
1690 }
1691
1692 static void
xfrout_fail(xfrout_ctx_t * xfr,isc_result_t result,const char * msg)1693 xfrout_fail(xfrout_ctx_t *xfr, isc_result_t result, const char *msg) {
1694 xfr->shuttingdown = true;
1695 xfrout_log(xfr, ISC_LOG_ERROR, "%s: %s", msg,
1696 isc_result_totext(result));
1697 xfrout_maybe_destroy(xfr);
1698 }
1699
1700 static void
xfrout_maybe_destroy(xfrout_ctx_t * xfr)1701 xfrout_maybe_destroy(xfrout_ctx_t *xfr) {
1702 INSIST(xfr->shuttingdown);
1703 #if 0
1704 if (xfr->sends > 0) {
1705 /*
1706 * If we are currently sending, cancel it and wait for
1707 * cancel event before destroying the context.
1708 */
1709 isc_socket_cancel(xfr->client->tcpsocket,xfr->client->task,
1710 ISC_SOCKCANCEL_SEND);
1711 } else {
1712 #endif /* if 0 */
1713 ns_client_drop(xfr->client, ISC_R_CANCELED);
1714 isc_nmhandle_unref(xfr->client->handle);
1715 xfrout_ctx_destroy(&xfr);
1716 #if 0
1717 }
1718 #endif /* if 0 */
1719 }
1720
1721 static void
xfrout_client_shutdown(void * arg,isc_result_t result)1722 xfrout_client_shutdown(void *arg, isc_result_t result) {
1723 xfrout_ctx_t *xfr = (xfrout_ctx_t *)arg;
1724 xfrout_fail(xfr, result, "aborted");
1725 }
1726
1727 /*
1728 * Log outgoing zone transfer messages in a format like
1729 * <client>: transfer of <zone>: <message>
1730 */
1731
1732 static void
1733 xfrout_logv(ns_client_t *client, dns_name_t *zonename, dns_rdataclass_t rdclass,
1734 int level, const char *fmt, va_list ap) ISC_FORMAT_PRINTF(5, 0);
1735
1736 static void
xfrout_logv(ns_client_t * client,dns_name_t * zonename,dns_rdataclass_t rdclass,int level,const char * fmt,va_list ap)1737 xfrout_logv(ns_client_t *client, dns_name_t *zonename, dns_rdataclass_t rdclass,
1738 int level, const char *fmt, va_list ap) {
1739 char msgbuf[2048];
1740 char namebuf[DNS_NAME_FORMATSIZE];
1741 char classbuf[DNS_RDATACLASS_FORMATSIZE];
1742
1743 dns_name_format(zonename, namebuf, sizeof(namebuf));
1744 dns_rdataclass_format(rdclass, classbuf, sizeof(classbuf));
1745 vsnprintf(msgbuf, sizeof(msgbuf), fmt, ap);
1746 ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
1747 level, "transfer of '%s/%s': %s", namebuf, classbuf,
1748 msgbuf);
1749 }
1750
1751 /*
1752 * Logging function for use when a xfrout_ctx_t has not yet been created.
1753 */
1754 static void
xfrout_log1(ns_client_t * client,dns_name_t * zonename,dns_rdataclass_t rdclass,int level,const char * fmt,...)1755 xfrout_log1(ns_client_t *client, dns_name_t *zonename, dns_rdataclass_t rdclass,
1756 int level, const char *fmt, ...) {
1757 va_list ap;
1758 va_start(ap, fmt);
1759 xfrout_logv(client, zonename, rdclass, level, fmt, ap);
1760 va_end(ap);
1761 }
1762
1763 /*
1764 * Logging function for use when there is a xfrout_ctx_t.
1765 */
1766 static void
xfrout_log(xfrout_ctx_t * xfr,int level,const char * fmt,...)1767 xfrout_log(xfrout_ctx_t *xfr, int level, const char *fmt, ...) {
1768 va_list ap;
1769 va_start(ap, fmt);
1770 xfrout_logv(xfr->client, xfr->qname, xfr->qclass, level, fmt, ap);
1771 va_end(ap);
1772 }
1773