Add BIND 9.2.4rc7.
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / xfrin.c
blob4fcd895d1ed3f07ce0209592fca2349e9905d363
1 /*
2 * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
3 * Copyright (C) 1999-2001, 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.5 2004/03/09 06:11:11 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 end_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 dns_tsigkey_t *tsigkey,
189 dns_xfrin_ctx_t **xfrp);
191 static isc_result_t axfr_init(dns_xfrin_ctx_t *xfr);
192 static isc_result_t axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);
193 static isc_result_t axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
194 dns_name_t *name, dns_ttl_t ttl,
195 dns_rdata_t *rdata);
196 static isc_result_t axfr_apply(dns_xfrin_ctx_t *xfr);
197 static isc_result_t axfr_commit(dns_xfrin_ctx_t *xfr);
199 static isc_result_t ixfr_init(dns_xfrin_ctx_t *xfr);
200 static isc_result_t ixfr_apply(dns_xfrin_ctx_t *xfr);
201 static isc_result_t ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
202 dns_name_t *name, dns_ttl_t ttl,
203 dns_rdata_t *rdata);
204 static isc_result_t ixfr_commit(dns_xfrin_ctx_t *xfr);
206 static isc_result_t xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name,
207 isc_uint32_t ttl, dns_rdata_t *rdata);
209 static isc_result_t xfrin_start(dns_xfrin_ctx_t *xfr);
211 static void xfrin_connect_done(isc_task_t *task, isc_event_t *event);
212 static isc_result_t xfrin_send_request(dns_xfrin_ctx_t *xfr);
213 static void xfrin_send_done(isc_task_t *task, isc_event_t *event);
214 static void xfrin_sendlen_done(isc_task_t *task, isc_event_t *event);
215 static void xfrin_recv_done(isc_task_t *task, isc_event_t *event);
216 static void xfrin_timeout(isc_task_t *task, isc_event_t *event);
218 static void maybe_free(dns_xfrin_ctx_t *xfr);
220 static void
221 xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg);
222 static isc_result_t
223 render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf);
225 static void
226 xfrin_logv(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
227 isc_sockaddr_t *masteraddr, const char *fmt, va_list ap)
228 ISC_FORMAT_PRINTF(5, 0);
230 static void
231 xfrin_log1(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
232 isc_sockaddr_t *masteraddr, const char *fmt, ...)
233 ISC_FORMAT_PRINTF(5, 6);
235 static void
236 xfrin_log(dns_xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...)
237 ISC_FORMAT_PRINTF(3, 4);
239 /**************************************************************************/
241 * AXFR handling
244 static isc_result_t
245 axfr_init(dns_xfrin_ctx_t *xfr) {
246 isc_result_t result;
248 xfr->is_ixfr = ISC_FALSE;
250 if (xfr->db != NULL)
251 dns_db_detach(&xfr->db);
253 CHECK(axfr_makedb(xfr, &xfr->db));
254 CHECK(dns_db_beginload(xfr->db, &xfr->axfr.add_func,
255 &xfr->axfr.add_private));
256 result = ISC_R_SUCCESS;
257 failure:
258 return (result);
261 static isc_result_t
262 axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
263 return (dns_db_create(xfr->mctx, /* XXX */
264 "rbt", /* XXX guess */
265 &xfr->name,
266 dns_dbtype_zone,
267 xfr->rdclass,
268 0, NULL, /* XXX guess */
269 dbp));
272 static isc_result_t
273 axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
274 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
276 isc_result_t result;
278 dns_difftuple_t *tuple = NULL;
279 CHECK(dns_difftuple_create(xfr->diff.mctx, op,
280 name, ttl, rdata, &tuple));
281 dns_diff_append(&xfr->diff, &tuple);
282 if (++xfr->difflen > 100)
283 CHECK(axfr_apply(xfr));
284 result = ISC_R_SUCCESS;
285 failure:
286 return (result);
290 * Store a set of AXFR RRs in the database.
292 static isc_result_t
293 axfr_apply(dns_xfrin_ctx_t *xfr) {
294 isc_result_t result;
296 CHECK(dns_diff_load(&xfr->diff,
297 xfr->axfr.add_func, xfr->axfr.add_private));
298 xfr->difflen = 0;
299 dns_diff_clear(&xfr->diff);
300 result = ISC_R_SUCCESS;
301 failure:
302 return (result);
305 static isc_result_t
306 axfr_commit(dns_xfrin_ctx_t *xfr) {
307 isc_result_t result;
309 CHECK(axfr_apply(xfr));
310 CHECK(dns_db_endload(xfr->db, &xfr->axfr.add_private));
311 CHECK(dns_zone_replacedb(xfr->zone, xfr->db, ISC_TRUE));
313 result = ISC_R_SUCCESS;
314 failure:
315 return (result);
318 /**************************************************************************/
320 * IXFR handling
323 static isc_result_t
324 ixfr_init(dns_xfrin_ctx_t *xfr) {
325 isc_result_t result;
326 char *journalfile;
328 if (xfr->reqtype != dns_rdatatype_ixfr) {
329 xfrin_log(xfr, ISC_LOG_ERROR,
330 "got incremental response to AXFR request");
331 return (DNS_R_FORMERR);
334 xfr->is_ixfr = ISC_TRUE;
335 INSIST(xfr->db != NULL);
336 xfr->difflen = 0;
338 journalfile = dns_zone_getjournal(xfr->zone);
339 if (journalfile != NULL)
340 CHECK(dns_journal_open(xfr->mctx, journalfile,
341 ISC_TRUE, &xfr->ixfr.journal));
343 result = ISC_R_SUCCESS;
344 failure:
345 return (result);
348 static isc_result_t
349 ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
350 dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
352 isc_result_t result;
354 dns_difftuple_t *tuple = NULL;
355 CHECK(dns_difftuple_create(xfr->diff.mctx, op,
356 name, ttl, rdata, &tuple));
357 dns_diff_append(&xfr->diff, &tuple);
358 if (++xfr->difflen > 100)
359 CHECK(ixfr_apply(xfr));
360 result = ISC_R_SUCCESS;
361 failure:
362 return (result);
366 * Apply a set of IXFR changes to the database.
368 static isc_result_t
369 ixfr_apply(dns_xfrin_ctx_t *xfr) {
370 isc_result_t result;
372 if (xfr->ver == NULL) {
373 CHECK(dns_db_newversion(xfr->db, &xfr->ver));
374 if (xfr->ixfr.journal != NULL)
375 CHECK(dns_journal_begin_transaction(xfr->ixfr.journal));
377 CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver));
378 if (xfr->ixfr.journal != NULL)
379 dns_journal_writediff(xfr->ixfr.journal, &xfr->diff);
380 dns_diff_clear(&xfr->diff);
381 xfr->difflen = 0;
382 result = ISC_R_SUCCESS;
383 failure:
384 return (result);
387 static isc_result_t
388 ixfr_commit(dns_xfrin_ctx_t *xfr) {
389 isc_result_t result;
391 CHECK(ixfr_apply(xfr));
392 if (xfr->ver != NULL) {
393 /* XXX enter ready-to-commit state here */
394 if (xfr->ixfr.journal != NULL)
395 CHECK(dns_journal_commit(xfr->ixfr.journal));
396 dns_db_closeversion(xfr->db, &xfr->ver, ISC_TRUE);
397 dns_zone_markdirty(xfr->zone);
399 result = ISC_R_SUCCESS;
400 failure:
401 return (result);
404 /**************************************************************************/
406 * Common AXFR/IXFR protocol code
410 * Handle a single incoming resource record according to the current
411 * state.
413 static isc_result_t
414 xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
415 dns_rdata_t *rdata)
417 isc_result_t result;
419 redo:
420 switch (xfr->state) {
421 case XFRST_SOAQUERY:
422 if (rdata->type != dns_rdatatype_soa) {
423 xfrin_log(xfr, ISC_LOG_ERROR,
424 "non-SOA response to SOA query");
425 FAIL(DNS_R_FORMERR);
427 xfr->end_serial = dns_soa_getserial(rdata);
428 if (!DNS_SERIAL_GT(xfr->end_serial,
429 xfr->ixfr.request_serial) &&
430 !dns_zone_isforced(xfr->zone)) {
431 xfrin_log(xfr, ISC_LOG_DEBUG(3),
432 "requested serial %u, "
433 "master has %u, not updating",
434 xfr->ixfr.request_serial, xfr->end_serial);
435 FAIL(DNS_R_UPTODATE);
437 xfr->state = XFRST_GOTSOA;
438 break;
440 case XFRST_GOTSOA:
442 * Skip other records in the answer section.
444 break;
446 case XFRST_INITIALSOA:
447 if (rdata->type != dns_rdatatype_soa) {
448 xfrin_log(xfr, ISC_LOG_ERROR,
449 "first RR in zone transfer must be SOA");
450 FAIL(DNS_R_FORMERR);
453 * Remember the serial number in the intial SOA.
454 * We need it to recognize the end of an IXFR.
456 xfr->end_serial = dns_soa_getserial(rdata);
457 if (xfr->reqtype == dns_rdatatype_ixfr &&
458 ! DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial)
459 && !dns_zone_isforced(xfr->zone))
462 * This must be the single SOA record that is
463 * sent when the current version on the master
464 * is not newer than the version in the request.
466 xfrin_log(xfr, ISC_LOG_DEBUG(3),
467 "requested serial %u, "
468 "master has %u, not updating",
469 xfr->ixfr.request_serial, xfr->end_serial);
470 FAIL(DNS_R_UPTODATE);
472 if (xfr->reqtype == dns_rdatatype_axfr)
473 xfr->checkid = ISC_FALSE;
474 xfr->state = XFRST_FIRSTDATA;
475 break;
477 case XFRST_FIRSTDATA:
479 * If the transfer begins with one SOA record, it is an AXFR,
480 * if it begins with two SOAs, it is an IXFR.
482 if (xfr->reqtype == dns_rdatatype_ixfr &&
483 rdata->type == dns_rdatatype_soa &&
484 xfr->ixfr.request_serial == dns_soa_getserial(rdata)) {
485 xfrin_log(xfr, ISC_LOG_DEBUG(3),
486 "got incremental response");
487 CHECK(ixfr_init(xfr));
488 xfr->state = XFRST_IXFR_DELSOA;
489 } else {
490 xfrin_log(xfr, ISC_LOG_DEBUG(3),
491 "got nonincremental response");
492 CHECK(axfr_init(xfr));
493 xfr->state = XFRST_AXFR;
495 goto redo;
497 case XFRST_IXFR_DELSOA:
498 INSIST(rdata->type == dns_rdatatype_soa);
499 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
500 xfr->state = XFRST_IXFR_DEL;
501 break;
503 case XFRST_IXFR_DEL:
504 if (rdata->type == dns_rdatatype_soa) {
505 isc_uint32_t soa_serial = dns_soa_getserial(rdata);
506 xfr->state = XFRST_IXFR_ADDSOA;
507 xfr->ixfr.end_serial = soa_serial;
508 goto redo;
510 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
511 break;
513 case XFRST_IXFR_ADDSOA:
514 INSIST(rdata->type == dns_rdatatype_soa);
515 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
516 xfr->state = XFRST_IXFR_ADD;
517 break;
519 case XFRST_IXFR_ADD:
520 if (rdata->type == dns_rdatatype_soa) {
521 isc_uint32_t soa_serial = dns_soa_getserial(rdata);
522 CHECK(ixfr_commit(xfr));
523 if (soa_serial == xfr->end_serial) {
524 xfr->state = XFRST_END;
525 break;
526 } else {
527 xfr->state = XFRST_IXFR_DELSOA;
528 goto redo;
531 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
532 break;
534 case XFRST_AXFR:
536 * Old BINDs sent cross class A records for non IN classes.
538 if (rdata->type == dns_rdatatype_a &&
539 rdata->rdclass != xfr->rdclass &&
540 xfr->rdclass != dns_rdataclass_in)
541 break;
542 CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
543 if (rdata->type == dns_rdatatype_soa) {
544 CHECK(axfr_commit(xfr));
545 xfr->state = XFRST_END;
546 break;
548 break;
549 case XFRST_END:
550 FAIL(DNS_R_EXTRADATA);
551 default:
552 INSIST(0);
553 break;
555 result = ISC_R_SUCCESS;
556 failure:
557 return (result);
560 isc_result_t
561 dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
562 isc_sockaddr_t *masteraddr, dns_tsigkey_t *tsigkey,
563 isc_mem_t *mctx, isc_timermgr_t *timermgr,
564 isc_socketmgr_t *socketmgr, isc_task_t *task,
565 dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
567 dns_name_t *zonename = dns_zone_getorigin(zone);
568 dns_xfrin_ctx_t *xfr;
569 isc_result_t result;
570 dns_db_t *db = NULL;
572 REQUIRE(xfrp != NULL && *xfrp == NULL);
574 (void)dns_zone_getdb(zone, &db);
576 CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename,
577 dns_zone_getclass(zone), xfrtype, masteraddr,
578 tsigkey, &xfr));
580 CHECK(xfrin_start(xfr));
582 xfr->done = done;
583 xfr->refcount++;
584 *xfrp = xfr;
586 failure:
587 if (db != NULL)
588 dns_db_detach(&db);
589 if (result != ISC_R_SUCCESS)
590 xfrin_log1(ISC_LOG_ERROR, zonename, dns_zone_getclass(zone),
591 masteraddr, "zone transfer setup failed");
592 return (result);
595 void
596 dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
597 if (! xfr->shuttingdown)
598 xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
601 void
602 dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target) {
603 REQUIRE(target != NULL && *target == NULL);
604 source->refcount++;
605 *target = source;
608 void
609 dns_xfrin_detach(dns_xfrin_ctx_t **xfrp) {
610 dns_xfrin_ctx_t *xfr = *xfrp;
611 INSIST(xfr->refcount > 0);
612 xfr->refcount--;
613 maybe_free(xfr);
614 *xfrp = NULL;
617 static void
618 xfrin_cancelio(dns_xfrin_ctx_t *xfr) {
619 if (xfr->connects > 0) {
620 isc_socket_cancel(xfr->socket, xfr->task,
621 ISC_SOCKCANCEL_CONNECT);
622 } else if (xfr->recvs > 0) {
623 dns_tcpmsg_cancelread(&xfr->tcpmsg);
624 } else if (xfr->sends > 0) {
625 isc_socket_cancel(xfr->socket, xfr->task,
626 ISC_SOCKCANCEL_SEND);
630 static void
631 xfrin_reset(dns_xfrin_ctx_t *xfr) {
632 REQUIRE(VALID_XFRIN(xfr));
634 xfrin_log(xfr, ISC_LOG_INFO, "resetting");
636 xfrin_cancelio(xfr);
638 if (xfr->socket != NULL)
639 isc_socket_detach(&xfr->socket);
641 if (xfr->lasttsig != NULL)
642 isc_buffer_free(&xfr->lasttsig);
644 dns_diff_clear(&xfr->diff);
645 xfr->difflen = 0;
647 if (xfr->ixfr.journal != NULL)
648 dns_journal_destroy(&xfr->ixfr.journal);
650 if (xfr->axfr.add_private != NULL) {
651 (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
652 xfr->axfr.add_func = NULL;
655 if (xfr->tcpmsg_valid) {
656 dns_tcpmsg_invalidate(&xfr->tcpmsg);
657 xfr->tcpmsg_valid = ISC_FALSE;
660 if (xfr->ver != NULL)
661 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
665 static void
666 xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
667 if (result != DNS_R_UPTODATE) {
668 xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s",
669 msg, isc_result_totext(result));
670 if (xfr->is_ixfr)
671 /* Pass special result code to force AXFR retry */
672 result = DNS_R_BADIXFR;
674 xfrin_cancelio(xfr);
675 if (xfr->done != NULL) {
676 (xfr->done)(xfr->zone, result);
677 xfr->done = NULL;
679 xfr->shuttingdown = ISC_TRUE;
680 maybe_free(xfr);
683 static isc_result_t
684 xfrin_create(isc_mem_t *mctx,
685 dns_zone_t *zone,
686 dns_db_t *db,
687 isc_task_t *task,
688 isc_timermgr_t *timermgr,
689 isc_socketmgr_t *socketmgr,
690 dns_name_t *zonename,
691 dns_rdataclass_t rdclass,
692 dns_rdatatype_t reqtype,
693 isc_sockaddr_t *masteraddr,
694 dns_tsigkey_t *tsigkey,
695 dns_xfrin_ctx_t **xfrp)
697 dns_xfrin_ctx_t *xfr = NULL;
698 isc_result_t result;
699 isc_uint32_t tmp;
701 xfr = isc_mem_get(mctx, sizeof(*xfr));
702 if (xfr == NULL)
703 return (ISC_R_NOMEMORY);
704 xfr->mctx = mctx;
705 xfr->refcount = 0;
706 xfr->zone = NULL;
707 dns_zone_iattach(zone, &xfr->zone);
708 xfr->task = NULL;
709 isc_task_attach(task, &xfr->task);
710 xfr->timer = NULL;
711 xfr->socketmgr = socketmgr;
712 xfr->done = NULL;
714 xfr->connects = 0;
715 xfr->sends = 0;
716 xfr->recvs = 0;
717 xfr->shuttingdown = ISC_FALSE;
719 dns_name_init(&xfr->name, NULL);
720 xfr->rdclass = rdclass;
721 isc_random_get(&tmp);
722 xfr->checkid = ISC_TRUE;
723 xfr->id = (isc_uint16_t)(tmp & 0xffff);
724 xfr->reqtype = reqtype;
726 /* sockaddr */
727 xfr->socket = NULL;
728 /* qbuffer */
729 /* qbuffer_data */
730 /* tcpmsg */
731 xfr->tcpmsg_valid = ISC_FALSE;
733 xfr->db = NULL;
734 if (db != NULL)
735 dns_db_attach(db, &xfr->db);
736 xfr->ver = NULL;
737 dns_diff_init(xfr->mctx, &xfr->diff);
738 xfr->difflen = 0;
740 xfr->state = XFRST_INITIALSOA;
741 /* end_serial */
743 xfr->nmsg = 0;
745 xfr->tsigkey = NULL;
746 if (tsigkey != NULL)
747 dns_tsigkey_attach(tsigkey, &xfr->tsigkey);
748 xfr->lasttsig = NULL;
749 xfr->tsigctx = NULL;
750 xfr->sincetsig = 0;
751 xfr->is_ixfr = ISC_FALSE;
753 /* ixfr.request_serial */
754 /* ixfr.end_serial */
755 xfr->ixfr.journal = NULL;
757 xfr->axfr.add_func = NULL;
758 xfr->axfr.add_private = NULL;
760 CHECK(dns_name_dup(zonename, mctx, &xfr->name));
762 CHECK(isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
763 task, xfrin_timeout, xfr, &xfr->timer));
764 CHECK(dns_timer_setidle(xfr->timer,
765 dns_zone_getmaxxfrin(xfr->zone),
766 dns_zone_getidlein(xfr->zone),
767 ISC_FALSE));
769 xfr->masteraddr = *masteraddr;
771 switch (isc_sockaddr_pf(masteraddr)) {
772 case PF_INET:
773 xfr->sourceaddr = *dns_zone_getxfrsource4(zone);
774 break;
775 case PF_INET6:
776 xfr->sourceaddr = *dns_zone_getxfrsource6(zone);
777 break;
778 default:
779 INSIST(0);
781 isc_sockaddr_setport(&xfr->sourceaddr, 0);
783 isc_buffer_init(&xfr->qbuffer, xfr->qbuffer_data,
784 sizeof(xfr->qbuffer_data));
786 xfr->magic = XFRIN_MAGIC;
787 *xfrp = xfr;
788 return (ISC_R_SUCCESS);
790 failure:
791 xfrin_fail(xfr, result, "failed creating transfer context");
792 return (result);
795 static isc_result_t
796 xfrin_start(dns_xfrin_ctx_t *xfr) {
797 isc_result_t result;
798 CHECK(isc_socket_create(xfr->socketmgr,
799 isc_sockaddr_pf(&xfr->sourceaddr),
800 isc_sockettype_tcp,
801 &xfr->socket));
802 CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr));
803 CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task,
804 xfrin_connect_done, xfr));
805 xfr->connects++;
806 return (ISC_R_SUCCESS);
807 failure:
808 xfrin_fail(xfr, result, "failed setting up socket");
809 return (result);
812 /* XXX the resolver could use this, too */
814 static isc_result_t
815 render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf) {
816 dns_compress_t cctx;
817 isc_boolean_t cleanup_cctx = ISC_FALSE;
818 isc_result_t result;
820 CHECK(dns_compress_init(&cctx, -1, mctx));
821 cleanup_cctx = ISC_TRUE;
822 CHECK(dns_message_renderbegin(msg, &cctx, buf));
823 CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
824 CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
825 CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0));
826 CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0));
827 CHECK(dns_message_renderend(msg));
828 result = ISC_R_SUCCESS;
829 failure:
830 if (cleanup_cctx)
831 dns_compress_invalidate(&cctx);
832 return (result);
836 * A connection has been established.
838 static void
839 xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
840 isc_socket_connev_t *cev = (isc_socket_connev_t *) event;
841 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
842 isc_result_t evresult = cev->result;
843 isc_result_t result;
845 REQUIRE(VALID_XFRIN(xfr));
847 UNUSED(task);
849 INSIST(event->ev_type == ISC_SOCKEVENT_CONNECT);
850 isc_event_free(&event);
852 xfr->connects--;
853 if (xfr->shuttingdown) {
854 maybe_free(xfr);
855 return;
858 CHECK(evresult);
859 xfrin_log(xfr, ISC_LOG_DEBUG(3), "connected");
861 dns_tcpmsg_init(xfr->mctx, xfr->socket, &xfr->tcpmsg);
862 xfr->tcpmsg_valid = ISC_TRUE;
864 CHECK(xfrin_send_request(xfr));
865 failure:
866 if (result != ISC_R_SUCCESS)
867 xfrin_fail(xfr, result, "failed to connect");
871 * Convert a tuple into a dns_name_t suitable for inserting
872 * into the given dns_message_t.
874 static isc_result_t
875 tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target)
877 isc_result_t result;
878 dns_rdata_t *rdata = NULL;
879 dns_rdatalist_t *rdl = NULL;
880 dns_rdataset_t *rds = NULL;
881 dns_name_t *name = NULL;
883 REQUIRE(target != NULL && *target == NULL);
885 CHECK(dns_message_gettemprdata(msg, &rdata));
886 dns_rdata_init(rdata);
887 dns_rdata_clone(&tuple->rdata, rdata);
889 CHECK(dns_message_gettemprdatalist(msg, &rdl));
890 dns_rdatalist_init(rdl);
891 rdl->type = tuple->rdata.type;
892 rdl->rdclass = tuple->rdata.rdclass;
893 rdl->ttl = tuple->ttl;
894 ISC_LIST_APPEND(rdl->rdata, rdata, link);
896 CHECK(dns_message_gettemprdataset(msg, &rds));
897 dns_rdataset_init(rds);
898 CHECK(dns_rdatalist_tordataset(rdl, rds));
900 CHECK(dns_message_gettempname(msg, &name));
901 dns_name_init(name, NULL);
902 dns_name_clone(&tuple->name, name);
903 ISC_LIST_APPEND(name->list, rds, link);
905 *target = name;
906 return (ISC_R_SUCCESS);
908 failure:
910 if (rds != NULL)
911 dns_rdataset_disassociate(rds);
912 dns_message_puttemprdataset(msg, &rds);
913 if (rdl != NULL) {
914 ISC_LIST_UNLINK(rdl->rdata, rdata, link);
915 dns_message_puttemprdatalist(msg, &rdl);
917 if (rdata != NULL)
918 dns_message_puttemprdata(msg, &rdata);
920 return (result);
925 * Build an *XFR request and send its length prefix.
927 static isc_result_t
928 xfrin_send_request(dns_xfrin_ctx_t *xfr) {
929 isc_result_t result;
930 isc_region_t region;
931 isc_region_t lregion;
932 dns_rdataset_t *qrdataset = NULL;
933 dns_message_t *msg = NULL;
934 unsigned char length[2];
935 dns_difftuple_t *soatuple = NULL;
936 dns_name_t *qname = NULL;
937 dns_dbversion_t *ver = NULL;
938 dns_name_t *msgsoaname = NULL;
940 /* Create the request message */
941 CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg));
942 CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
944 /* Create a name for the question section. */
945 CHECK(dns_message_gettempname(msg, &qname));
946 dns_name_init(qname, NULL);
947 dns_name_clone(&xfr->name, qname);
949 /* Formulate the question and attach it to the question name. */
950 CHECK(dns_message_gettemprdataset(msg, &qrdataset));
951 dns_rdataset_init(qrdataset);
952 dns_rdataset_makequestion(qrdataset, xfr->rdclass, xfr->reqtype);
953 ISC_LIST_APPEND(qname->list, qrdataset, link);
954 qrdataset = NULL;
956 dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
957 qname = NULL;
959 if (xfr->reqtype == dns_rdatatype_ixfr) {
960 /* Get the SOA and add it to the authority section. */
961 /* XXX is using the current version the right thing? */
962 dns_db_currentversion(xfr->db, &ver);
963 CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx,
964 DNS_DIFFOP_EXISTS, &soatuple));
965 xfr->ixfr.request_serial = dns_soa_getserial(&soatuple->rdata);
966 xfrin_log(xfr, ISC_LOG_DEBUG(3),
967 "requesting IXFR for serial %u",
968 xfr->ixfr.request_serial);
970 CHECK(tuple2msgname(soatuple, msg, &msgsoaname));
971 dns_message_addname(msg, msgsoaname, DNS_SECTION_AUTHORITY);
974 xfr->checkid = ISC_TRUE;
975 xfr->id++;
976 msg->id = xfr->id;
978 CHECK(render(msg, xfr->mctx, &xfr->qbuffer));
981 * Free the last tsig, if there is one.
983 if (xfr->lasttsig != NULL)
984 isc_buffer_free(&xfr->lasttsig);
987 * Save the query TSIG and don't let message_destroy free it.
989 CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
991 isc_buffer_usedregion(&xfr->qbuffer, &region);
992 INSIST(region.length <= 65535);
994 length[0] = region.length >> 8;
995 length[1] = region.length & 0xFF;
996 lregion.base = length;
997 lregion.length = 2;
998 CHECK(isc_socket_send(xfr->socket, &lregion, xfr->task,
999 xfrin_sendlen_done, xfr));
1000 xfr->sends++;
1002 failure:
1003 if (qname != NULL)
1004 dns_message_puttempname(msg, &qname);
1005 if (qrdataset != NULL)
1006 dns_message_puttemprdataset(msg, &qrdataset);
1007 if (msg != NULL)
1008 dns_message_destroy(&msg);
1009 if (soatuple != NULL)
1010 dns_difftuple_free(&soatuple);
1011 if (ver != NULL)
1012 dns_db_closeversion(xfr->db, &ver, ISC_FALSE);
1013 return (result);
1016 /* XXX there should be library support for sending DNS TCP messages */
1018 static void
1019 xfrin_sendlen_done(isc_task_t *task, isc_event_t *event) {
1020 isc_socketevent_t *sev = (isc_socketevent_t *) event;
1021 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1022 isc_result_t evresult = sev->result;
1023 isc_result_t result;
1024 isc_region_t region;
1026 REQUIRE(VALID_XFRIN(xfr));
1028 UNUSED(task);
1030 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1031 isc_event_free(&event);
1033 xfr->sends--;
1034 if (xfr->shuttingdown) {
1035 maybe_free(xfr);
1036 return;
1039 xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request length prefix");
1040 CHECK(evresult);
1042 isc_buffer_usedregion(&xfr->qbuffer, &region);
1043 CHECK(isc_socket_send(xfr->socket, &region, xfr->task,
1044 xfrin_send_done, xfr));
1045 xfr->sends++;
1046 failure:
1047 if (result != ISC_R_SUCCESS)
1048 xfrin_fail(xfr, result, "failed sending request length prefix");
1052 static void
1053 xfrin_send_done(isc_task_t *task, isc_event_t *event) {
1054 isc_socketevent_t *sev = (isc_socketevent_t *) event;
1055 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1056 isc_result_t result;
1058 REQUIRE(VALID_XFRIN(xfr));
1060 UNUSED(task);
1062 INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1064 xfr->sends--;
1065 xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request data");
1066 CHECK(sev->result);
1068 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
1069 xfrin_recv_done, xfr));
1070 xfr->recvs++;
1071 failure:
1072 isc_event_free(&event);
1073 if (result != ISC_R_SUCCESS)
1074 xfrin_fail(xfr, result, "failed sending request data");
1078 static void
1079 xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
1080 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) ev->ev_arg;
1081 isc_result_t result;
1082 dns_message_t *msg = NULL;
1083 dns_name_t *name;
1084 dns_tcpmsg_t *tcpmsg;
1085 dns_name_t *tsigowner = NULL;
1087 REQUIRE(VALID_XFRIN(xfr));
1089 UNUSED(task);
1091 INSIST(ev->ev_type == DNS_EVENT_TCPMSG);
1092 tcpmsg = ev->ev_sender;
1093 isc_event_free(&ev);
1095 xfr->recvs--;
1096 if (xfr->shuttingdown) {
1097 maybe_free(xfr);
1098 return;
1101 CHECK(tcpmsg->result);
1103 xfrin_log(xfr, ISC_LOG_DEBUG(7), "received %u bytes",
1104 tcpmsg->buffer.used);
1106 CHECK(isc_timer_touch(xfr->timer));
1108 CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTPARSE, &msg));
1110 dns_message_settsigkey(msg, xfr->tsigkey);
1111 dns_message_setquerytsig(msg, xfr->lasttsig);
1112 msg->tsigctx = xfr->tsigctx;
1113 if (xfr->nmsg > 0)
1114 msg->tcp_continuation = 1;
1116 result = dns_message_parse(msg, &tcpmsg->buffer,
1117 DNS_MESSAGEPARSE_PRESERVEORDER);
1119 if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror ||
1120 (xfr->checkid && msg->id != xfr->id)) {
1121 if (result == ISC_R_SUCCESS)
1122 result = ISC_RESULTCLASS_DNSRCODE + msg->rcode; /*XXX*/
1123 if (result == ISC_R_SUCCESS || result == DNS_R_NOERROR)
1124 result = DNS_R_UNEXPECTEDID;
1125 if (xfr->reqtype == dns_rdatatype_axfr ||
1126 xfr->reqtype == dns_rdatatype_soa)
1127 FAIL(result);
1128 xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
1129 isc_result_totext(result));
1130 try_axfr:
1131 dns_message_destroy(&msg);
1132 xfrin_reset(xfr);
1133 xfr->reqtype = dns_rdatatype_soa;
1134 xfr->state = XFRST_SOAQUERY;
1135 xfrin_start(xfr);
1136 return;
1140 * Does the server know about IXFR? If it doesn't we will get
1141 * a message with a empty answer section or a potentially a CNAME /
1142 * DNAME, the later is handled by xfr_rr() which will return FORMERR
1143 * if the first RR in the answer section is not a SOA record.
1145 if (xfr->reqtype == dns_rdatatype_ixfr &&
1146 xfr->state == XFRST_INITIALSOA &&
1147 msg->counts[DNS_SECTION_ANSWER] == 0) {
1148 xfrin_log(xfr, ISC_LOG_DEBUG(3),
1149 "empty answer section, retrying with AXFR");
1150 goto try_axfr;
1154 result = dns_message_checksig(msg, dns_zone_getview(xfr->zone));
1155 if (result != ISC_R_SUCCESS) {
1156 xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
1157 isc_result_totext(result));
1158 FAIL(result);
1161 for (result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
1162 result == ISC_R_SUCCESS;
1163 result = dns_message_nextname(msg, DNS_SECTION_ANSWER))
1165 dns_rdataset_t *rds;
1167 name = NULL;
1168 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
1169 for (rds = ISC_LIST_HEAD(name->list);
1170 rds != NULL;
1171 rds = ISC_LIST_NEXT(rds, link))
1173 for (result = dns_rdataset_first(rds);
1174 result == ISC_R_SUCCESS;
1175 result = dns_rdataset_next(rds))
1177 dns_rdata_t rdata = DNS_RDATA_INIT;
1178 dns_rdataset_current(rds, &rdata);
1179 CHECK(xfr_rr(xfr, name, rds->ttl, &rdata));
1183 if (result != ISC_R_NOMORE)
1184 goto failure;
1186 if (dns_message_gettsig(msg, &tsigowner) != NULL) {
1188 * Reset the counter.
1190 xfr->sincetsig = 0;
1193 * Free the last tsig, if there is one.
1195 if (xfr->lasttsig != NULL)
1196 isc_buffer_free(&xfr->lasttsig);
1199 * Update the last tsig pointer.
1201 CHECK(dns_message_getquerytsig(msg, xfr->mctx,
1202 &xfr->lasttsig));
1204 } else if (dns_message_gettsigkey(msg) != NULL) {
1205 xfr->sincetsig++;
1206 if (xfr->sincetsig > 100 ||
1207 xfr->nmsg == 0 || xfr->state == XFRST_END)
1209 result = DNS_R_EXPECTEDTSIG;
1210 goto failure;
1215 * Update the number of messages received.
1217 xfr->nmsg++;
1220 * Copy the context back.
1222 xfr->tsigctx = msg->tsigctx;
1224 dns_message_destroy(&msg);
1226 if (xfr->state == XFRST_GOTSOA) {
1227 xfr->reqtype = dns_rdatatype_axfr;
1228 xfr->state = XFRST_INITIALSOA;
1229 CHECK(xfrin_send_request(xfr));
1230 } else if (xfr->state == XFRST_END) {
1232 * Inform the caller we succeeded.
1234 if (xfr->done != NULL) {
1235 (xfr->done)(xfr->zone, ISC_R_SUCCESS);
1236 xfr->done = NULL;
1239 * We should have no outstanding events at this
1240 * point, thus maybe_free() should succeed.
1242 xfr->shuttingdown = ISC_TRUE;
1243 maybe_free(xfr);
1244 } else {
1246 * Read the next message.
1248 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
1249 xfrin_recv_done, xfr));
1250 xfr->recvs++;
1252 return;
1254 failure:
1255 if (msg != NULL)
1256 dns_message_destroy(&msg);
1257 if (result != ISC_R_SUCCESS)
1258 xfrin_fail(xfr, result, "failed while receiving responses");
1261 static void
1262 xfrin_timeout(isc_task_t *task, isc_event_t *event) {
1263 dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1265 REQUIRE(VALID_XFRIN(xfr));
1267 UNUSED(task);
1269 isc_event_free(&event);
1271 * This will log "giving up: timeout".
1273 xfrin_fail(xfr, ISC_R_TIMEDOUT, "giving up");
1276 static void
1277 maybe_free(dns_xfrin_ctx_t *xfr) {
1278 REQUIRE(VALID_XFRIN(xfr));
1280 if (! xfr->shuttingdown || xfr->refcount != 0 ||
1281 xfr->connects != 0 || xfr->sends != 0 ||
1282 xfr->recvs != 0)
1283 return;
1285 xfrin_log(xfr, ISC_LOG_INFO, "end of transfer");
1287 if (xfr->socket != NULL)
1288 isc_socket_detach(&xfr->socket);
1290 if (xfr->timer != NULL)
1291 isc_timer_detach(&xfr->timer);
1293 if (xfr->task != NULL)
1294 isc_task_detach(&xfr->task);
1296 if (xfr->tsigkey != NULL)
1297 dns_tsigkey_detach(&xfr->tsigkey);
1299 if (xfr->lasttsig != NULL)
1300 isc_buffer_free(&xfr->lasttsig);
1302 dns_diff_clear(&xfr->diff);
1304 if (xfr->ixfr.journal != NULL)
1305 dns_journal_destroy(&xfr->ixfr.journal);
1307 if (xfr->axfr.add_private != NULL)
1308 (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
1310 if (xfr->tcpmsg_valid)
1311 dns_tcpmsg_invalidate(&xfr->tcpmsg);
1313 if ((xfr->name.attributes & DNS_NAMEATTR_DYNAMIC) != 0)
1314 dns_name_free(&xfr->name, xfr->mctx);
1316 if (xfr->ver != NULL)
1317 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
1319 if (xfr->db != NULL)
1320 dns_db_detach(&xfr->db);
1322 if (xfr->zone != NULL)
1323 dns_zone_idetach(&xfr->zone);
1325 isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
1329 * Log incoming zone transfer messages in a format like
1330 * transfer of <zone> from <address>: <message>
1332 static void
1333 xfrin_logv(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
1334 isc_sockaddr_t *masteraddr, const char *fmt, va_list ap)
1336 char zntext[DNS_NAME_FORMATSIZE];
1337 char mastertext[ISC_SOCKADDR_FORMATSIZE];
1338 char classtext[DNS_RDATACLASS_FORMATSIZE];
1339 char msgtext[2048];
1341 dns_name_format(zonename, zntext, sizeof(zntext));
1342 dns_rdataclass_format(rdclass, classtext, sizeof(classtext));
1343 isc_sockaddr_format(masteraddr, mastertext, sizeof(mastertext));
1344 vsnprintf(msgtext, sizeof(msgtext), fmt, ap);
1346 isc_log_write(dns_lctx, DNS_LOGCATEGORY_XFER_IN,
1347 DNS_LOGMODULE_XFER_IN, level,
1348 "transfer of '%s/%s' from %s: %s",
1349 zntext, classtext, mastertext, msgtext);
1353 * Logging function for use when a xfrin_ctx_t has not yet been created.
1356 static void
1357 xfrin_log1(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
1358 isc_sockaddr_t *masteraddr, const char *fmt, ...)
1360 va_list ap;
1362 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
1363 return;
1365 va_start(ap, fmt);
1366 xfrin_logv(level, zonename, rdclass, masteraddr, fmt, ap);
1367 va_end(ap);
1371 * Logging function for use when there is a xfrin_ctx_t.
1374 static void
1375 xfrin_log(dns_xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...)
1377 va_list ap;
1379 if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
1380 return;
1382 va_start(ap, fmt);
1383 xfrin_logv(level, &xfr->name, xfr->rdclass, &xfr->masteraddr, fmt, ap);
1384 va_end(ap);