Import bind-9.3.4
[dragonfly.git] / contrib / bind-9.3 / lib / dns / xfrin.c
blobfdeed14bd6e67aafb8bcdcd6ce917ec5fdaa0293
1 /*
2 * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2003 Internet Software Consortium.
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* $Id: xfrin.c,v 1.124.2.4.2.16 2006/07/19 01:04:24 marka Exp $ */
20 #include <config.h>
22 #include <isc/mem.h>
23 #include <isc/print.h>
24 #include <isc/random.h>
25 #include <isc/string.h> /* Required for HP/UX (and others?) */
26 #include <isc/task.h>
27 #include <isc/timer.h>
28 #include <isc/util.h>
30 #include <dns/db.h>
31 #include <dns/diff.h>
32 #include <dns/events.h>
33 #include <dns/journal.h>
34 #include <dns/log.h>
35 #include <dns/message.h>
36 #include <dns/rdataclass.h>
37 #include <dns/rdatalist.h>
38 #include <dns/rdataset.h>
39 #include <dns/result.h>
40 #include <dns/soa.h>
41 #include <dns/tcpmsg.h>
42 #include <dns/timer.h>
43 #include <dns/tsig.h>
44 #include <dns/view.h>
45 #include <dns/xfrin.h>
46 #include <dns/zone.h>
48 #include <dst/dst.h>
51 * Incoming AXFR and IXFR.
55 * It would be non-sensical (or at least obtuse) to use FAIL() with an
56 * ISC_R_SUCCESS code, but the test is there to keep the Solaris compiler
57 * from complaining about "end-of-loop code not reached".
59 #define FAIL(code) \
60 do { result = (code); \
61 if (result != ISC_R_SUCCESS) goto failure; \
62 } while (0)
64 #define CHECK(op) \
65 do { result = (op); \
66 if (result != ISC_R_SUCCESS) goto failure; \
67 } while (0)
70 * The states of the *XFR state machine. We handle both IXFR and AXFR
71 * with a single integrated state machine because they cannot be distinguished
72 * immediately - an AXFR response to an IXFR request can only be detected
73 * when the first two (2) response RRs have already been received.
75 typedef enum {
76 XFRST_SOAQUERY,
77 XFRST_GOTSOA,
78 XFRST_INITIALSOA,
79 XFRST_FIRSTDATA,
80 XFRST_IXFR_DELSOA,
81 XFRST_IXFR_DEL,
82 XFRST_IXFR_ADDSOA,
83 XFRST_IXFR_ADD,
84 XFRST_AXFR,
85 XFRST_END
86 } xfrin_state_t;
89 * Incoming zone transfer context.
92 struct dns_xfrin_ctx {
93 unsigned int magic;
94 isc_mem_t *mctx;
95 dns_zone_t *zone;
97 int refcount;
99 isc_task_t *task;
100 isc_timer_t *timer;
101 isc_socketmgr_t *socketmgr;
103 int connects; /* Connect in progress */
104 int sends; /* Send in progress */
105 int recvs; /* Receive in progress */
106 isc_boolean_t shuttingdown;
108 dns_name_t name; /* Name of zone to transfer */
109 dns_rdataclass_t rdclass;
111 isc_boolean_t checkid;
112 dns_messageid_t id;
115 * Requested transfer type (dns_rdatatype_axfr or
116 * dns_rdatatype_ixfr). The actual transfer type
117 * may differ due to IXFR->AXFR fallback.
119 dns_rdatatype_t reqtype;
121 isc_sockaddr_t masteraddr;
122 isc_sockaddr_t sourceaddr;
123 isc_socket_t *socket;
125 /* Buffer for IXFR/AXFR request message */
126 isc_buffer_t qbuffer;
127 unsigned char qbuffer_data[512];
129 /* Incoming reply TCP message */
130 dns_tcpmsg_t tcpmsg;
131 isc_boolean_t tcpmsg_valid;
133 dns_db_t *db;
134 dns_dbversion_t *ver;
135 dns_diff_t diff; /* Pending database changes */
136 int difflen; /* Number of pending tuples */
138 xfrin_state_t state;
139 isc_uint32_t end_serial;
140 isc_boolean_t is_ixfr;
142 unsigned int nmsg; /* Number of messages recvd */
144 dns_tsigkey_t *tsigkey; /* Key used to create TSIG */
145 isc_buffer_t *lasttsig; /* The last TSIG */
146 dst_context_t *tsigctx; /* TSIG verification context */
147 unsigned int sincetsig; /* recvd since the last TSIG */
148 dns_xfrindone_t done;
151 * AXFR- and IXFR-specific data. Only one is used at a time
152 * according to the is_ixfr flag, so this could be a union,
153 * but keeping them separate makes it a bit simpler to clean
154 * things up when destroying the context.
156 struct {
157 dns_addrdatasetfunc_t add_func;
158 dns_dbload_t *add_private;
159 } axfr;
161 struct {
162 isc_uint32_t request_serial;
163 isc_uint32_t current_serial;
164 dns_journal_t *journal;
166 } ixfr;
169 #define XFRIN_MAGIC ISC_MAGIC('X', 'f', 'r', 'I')
170 #define VALID_XFRIN(x) ISC_MAGIC_VALID(x, XFRIN_MAGIC)
172 /**************************************************************************/
174 * Forward declarations.
177 static isc_result_t
178 xfrin_create(isc_mem_t *mctx,
179 dns_zone_t *zone,
180 dns_db_t *db,
181 isc_task_t *task,
182 isc_timermgr_t *timermgr,
183 isc_socketmgr_t *socketmgr,
184 dns_name_t *zonename,
185 dns_rdataclass_t rdclass,
186 dns_rdatatype_t reqtype,
187 isc_sockaddr_t *masteraddr,
188 isc_sockaddr_t *sourceaddr,
189 dns_tsigkey_t *tsigkey,
190 dns_xfrin_ctx_t **xfrp);
192 static isc_result_t axfr_init(dns_xfrin_ctx_t *xfr);
193 static isc_result_t axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);
194 static isc_result_t axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
195 dns_name_t *name, dns_ttl_t ttl,
196 dns_rdata_t *rdata);
197 static isc_result_t axfr_apply(dns_xfrin_ctx_t *xfr);
198 static isc_result_t axfr_commit(dns_xfrin_ctx_t *xfr);
200 static isc_result_t ixfr_init(dns_xfrin_ctx_t *xfr);
201 static isc_result_t ixfr_apply(dns_xfrin_ctx_t *xfr);
202 static isc_result_t ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
203 dns_name_t *name, dns_ttl_t ttl,
204 dns_rdata_t *rdata);
205 static isc_result_t ixfr_commit(dns_xfrin_ctx_t *xfr);
207 static isc_result_t xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name,
208 isc_uint32_t ttl, dns_rdata_t *rdata);
210 static isc_result_t xfrin_start(dns_xfrin_ctx_t *xfr);
212 static void xfrin_connect_done(isc_task_t *task, isc_event_t *event);
213 static isc_result_t xfrin_send_request(dns_xfrin_ctx_t *xfr);
214 static void xfrin_send_done(isc_task_t *task, isc_event_t *event);
215 static void xfrin_sendlen_done(isc_task_t *task, isc_event_t *event);
216 static void xfrin_recv_done(isc_task_t *task, isc_event_t *event);
217 static void xfrin_timeout(isc_task_t *task, isc_event_t *event);
219 static void maybe_free(dns_xfrin_ctx_t *xfr);
221 static void
222 xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg);
223 static isc_result_t
224 render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf);
226 static void
227 xfrin_logv(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
228 isc_sockaddr_t *masteraddr, const char *fmt, va_list ap)
229 ISC_FORMAT_PRINTF(5, 0);
231 static void
232 xfrin_log1(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
233 isc_sockaddr_t *masteraddr, const char *fmt, ...)
234 ISC_FORMAT_PRINTF(5, 6);
236 static void
237 xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
238 ISC_FORMAT_PRINTF(3, 4);
240 /**************************************************************************/
242 * AXFR handling
245 static isc_result_t
246 axfr_init(dns_xfrin_ctx_t *xfr) {
247 isc_result_t result;
249 xfr->is_ixfr = ISC_FALSE;
251 if (xfr->db != NULL)
252 dns_db_detach(&xfr->db);
254 CHECK(axfr_makedb(xfr, &xfr->db));
255 CHECK(dns_db_beginload(xfr->db, &xfr->axfr.add_func,
256 &xfr->axfr.add_private));
257 result = ISC_R_SUCCESS;
258 failure:
259 return (result);
262 static isc_result_t
263 axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
264 return (dns_db_create(xfr->mctx, /* XXX */
265 "rbt", /* XXX guess */
266 &xfr->name,
267 dns_dbtype_zone,
268 xfr->rdclass,
269 0, NULL, /* XXX guess */
270 dbp));
273 static isc_result_t
274 axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
275 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
277 isc_result_t result;
279 dns_difftuple_t *tuple = NULL;
281 CHECK(dns_zone_checknames(xfr->zone, name, rdata));
282 CHECK(dns_difftuple_create(xfr->diff.mctx, op,
283 name, ttl, rdata, &tuple));
284 dns_diff_append(&xfr->diff, &tuple);
285 if (++xfr->difflen > 100)
286 CHECK(axfr_apply(xfr));
287 result = ISC_R_SUCCESS;
288 failure:
289 return (result);
293 * Store a set of AXFR RRs in the database.
295 static isc_result_t
296 axfr_apply(dns_xfrin_ctx_t *xfr) {
297 isc_result_t result;
299 CHECK(dns_diff_load(&xfr->diff,
300 xfr->axfr.add_func, xfr->axfr.add_private));
301 xfr->difflen = 0;
302 dns_diff_clear(&xfr->diff);
303 result = ISC_R_SUCCESS;
304 failure:
305 return (result);
308 static isc_result_t
309 axfr_commit(dns_xfrin_ctx_t *xfr) {
310 isc_result_t result;
312 CHECK(axfr_apply(xfr));
313 CHECK(dns_db_endload(xfr->db, &xfr->axfr.add_private));
314 CHECK(dns_zone_replacedb(xfr->zone, xfr->db, ISC_TRUE));
316 result = ISC_R_SUCCESS;
317 failure:
318 return (result);
321 /**************************************************************************/
323 * IXFR handling
326 static isc_result_t
327 ixfr_init(dns_xfrin_ctx_t *xfr) {
328 isc_result_t result;
329 char *journalfile;
331 if (xfr->reqtype != dns_rdatatype_ixfr) {
332 xfrin_log(xfr, ISC_LOG_ERROR,
333 "got incremental response to AXFR request");
334 return (DNS_R_FORMERR);
337 xfr->is_ixfr = ISC_TRUE;
338 INSIST(xfr->db != NULL);
339 xfr->difflen = 0;
341 journalfile = dns_zone_getjournal(xfr->zone);
342 if (journalfile != NULL)
343 CHECK(dns_journal_open(xfr->mctx, journalfile,
344 ISC_TRUE, &xfr->ixfr.journal));
346 result = ISC_R_SUCCESS;
347 failure:
348 return (result);
351 static isc_result_t
352 ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
353 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
355 isc_result_t result;
357 dns_difftuple_t *tuple = NULL;
358 if (op == DNS_DIFFOP_ADD)
359 CHECK(dns_zone_checknames(xfr->zone, name, rdata));
360 CHECK(dns_difftuple_create(xfr->diff.mctx, op,
361 name, ttl, rdata, &tuple));
362 dns_diff_append(&xfr->diff, &tuple);
363 if (++xfr->difflen > 100)
364 CHECK(ixfr_apply(xfr));
365 result = ISC_R_SUCCESS;
366 failure:
367 return (result);
371 * Apply a set of IXFR changes to the database.
373 static isc_result_t
374 ixfr_apply(dns_xfrin_ctx_t *xfr) {
375 isc_result_t result;
377 if (xfr->ver == NULL) {
378 CHECK(dns_db_newversion(xfr->db, &xfr->ver));
379 if (xfr->ixfr.journal != NULL)
380 CHECK(dns_journal_begin_transaction(xfr->ixfr.journal));
382 CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver));
383 if (xfr->ixfr.journal != NULL) {
384 result = dns_journal_writediff(xfr->ixfr.journal, &xfr->diff);
385 if (result != ISC_R_SUCCESS)
386 goto failure;
388 dns_diff_clear(&xfr->diff);
389 xfr->difflen = 0;
390 result = ISC_R_SUCCESS;
391 failure:
392 return (result);
395 static isc_result_t
396 ixfr_commit(dns_xfrin_ctx_t *xfr) {
397 isc_result_t result;
399 CHECK(ixfr_apply(xfr));
400 if (xfr->ver != NULL) {
401 /* XXX enter ready-to-commit state here */
402 if (xfr->ixfr.journal != NULL)
403 CHECK(dns_journal_commit(xfr->ixfr.journal));
404 dns_db_closeversion(xfr->db, &xfr->ver, ISC_TRUE);
405 dns_zone_markdirty(xfr->zone);
407 result = ISC_R_SUCCESS;
408 failure:
409 return (result);
412 /**************************************************************************/
414 * Common AXFR/IXFR protocol code
418 * Handle a single incoming resource record according to the current
419 * state.
421 static isc_result_t
422 xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
423 dns_rdata_t *rdata)
425 isc_result_t result;
427 redo:
428 switch (xfr->state) {
429 case XFRST_SOAQUERY:
430 if (rdata->type != dns_rdatatype_soa) {
431 xfrin_log(xfr, ISC_LOG_ERROR,
432 "non-SOA response to SOA query");
433 FAIL(DNS_R_FORMERR);
435 xfr->end_serial = dns_soa_getserial(rdata);
436 if (!DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) &&
437 !dns_zone_isforced(xfr->zone)) {
438 xfrin_log(xfr, ISC_LOG_DEBUG(3),
439 "requested serial %u, "
440 "master has %u, not updating",
441 xfr->ixfr.request_serial, xfr->end_serial);
442 FAIL(DNS_R_UPTODATE);
444 xfr->state = XFRST_GOTSOA;
445 break;
447 case XFRST_GOTSOA:
449 * Skip other records in the answer section.
451 break;
453 case XFRST_INITIALSOA:
454 if (rdata->type != dns_rdatatype_soa) {
455 xfrin_log(xfr, ISC_LOG_ERROR,
456 "first RR in zone transfer must be SOA");
457 FAIL(DNS_R_FORMERR);
460 * Remember the serial number in the intial SOA.
461 * We need it to recognize the end of an IXFR.
463 xfr->end_serial = dns_soa_getserial(rdata);
464 if (xfr->reqtype == dns_rdatatype_ixfr &&
465 ! DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial)
466 && !dns_zone_isforced(xfr->zone))
469 * This must be the single SOA record that is
470 * sent when the current version on the master
471 * is not newer than the version in the request.
473 xfrin_log(xfr, ISC_LOG_DEBUG(3),
474 "requested serial %u, "
475 "master has %u, not updating",
476 xfr->ixfr.request_serial, xfr->end_serial);
477 FAIL(DNS_R_UPTODATE);
479 if (xfr->reqtype == dns_rdatatype_axfr)
480 xfr->checkid = ISC_FALSE;
481 xfr->state = XFRST_FIRSTDATA;
482 break;
484 case XFRST_FIRSTDATA:
486 * If the transfer begins with one SOA record, it is an AXFR,
487 * if it begins with two SOAs, it is an IXFR.
489 if (xfr->reqtype == dns_rdatatype_ixfr &&
490 rdata->type == dns_rdatatype_soa &&
491 xfr->ixfr.request_serial == dns_soa_getserial(rdata)) {
492 xfrin_log(xfr, ISC_LOG_DEBUG(3),
493 "got incremental response");
494 CHECK(ixfr_init(xfr));
495 xfr->state = XFRST_IXFR_DELSOA;
496 } else {
497 xfrin_log(xfr, ISC_LOG_DEBUG(3),
498 "got nonincremental response");
499 CHECK(axfr_init(xfr));
500 xfr->state = XFRST_AXFR;
502 goto redo;
504 case XFRST_IXFR_DELSOA:
505 INSIST(rdata->type == dns_rdatatype_soa);
506 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
507 xfr->state = XFRST_IXFR_DEL;
508 break;
510 case XFRST_IXFR_DEL:
511 if (rdata->type == dns_rdatatype_soa) {
512 isc_uint32_t soa_serial = dns_soa_getserial(rdata);
513 xfr->state = XFRST_IXFR_ADDSOA;
514 xfr->ixfr.current_serial = soa_serial;
515 goto redo;
517 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
518 break;
520 case XFRST_IXFR_ADDSOA:
521 INSIST(rdata->type == dns_rdatatype_soa);
522 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
523 xfr->state = XFRST_IXFR_ADD;
524 break;
526 case XFRST_IXFR_ADD:
527 if (rdata->type == dns_rdatatype_soa) {
528 isc_uint32_t soa_serial = dns_soa_getserial(rdata);
529 if (soa_serial == xfr->end_serial) {
530 CHECK(ixfr_commit(xfr));
531 xfr->state = XFRST_END;
532 break;
533 } else if (soa_serial != xfr->ixfr.current_serial) {
534 xfrin_log(xfr, ISC_LOG_ERROR,
535 "IXFR out of sync: "
536 "expected serial %u, got %u",
537 xfr->ixfr.current_serial, soa_serial);
538 FAIL(DNS_R_FORMERR);
539 } else {
540 CHECK(ixfr_commit(xfr));
541 xfr->state = XFRST_IXFR_DELSOA;
542 goto redo;
545 if (rdata->type == dns_rdatatype_ns &&
546 dns_name_iswildcard(name))
547 FAIL(DNS_R_INVALIDNS);
548 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
549 break;
551 case XFRST_AXFR:
553 * Old BINDs sent cross class A records for non IN classes.
555 if (rdata->type == dns_rdatatype_a &&
556 rdata->rdclass != xfr->rdclass &&
557 xfr->rdclass != dns_rdataclass_in)
558 break;
559 CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
560 if (rdata->type == dns_rdatatype_soa) {
561 CHECK(axfr_commit(xfr));
562 xfr->state = XFRST_END;
563 break;
565 break;
566 case XFRST_END:
567 FAIL(DNS_R_EXTRADATA);
568 default:
569 INSIST(0);
570 break;
572 result = ISC_R_SUCCESS;
573 failure:
574 return (result);
577 isc_result_t
578 dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
579 isc_sockaddr_t *masteraddr, dns_tsigkey_t *tsigkey,
580 isc_mem_t *mctx, isc_timermgr_t *timermgr,
581 isc_socketmgr_t *socketmgr, isc_task_t *task,
582 dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
584 isc_sockaddr_t sourceaddr;
586 switch (isc_sockaddr_pf(masteraddr)) {
587 case PF_INET:
588 sourceaddr = *dns_zone_getxfrsource4(zone);
589 break;
590 case PF_INET6:
591 sourceaddr = *dns_zone_getxfrsource6(zone);
592 break;
593 default:
594 INSIST(0);
597 return(dns_xfrin_create2(zone, xfrtype, masteraddr, &sourceaddr,
598 tsigkey, mctx, timermgr, socketmgr,
599 task, done, xfrp));
602 isc_result_t
603 dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype,
604 isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr,
605 dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
606 isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
607 isc_task_t *task, dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
609 dns_name_t *zonename = dns_zone_getorigin(zone);
610 dns_xfrin_ctx_t *xfr = NULL;
611 isc_result_t result;
612 dns_db_t *db = NULL;
614 REQUIRE(xfrp != NULL && *xfrp == NULL);
616 (void)dns_zone_getdb(zone, &db);
618 if (xfrtype == dns_rdatatype_soa || xfrtype == dns_rdatatype_ixfr)
619 REQUIRE(db != NULL);
621 CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename,
622 dns_zone_getclass(zone), xfrtype, masteraddr,
623 sourceaddr, tsigkey, &xfr));
625 CHECK(xfrin_start(xfr));
627 xfr->done = done;
628 xfr->refcount++;
629 *xfrp = xfr;
631 failure:
632 if (db != NULL)
633 dns_db_detach(&db);
634 if (result != ISC_R_SUCCESS)
635 xfrin_log1(ISC_LOG_ERROR, zonename, dns_zone_getclass(zone),
636 masteraddr, "zone transfer setup failed");
637 return (result);
640 void
641 dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
642 if (! xfr->shuttingdown)
643 xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
646 void
647 dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target) {
648 REQUIRE(target != NULL && *target == NULL);
649 source->refcount++;
650 *target = source;
653 void
654 dns_xfrin_detach(dns_xfrin_ctx_t **xfrp) {
655 dns_xfrin_ctx_t *xfr = *xfrp;
656 INSIST(xfr->refcount > 0);
657 xfr->refcount--;
658 maybe_free(xfr);
659 *xfrp = NULL;
662 static void
663 xfrin_cancelio(dns_xfrin_ctx_t *xfr) {
664 if (xfr->connects > 0) {
665 isc_socket_cancel(xfr->socket, xfr->task,
666 ISC_SOCKCANCEL_CONNECT);
667 } else if (xfr->recvs > 0) {
668 dns_tcpmsg_cancelread(&xfr->tcpmsg);
669 } else if (xfr->sends > 0) {
670 isc_socket_cancel(xfr->socket, xfr->task,
671 ISC_SOCKCANCEL_SEND);
675 static void
676 xfrin_reset(dns_xfrin_ctx_t *xfr) {
677 REQUIRE(VALID_XFRIN(xfr));
679 xfrin_log(xfr, ISC_LOG_INFO, "resetting");
681 xfrin_cancelio(xfr);
683 if (xfr->socket != NULL)
684 isc_socket_detach(&xfr->socket);
686 if (xfr->lasttsig != NULL)
687 isc_buffer_free(&xfr->lasttsig);
689 dns_diff_clear(&xfr->diff);
690 xfr->difflen = 0;
692 if (xfr->ixfr.journal != NULL)
693 dns_journal_destroy(&xfr->ixfr.journal);
695 if (xfr->axfr.add_private != NULL) {
696 (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
697 xfr->axfr.add_func = NULL;
700 if (xfr->tcpmsg_valid) {
701 dns_tcpmsg_invalidate(&xfr->tcpmsg);
702 xfr->tcpmsg_valid = ISC_FALSE;
705 if (xfr->ver != NULL)
706 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
710 static void
711 xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
712 if (result != DNS_R_UPTODATE) {
713 xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s",
714 msg, isc_result_totext(result));
715 if (xfr->is_ixfr)
716 /* Pass special result code to force AXFR retry */
717 result = DNS_R_BADIXFR;
719 xfrin_cancelio(xfr);
720 if (xfr->done != NULL) {
721 (xfr->done)(xfr->zone, result);
722 xfr->done = NULL;
724 xfr->shuttingdown = ISC_TRUE;
725 maybe_free(xfr);
728 static isc_result_t
729 xfrin_create(isc_mem_t *mctx,
730 dns_zone_t *zone,
731 dns_db_t *db,
732 isc_task_t *task,
733 isc_timermgr_t *timermgr,
734 isc_socketmgr_t *socketmgr,
735 dns_name_t *zonename,
736 dns_rdataclass_t rdclass,
737 dns_rdatatype_t reqtype,
738 isc_sockaddr_t *masteraddr,
739 isc_sockaddr_t *sourceaddr,
740 dns_tsigkey_t *tsigkey,
741 dns_xfrin_ctx_t **xfrp)
743 dns_xfrin_ctx_t *xfr = NULL;
744 isc_result_t result;
745 isc_uint32_t tmp;
747 xfr = isc_mem_get(mctx, sizeof(*xfr));
748 if (xfr == NULL)
749 return (ISC_R_NOMEMORY);
750 xfr->mctx = mctx;
751 xfr->refcount = 0;
752 xfr->zone = NULL;
753 dns_zone_iattach(zone, &xfr->zone);
754 xfr->task = NULL;
755 isc_task_attach(task, &xfr->task);
756 xfr->timer = NULL;
757 xfr->socketmgr = socketmgr;
758 xfr->done = NULL;
760 xfr->connects = 0;
761 xfr->sends = 0;
762 xfr->recvs = 0;
763 xfr->shuttingdown = ISC_FALSE;
765 dns_name_init(&xfr->name, NULL);
766 xfr->rdclass = rdclass;
767 isc_random_get(&tmp);
768 xfr->checkid = ISC_TRUE;
769 xfr->id = (isc_uint16_t)(tmp & 0xffff);
770 xfr->reqtype = reqtype;
772 /* sockaddr */
773 xfr->socket = NULL;
774 /* qbuffer */
775 /* qbuffer_data */
776 /* tcpmsg */
777 xfr->tcpmsg_valid = ISC_FALSE;
779 xfr->db = NULL;
780 if (db != NULL)
781 dns_db_attach(db, &xfr->db);
782 xfr->ver = NULL;
783 dns_diff_init(xfr->mctx, &xfr->diff);
784 xfr->difflen = 0;
786 if (reqtype == dns_rdatatype_soa)
787 xfr->state = XFRST_SOAQUERY;
788 else
789 xfr->state = XFRST_INITIALSOA;
790 /* end_serial */
792 xfr->nmsg = 0;
794 xfr->tsigkey = NULL;
795 if (tsigkey != NULL)
796 dns_tsigkey_attach(tsigkey, &xfr->tsigkey);
797 xfr->lasttsig = NULL;
798 xfr->tsigctx = NULL;
799 xfr->sincetsig = 0;
800 xfr->is_ixfr = ISC_FALSE;
802 /* ixfr.request_serial */
803 /* ixfr.current_serial */
804 xfr->ixfr.journal = NULL;
806 xfr->axfr.add_func = NULL;
807 xfr->axfr.add_private = NULL;
809 CHECK(dns_name_dup(zonename, mctx, &xfr->name));
811 CHECK(isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
812 task, xfrin_timeout, xfr, &xfr->timer));
813 CHECK(dns_timer_setidle(xfr->timer,
814 dns_zone_getmaxxfrin(xfr->zone),
815 dns_zone_getidlein(xfr->zone),
816 ISC_FALSE));
818 xfr->masteraddr = *masteraddr;
820 INSIST(isc_sockaddr_pf(masteraddr) == isc_sockaddr_pf(sourceaddr));
821 xfr->sourceaddr = *sourceaddr;
822 isc_sockaddr_setport(&xfr->sourceaddr, 0);
824 isc_buffer_init(&xfr->qbuffer, xfr->qbuffer_data,
825 sizeof(xfr->qbuffer_data));
827 xfr->magic = XFRIN_MAGIC;
828 *xfrp = xfr;
829 return (ISC_R_SUCCESS);
831 failure:
832 if (xfr->timer != NULL)
833 isc_timer_detach(&xfr->timer);
834 if (dns_name_dynamic(&xfr->name))
835 dns_name_free(&xfr->name, xfr->mctx);
836 if (xfr->tsigkey != NULL)
837 dns_tsigkey_detach(&xfr->tsigkey);
838 if (xfr->db != NULL)
839 dns_db_detach(&xfr->db);
840 isc_task_detach(&xfr->task);
841 dns_zone_idetach(&xfr->zone);
842 isc_mem_put(mctx, xfr, sizeof(*xfr));
844 return (result);
847 static isc_result_t
848 xfrin_start(dns_xfrin_ctx_t *xfr) {
849 isc_result_t result;
850 CHECK(isc_socket_create(xfr->socketmgr,
851 isc_sockaddr_pf(&xfr->sourceaddr),
852 isc_sockettype_tcp,
853 &xfr->socket));
854 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
855 CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr));
856 #endif
857 CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task,
858 xfrin_connect_done, xfr));
859 xfr->connects++;
860 return (ISC_R_SUCCESS);
861 failure:
862 xfrin_fail(xfr, result, "failed setting up socket");
863 return (result);
866 /* XXX the resolver could use this, too */
868 static isc_result_t
869 render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf) {
870 dns_compress_t cctx;
871 isc_boolean_t cleanup_cctx = ISC_FALSE;
872 isc_result_t result;
874 CHECK(dns_compress_init(&cctx, -1, mctx));
875 cleanup_cctx = ISC_TRUE;
876 CHECK(dns_message_renderbegin(msg, &cctx, buf));
877 CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
878 CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
879 CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0));
880 CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0));
881 CHECK(dns_message_renderend(msg));
882 result = ISC_R_SUCCESS;
883 failure:
884 if (cleanup_cctx)
885 dns_compress_invalidate(&cctx);
886 return (result);
890 * A connection has been established.
892 static void
893 xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
894 isc_socket_connev_t *cev = (isc_socket_connev_t *) event;
895 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
896 isc_result_t evresult = cev->result;
897 isc_result_t result;
898 char sourcetext[ISC_SOCKADDR_FORMATSIZE];
899 isc_sockaddr_t sockaddr;
901 REQUIRE(VALID_XFRIN(xfr));
903 UNUSED(task);
905 INSIST(event->ev_type == ISC_SOCKEVENT_CONNECT);
906 isc_event_free(&event);
908 xfr->connects--;
909 if (xfr->shuttingdown) {
910 maybe_free(xfr);
911 return;
914 CHECK(evresult);
915 result = isc_socket_getsockname(xfr->socket, &sockaddr);
916 if (result == ISC_R_SUCCESS) {
917 isc_sockaddr_format(&sockaddr, sourcetext, sizeof(sourcetext));
918 } else
919 strcpy(sourcetext, "<UNKNOWN>");
920 xfrin_log(xfr, ISC_LOG_INFO, "connected using %s", sourcetext);
922 dns_tcpmsg_init(xfr->mctx, xfr->socket, &xfr->tcpmsg);
923 xfr->tcpmsg_valid = ISC_TRUE;
925 CHECK(xfrin_send_request(xfr));
926 failure:
927 if (result != ISC_R_SUCCESS)
928 xfrin_fail(xfr, result, "failed to connect");
932 * Convert a tuple into a dns_name_t suitable for inserting
933 * into the given dns_message_t.
935 static isc_result_t
936 tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target)
938 isc_result_t result;
939 dns_rdata_t *rdata = NULL;
940 dns_rdatalist_t *rdl = NULL;
941 dns_rdataset_t *rds = NULL;
942 dns_name_t *name = NULL;
944 REQUIRE(target != NULL && *target == NULL);
946 CHECK(dns_message_gettemprdata(msg, &rdata));
947 dns_rdata_init(rdata);
948 dns_rdata_clone(&tuple->rdata, rdata);
950 CHECK(dns_message_gettemprdatalist(msg, &rdl));
951 dns_rdatalist_init(rdl);
952 rdl->type = tuple->rdata.type;
953 rdl->rdclass = tuple->rdata.rdclass;
954 rdl->ttl = tuple->ttl;
955 ISC_LIST_APPEND(rdl->rdata, rdata, link);
957 CHECK(dns_message_gettemprdataset(msg, &rds));
958 dns_rdataset_init(rds);
959 CHECK(dns_rdatalist_tordataset(rdl, rds));
961 CHECK(dns_message_gettempname(msg, &name));
962 dns_name_init(name, NULL);
963 dns_name_clone(&tuple->name, name);
964 ISC_LIST_APPEND(name->list, rds, link);
966 *target = name;
967 return (ISC_R_SUCCESS);
969 failure:
971 if (rds != NULL) {
972 dns_rdataset_disassociate(rds);
973 dns_message_puttemprdataset(msg, &rds);
975 if (rdl != NULL) {
976 ISC_LIST_UNLINK(rdl->rdata, rdata, link);
977 dns_message_puttemprdatalist(msg, &rdl);
979 if (rdata != NULL)
980 dns_message_puttemprdata(msg, &rdata);
982 return (result);
987 * Build an *XFR request and send its length prefix.
989 static isc_result_t
990 xfrin_send_request(dns_xfrin_ctx_t *xfr) {
991 isc_result_t result;
992 isc_region_t region;
993 isc_region_t lregion;
994 dns_rdataset_t *qrdataset = NULL;
995 dns_message_t *msg = NULL;
996 unsigned char length[2];
997 dns_difftuple_t *soatuple = NULL;
998 dns_name_t *qname = NULL;
999 dns_dbversion_t *ver = NULL;
1000 dns_name_t *msgsoaname = NULL;
1002 /* Create the request message */
1003 CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg));
1004 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
1006 /* Create a name for the question section. */
1007 CHECK(dns_message_gettempname(msg, &qname));
1008 dns_name_init(qname, NULL);
1009 dns_name_clone(&xfr->name, qname);
1011 /* Formulate the question and attach it to the question name. */
1012 CHECK(dns_message_gettemprdataset(msg, &qrdataset));
1013 dns_rdataset_init(qrdataset);
1014 dns_rdataset_makequestion(qrdataset, xfr->rdclass, xfr->reqtype);
1015 ISC_LIST_APPEND(qname->list, qrdataset, link);
1016 qrdataset = NULL;
1018 dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
1019 qname = NULL;
1021 if (xfr->reqtype == dns_rdatatype_ixfr) {
1022 /* Get the SOA and add it to the authority section. */
1023 /* XXX is using the current version the right thing? */
1024 dns_db_currentversion(xfr->db, &ver);
1025 CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx,
1026 DNS_DIFFOP_EXISTS, &soatuple));
1027 xfr->ixfr.request_serial = dns_soa_getserial(&soatuple->rdata);
1028 xfr->ixfr.current_serial = xfr->ixfr.request_serial;
1029 xfrin_log(xfr, ISC_LOG_DEBUG(3),
1030 "requesting IXFR for serial %u",
1031 xfr->ixfr.request_serial);
1033 CHECK(tuple2msgname(soatuple, msg, &msgsoaname));
1034 dns_message_addname(msg, msgsoaname, DNS_SECTION_AUTHORITY);
1035 } else if (xfr->reqtype == dns_rdatatype_soa)
1036 CHECK(dns_db_getsoaserial(xfr->db, NULL,
1037 &xfr->ixfr.request_serial));
1039 xfr->checkid = ISC_TRUE;
1040 xfr->id++;
1041 msg->id = xfr->id;
1043 CHECK(render(msg, xfr->mctx, &xfr->qbuffer));
1046 * Free the last tsig, if there is one.
1048 if (xfr->lasttsig != NULL)
1049 isc_buffer_free(&xfr->lasttsig);
1052 * Save the query TSIG and don't let message_destroy free it.
1054 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
1056 isc_buffer_usedregion(&xfr->qbuffer, &region);
1057 INSIST(region.length <= 65535);
1059 length[0] = region.length >> 8;
1060 length[1] = region.length & 0xFF;
1061 lregion.base = length;
1062 lregion.length = 2;
1063 CHECK(isc_socket_send(xfr->socket, &lregion, xfr->task,
1064 xfrin_sendlen_done, xfr));
1065 xfr->sends++;
1067 failure:
1068 if (qname != NULL)
1069 dns_message_puttempname(msg, &qname);
1070 if (qrdataset != NULL)
1071 dns_message_puttemprdataset(msg, &qrdataset);
1072 if (msg != NULL)
1073 dns_message_destroy(&msg);
1074 if (soatuple != NULL)
1075 dns_difftuple_free(&soatuple);
1076 if (ver != NULL)
1077 dns_db_closeversion(xfr->db, &ver, ISC_FALSE);
1078 return (result);
1081 /* XXX there should be library support for sending DNS TCP messages */
1083 static void
1084 xfrin_sendlen_done(isc_task_t *task, isc_event_t *event) {
1085 isc_socketevent_t *sev = (isc_socketevent_t *) event;
1086 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1087 isc_result_t evresult = sev->result;
1088 isc_result_t result;
1089 isc_region_t region;
1091 REQUIRE(VALID_XFRIN(xfr));
1093 UNUSED(task);
1095 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1096 isc_event_free(&event);
1098 xfr->sends--;
1099 if (xfr->shuttingdown) {
1100 maybe_free(xfr);
1101 return;
1104 xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request length prefix");
1105 CHECK(evresult);
1107 isc_buffer_usedregion(&xfr->qbuffer, &region);
1108 CHECK(isc_socket_send(xfr->socket, &region, xfr->task,
1109 xfrin_send_done, xfr));
1110 xfr->sends++;
1111 failure:
1112 if (result != ISC_R_SUCCESS)
1113 xfrin_fail(xfr, result, "failed sending request length prefix");
1117 static void
1118 xfrin_send_done(isc_task_t *task, isc_event_t *event) {
1119 isc_socketevent_t *sev = (isc_socketevent_t *) event;
1120 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1121 isc_result_t result;
1123 REQUIRE(VALID_XFRIN(xfr));
1125 UNUSED(task);
1127 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1129 xfr->sends--;
1130 xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request data");
1131 CHECK(sev->result);
1133 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
1134 xfrin_recv_done, xfr));
1135 xfr->recvs++;
1136 failure:
1137 isc_event_free(&event);
1138 if (result != ISC_R_SUCCESS)
1139 xfrin_fail(xfr, result, "failed sending request data");
1143 static void
1144 xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
1145 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) ev->ev_arg;
1146 isc_result_t result;
1147 dns_message_t *msg = NULL;
1148 dns_name_t *name;
1149 dns_tcpmsg_t *tcpmsg;
1150 dns_name_t *tsigowner = NULL;
1152 REQUIRE(VALID_XFRIN(xfr));
1154 UNUSED(task);
1156 INSIST(ev->ev_type == DNS_EVENT_TCPMSG);
1157 tcpmsg = ev->ev_sender;
1158 isc_event_free(&ev);
1160 xfr->recvs--;
1161 if (xfr->shuttingdown) {
1162 maybe_free(xfr);
1163 return;
1166 CHECK(tcpmsg->result);
1168 xfrin_log(xfr, ISC_LOG_DEBUG(7), "received %u bytes",
1169 tcpmsg->buffer.used);
1171 CHECK(isc_timer_touch(xfr->timer));
1173 CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTPARSE, &msg));
1175 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
1176 CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
1177 msg->tsigctx = xfr->tsigctx;
1178 if (xfr->nmsg > 0)
1179 msg->tcp_continuation = 1;
1181 result = dns_message_parse(msg, &tcpmsg->buffer,
1182 DNS_MESSAGEPARSE_PRESERVEORDER);
1184 if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror ||
1185 (xfr->checkid && msg->id != xfr->id)) {
1186 if (result == ISC_R_SUCCESS)
1187 result = ISC_RESULTCLASS_DNSRCODE + msg->rcode; /*XXX*/
1188 if (result == ISC_R_SUCCESS || result == DNS_R_NOERROR)
1189 result = DNS_R_UNEXPECTEDID;
1190 if (xfr->reqtype == dns_rdatatype_axfr ||
1191 xfr->reqtype == dns_rdatatype_soa)
1192 FAIL(result);
1193 xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
1194 isc_result_totext(result));
1195 try_axfr:
1196 dns_message_destroy(&msg);
1197 xfrin_reset(xfr);
1198 xfr->reqtype = dns_rdatatype_soa;
1199 xfr->state = XFRST_SOAQUERY;
1200 (void)xfrin_start(xfr);
1201 return;
1205 * Does the server know about IXFR? If it doesn't we will get
1206 * a message with a empty answer section or a potentially a CNAME /
1207 * DNAME, the later is handled by xfr_rr() which will return FORMERR
1208 * if the first RR in the answer section is not a SOA record.
1210 if (xfr->reqtype == dns_rdatatype_ixfr &&
1211 xfr->state == XFRST_INITIALSOA &&
1212 msg->counts[DNS_SECTION_ANSWER] == 0) {
1213 xfrin_log(xfr, ISC_LOG_DEBUG(3),
1214 "empty answer section, retrying with AXFR");
1215 goto try_axfr;
1218 if (xfr->reqtype == dns_rdatatype_soa &&
1219 (msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
1220 FAIL(DNS_R_NOTAUTHORITATIVE);
1224 result = dns_message_checksig(msg, dns_zone_getview(xfr->zone));
1225 if (result != ISC_R_SUCCESS) {
1226 xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
1227 isc_result_totext(result));
1228 FAIL(result);
1231 for (result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
1232 result == ISC_R_SUCCESS;
1233 result = dns_message_nextname(msg, DNS_SECTION_ANSWER))
1235 dns_rdataset_t *rds;
1237 name = NULL;
1238 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
1239 for (rds = ISC_LIST_HEAD(name->list);
1240 rds != NULL;
1241 rds = ISC_LIST_NEXT(rds, link))
1243 for (result = dns_rdataset_first(rds);
1244 result == ISC_R_SUCCESS;
1245 result = dns_rdataset_next(rds))
1247 dns_rdata_t rdata = DNS_RDATA_INIT;
1248 dns_rdataset_current(rds, &rdata);
1249 CHECK(xfr_rr(xfr, name, rds->ttl, &rdata));
1253 if (result != ISC_R_NOMORE)
1254 goto failure;
1256 if (dns_message_gettsig(msg, &tsigowner) != NULL) {
1258 * Reset the counter.
1260 xfr->sincetsig = 0;
1263 * Free the last tsig, if there is one.
1265 if (xfr->lasttsig != NULL)
1266 isc_buffer_free(&xfr->lasttsig);
1269 * Update the last tsig pointer.
1271 CHECK(dns_message_getquerytsig(msg, xfr->mctx,
1272 &xfr->lasttsig));
1274 } else if (dns_message_gettsigkey(msg) != NULL) {
1275 xfr->sincetsig++;
1276 if (xfr->sincetsig > 100 ||
1277 xfr->nmsg == 0 || xfr->state == XFRST_END)
1279 result = DNS_R_EXPECTEDTSIG;
1280 goto failure;
1285 * Update the number of messages received.
1287 xfr->nmsg++;
1290 * Copy the context back.
1292 xfr->tsigctx = msg->tsigctx;
1294 dns_message_destroy(&msg);
1296 if (xfr->state == XFRST_GOTSOA) {
1297 xfr->reqtype = dns_rdatatype_axfr;
1298 xfr->state = XFRST_INITIALSOA;
1299 CHECK(xfrin_send_request(xfr));
1300 } else if (xfr->state == XFRST_END) {
1302 * Inform the caller we succeeded.
1304 if (xfr->done != NULL) {
1305 (xfr->done)(xfr->zone, ISC_R_SUCCESS);
1306 xfr->done = NULL;
1309 * We should have no outstanding events at this
1310 * point, thus maybe_free() should succeed.
1312 xfr->shuttingdown = ISC_TRUE;
1313 maybe_free(xfr);
1314 } else {
1316 * Read the next message.
1318 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
1319 xfrin_recv_done, xfr));
1320 xfr->recvs++;
1322 return;
1324 failure:
1325 if (msg != NULL)
1326 dns_message_destroy(&msg);
1327 if (result != ISC_R_SUCCESS)
1328 xfrin_fail(xfr, result, "failed while receiving responses");
1331 static void
1332 xfrin_timeout(isc_task_t *task, isc_event_t *event) {
1333 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1335 REQUIRE(VALID_XFRIN(xfr));
1337 UNUSED(task);
1339 isc_event_free(&event);
1341 * This will log "giving up: timeout".
1343 xfrin_fail(xfr, ISC_R_TIMEDOUT, "giving up");
1346 static void
1347 maybe_free(dns_xfrin_ctx_t *xfr) {
1348 REQUIRE(VALID_XFRIN(xfr));
1350 if (! xfr->shuttingdown || xfr->refcount != 0 ||
1351 xfr->connects != 0 || xfr->sends != 0 ||
1352 xfr->recvs != 0)
1353 return;
1355 xfrin_log(xfr, ISC_LOG_INFO, "end of transfer");
1357 if (xfr->socket != NULL)
1358 isc_socket_detach(&xfr->socket);
1360 if (xfr->timer != NULL)
1361 isc_timer_detach(&xfr->timer);
1363 if (xfr->task != NULL)
1364 isc_task_detach(&xfr->task);
1366 if (xfr->tsigkey != NULL)
1367 dns_tsigkey_detach(&xfr->tsigkey);
1369 if (xfr->lasttsig != NULL)
1370 isc_buffer_free(&xfr->lasttsig);
1372 dns_diff_clear(&xfr->diff);
1374 if (xfr->ixfr.journal != NULL)
1375 dns_journal_destroy(&xfr->ixfr.journal);
1377 if (xfr->axfr.add_private != NULL)
1378 (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
1380 if (xfr->tcpmsg_valid)
1381 dns_tcpmsg_invalidate(&xfr->tcpmsg);
1383 if ((xfr->name.attributes & DNS_NAMEATTR_DYNAMIC) != 0)
1384 dns_name_free(&xfr->name, xfr->mctx);
1386 if (xfr->ver != NULL)
1387 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
1389 if (xfr->db != NULL)
1390 dns_db_detach(&xfr->db);
1392 if (xfr->zone != NULL)
1393 dns_zone_idetach(&xfr->zone);
1395 isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
1399 * Log incoming zone transfer messages in a format like
1400 * transfer of <zone> from <address>: <message>
1402 static void
1403 xfrin_logv(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
1404 isc_sockaddr_t *masteraddr, const char *fmt, va_list ap)
1406 char zntext[DNS_NAME_FORMATSIZE];
1407 char mastertext[ISC_SOCKADDR_FORMATSIZE];
1408 char classtext[DNS_RDATACLASS_FORMATSIZE];
1409 char msgtext[2048];
1411 dns_name_format(zonename, zntext, sizeof(zntext));
1412 dns_rdataclass_format(rdclass, classtext, sizeof(classtext));
1413 isc_sockaddr_format(masteraddr, mastertext, sizeof(mastertext));
1414 vsnprintf(msgtext, sizeof(msgtext), fmt, ap);
1416 isc_log_write(dns_lctx, DNS_LOGCATEGORY_XFER_IN,
1417 DNS_LOGMODULE_XFER_IN, level,
1418 "transfer of '%s/%s' from %s: %s",
1419 zntext, classtext, mastertext, msgtext);
1423 * Logging function for use when a xfrin_ctx_t has not yet been created.
1426 static void
1427 xfrin_log1(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
1428 isc_sockaddr_t *masteraddr, const char *fmt, ...)
1430 va_list ap;
1432 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
1433 return;
1435 va_start(ap, fmt);
1436 xfrin_logv(level, zonename, rdclass, masteraddr, fmt, ap);
1437 va_end(ap);
1441 * Logging function for use when there is a xfrin_ctx_t.
1444 static void
1445 xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
1447 va_list ap;
1449 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
1450 return;
1452 va_start(ap, fmt);
1453 xfrin_logv(level, &xfr->name, xfr->rdclass, &xfr->masteraddr, fmt, ap);
1454 va_end(ap);