Merge from vendor branch GROFF:
[dragonfly.git] / contrib / bind-9.2.4rc7 / lib / dns / xfrin.c
1 /*
2  * Copyright (C) 2004  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2001, 2003  Internet Software Consortium.
4  *
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.
8  *
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.
16  */
17
18 /* $Id: xfrin.c,v 1.124.2.5 2004/03/09 06:11:11 marka Exp $ */
19
20 #include <config.h>
21
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>
29
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>
47
48 #include <dst/dst.h>
49
50 /*
51  * Incoming AXFR and IXFR.
52  */
53
54 /*
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".
58  */
59 #define FAIL(code) \
60         do { result = (code);                                   \
61                 if (result != ISC_R_SUCCESS) goto failure;      \
62         } while (0)
63
64 #define CHECK(op) \
65         do { result = (op);                                     \
66                 if (result != ISC_R_SUCCESS) goto failure;      \
67         } while (0)
68
69 /*
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.
74  */
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;
87
88 /*
89  * Incoming zone transfer context.
90  */
91
92 struct dns_xfrin_ctx {
93         unsigned int            magic;
94         isc_mem_t               *mctx;
95         dns_zone_t              *zone;
96
97         int                     refcount;
98
99         isc_task_t              *task;
100         isc_timer_t             *timer;
101         isc_socketmgr_t         *socketmgr;
102
103         int                     connects;       /* Connect in progress */
104         int                     sends;          /* Send in progress */
105         int                     recvs;          /* Receive in progress */
106         isc_boolean_t           shuttingdown;
107
108         dns_name_t              name;           /* Name of zone to transfer */
109         dns_rdataclass_t        rdclass;
110
111         isc_boolean_t           checkid;
112         dns_messageid_t         id;
113
114         /*
115          * Requested transfer type (dns_rdatatype_axfr or
116          * dns_rdatatype_ixfr).  The actual transfer type
117          * may differ due to IXFR->AXFR fallback.
118          */
119         dns_rdatatype_t         reqtype;
120
121         isc_sockaddr_t          masteraddr;
122         isc_sockaddr_t          sourceaddr;
123         isc_socket_t            *socket;
124
125         /* Buffer for IXFR/AXFR request message */
126         isc_buffer_t            qbuffer;
127         unsigned char           qbuffer_data[512];
128
129         /* Incoming reply TCP message */
130         dns_tcpmsg_t            tcpmsg;
131         isc_boolean_t           tcpmsg_valid;
132
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 */
137
138         xfrin_state_t           state;
139         isc_uint32_t            end_serial;
140         isc_boolean_t           is_ixfr;
141
142         unsigned int            nmsg;           /* Number of messages recvd */
143
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;
149
150         /*
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.
155          */
156         struct {
157                 dns_addrdatasetfunc_t add_func;
158                 dns_dbload_t          *add_private;
159         } axfr;
160
161         struct {
162                 isc_uint32_t    request_serial;
163                 isc_uint32_t    end_serial;
164                 dns_journal_t   *journal;
165
166         } ixfr;
167 };
168
169 #define XFRIN_MAGIC               ISC_MAGIC('X', 'f', 'r', 'I')
170 #define VALID_XFRIN(x)            ISC_MAGIC_VALID(x, XFRIN_MAGIC)
171
172 /**************************************************************************/
173 /*
174  * Forward declarations.
175  */
176
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);
190
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);
198
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);
205
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);
208
209 static isc_result_t xfrin_start(dns_xfrin_ctx_t *xfr);
210
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);
217
218 static void maybe_free(dns_xfrin_ctx_t *xfr);
219
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);
224
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);
229
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);
234
235 static void
236 xfrin_log(dns_xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...)
237      ISC_FORMAT_PRINTF(3, 4);
238
239 /**************************************************************************/
240 /*
241  * AXFR handling
242  */
243
244 static isc_result_t
245 axfr_init(dns_xfrin_ctx_t *xfr) {
246         isc_result_t result;
247
248         xfr->is_ixfr = ISC_FALSE;
249
250         if (xfr->db != NULL)
251                 dns_db_detach(&xfr->db);
252
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);
259 }
260
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));
270 }
271
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)
275 {
276         isc_result_t result;
277
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);
287 }
288
289 /*
290  * Store a set of AXFR RRs in the database.
291  */
292 static isc_result_t
293 axfr_apply(dns_xfrin_ctx_t *xfr) {
294         isc_result_t result;
295
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);
303 }
304
305 static isc_result_t
306 axfr_commit(dns_xfrin_ctx_t *xfr) {
307         isc_result_t result;
308
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));
312
313         result = ISC_R_SUCCESS;
314  failure:
315         return (result);
316 }
317
318 /**************************************************************************/
319 /*
320  * IXFR handling
321  */
322
323 static isc_result_t
324 ixfr_init(dns_xfrin_ctx_t *xfr) {
325         isc_result_t result;
326         char *journalfile;
327
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);
332         }
333
334         xfr->is_ixfr = ISC_TRUE;
335         INSIST(xfr->db != NULL);
336         xfr->difflen = 0;
337
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));
342
343         result = ISC_R_SUCCESS;
344  failure:
345         return (result);
346 }
347
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)
351 {
352         isc_result_t result;
353
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);
363 }
364
365 /*
366  * Apply a set of IXFR changes to the database.
367  */
368 static isc_result_t
369 ixfr_apply(dns_xfrin_ctx_t *xfr) {
370         isc_result_t result;
371
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));
376         }
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);
385 }
386
387 static isc_result_t
388 ixfr_commit(dns_xfrin_ctx_t *xfr) {
389         isc_result_t result;
390
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);
398         }
399         result = ISC_R_SUCCESS;
400  failure:
401         return (result);
402 }
403
404 /**************************************************************************/
405 /*
406  * Common AXFR/IXFR protocol code
407  */
408
409 /*
410  * Handle a single incoming resource record according to the current
411  * state.
412  */
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)
416 {
417         isc_result_t result;
418
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);
426                 }
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);
436                 }
437                 xfr->state = XFRST_GOTSOA;
438                 break;
439
440         case XFRST_GOTSOA:
441                 /*
442                  * Skip other records in the answer section.
443                  */
444                 break;
445
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);
451                 }
452                 /*
453                  * Remember the serial number in the intial SOA.
454                  * We need it to recognize the end of an IXFR.
455                  */
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))
460                 {
461                         /*
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.
465                          */
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);
471                 }
472                 if (xfr->reqtype == dns_rdatatype_axfr)
473                         xfr->checkid = ISC_FALSE;
474                 xfr->state = XFRST_FIRSTDATA;
475                 break;
476
477         case XFRST_FIRSTDATA:
478                 /*
479                  * If the transfer begins with one SOA record, it is an AXFR,
480                  * if it begins with two SOAs, it is an IXFR.
481                  */
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;
494                 }
495                 goto redo;
496
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;
502
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;
509                 }
510                 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
511                 break;
512
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;
518
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;
529                         }
530                 }
531                 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
532                 break;
533
534         case XFRST_AXFR:
535                 /*
536                  * Old BINDs sent cross class A records for non IN classes.
537                  */
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;
547                 }
548                 break;
549         case XFRST_END:
550                 FAIL(DNS_R_EXTRADATA);
551         default:
552                 INSIST(0);
553                 break;
554         }
555         result = ISC_R_SUCCESS;
556  failure:
557         return (result);
558 }
559
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)
566 {
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;
571
572         REQUIRE(xfrp != NULL && *xfrp == NULL);
573
574         (void)dns_zone_getdb(zone, &db);
575
576         CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename,
577                            dns_zone_getclass(zone), xfrtype, masteraddr,
578                            tsigkey, &xfr));
579
580         CHECK(xfrin_start(xfr));
581
582         xfr->done = done;
583         xfr->refcount++;
584         *xfrp = xfr;
585
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);
593 }
594
595 void
596 dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
597         if (! xfr->shuttingdown)
598                 xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
599 }
600
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;
606 }
607
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;
615 }
616
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);
627         }
628 }
629
630 static void
631 xfrin_reset(dns_xfrin_ctx_t *xfr) {
632         REQUIRE(VALID_XFRIN(xfr));
633
634         xfrin_log(xfr, ISC_LOG_INFO, "resetting");
635
636         xfrin_cancelio(xfr);
637
638         if (xfr->socket != NULL)
639                 isc_socket_detach(&xfr->socket);
640
641         if (xfr->lasttsig != NULL)
642                 isc_buffer_free(&xfr->lasttsig);
643
644         dns_diff_clear(&xfr->diff);
645         xfr->difflen = 0;
646
647         if (xfr->ixfr.journal != NULL)
648                 dns_journal_destroy(&xfr->ixfr.journal);
649
650         if (xfr->axfr.add_private != NULL) {
651                 (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
652                 xfr->axfr.add_func = NULL;
653         }
654
655         if (xfr->tcpmsg_valid) {
656                 dns_tcpmsg_invalidate(&xfr->tcpmsg);
657                 xfr->tcpmsg_valid = ISC_FALSE;
658         }
659
660         if (xfr->ver != NULL)
661                 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
662 }
663
664
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;
673         }
674         xfrin_cancelio(xfr);
675         if (xfr->done != NULL) {
676                 (xfr->done)(xfr->zone, result);
677                 xfr->done = NULL;
678         }
679         xfr->shuttingdown = ISC_TRUE;
680         maybe_free(xfr);
681 }
682
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)
696 {
697         dns_xfrin_ctx_t *xfr = NULL;
698         isc_result_t result;
699         isc_uint32_t tmp;
700
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;
713
714         xfr->connects = 0;
715         xfr->sends = 0;
716         xfr->recvs = 0;
717         xfr->shuttingdown = ISC_FALSE;
718
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;
725
726         /* sockaddr */
727         xfr->socket = NULL;
728         /* qbuffer */
729         /* qbuffer_data */
730         /* tcpmsg */
731         xfr->tcpmsg_valid = ISC_FALSE;
732
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;
739
740         xfr->state = XFRST_INITIALSOA;
741         /* end_serial */
742
743         xfr->nmsg = 0;
744
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;
752
753         /* ixfr.request_serial */
754         /* ixfr.end_serial */
755         xfr->ixfr.journal = NULL;
756
757         xfr->axfr.add_func = NULL;
758         xfr->axfr.add_private = NULL;
759
760         CHECK(dns_name_dup(zonename, mctx, &xfr->name));
761
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));
768
769         xfr->masteraddr = *masteraddr;
770
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);
780         }
781         isc_sockaddr_setport(&xfr->sourceaddr, 0);
782
783         isc_buffer_init(&xfr->qbuffer, xfr->qbuffer_data,
784                         sizeof(xfr->qbuffer_data));
785
786         xfr->magic = XFRIN_MAGIC;
787         *xfrp = xfr;
788         return (ISC_R_SUCCESS);
789
790  failure:
791         xfrin_fail(xfr, result, "failed creating transfer context");
792         return (result);
793 }
794
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);
810 }
811
812 /* XXX the resolver could use this, too */
813
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;
819
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);
833 }
834
835 /*
836  * A connection has been established.
837  */
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;
844
845         REQUIRE(VALID_XFRIN(xfr));
846
847         UNUSED(task);
848
849         INSIST(event->ev_type == ISC_SOCKEVENT_CONNECT);
850         isc_event_free(&event);
851
852         xfr->connects--;
853         if (xfr->shuttingdown) {
854                 maybe_free(xfr);
855                 return;
856         }
857
858         CHECK(evresult);
859         xfrin_log(xfr, ISC_LOG_DEBUG(3), "connected");
860
861         dns_tcpmsg_init(xfr->mctx, xfr->socket, &xfr->tcpmsg);
862         xfr->tcpmsg_valid = ISC_TRUE;
863
864         CHECK(xfrin_send_request(xfr));
865  failure:
866         if (result != ISC_R_SUCCESS)
867                 xfrin_fail(xfr, result, "failed to connect");
868 }
869
870 /*
871  * Convert a tuple into a dns_name_t suitable for inserting
872  * into the given dns_message_t.
873  */
874 static isc_result_t
875 tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target)
876 {
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;
882
883         REQUIRE(target != NULL && *target == NULL);
884
885         CHECK(dns_message_gettemprdata(msg, &rdata));
886         dns_rdata_init(rdata);
887         dns_rdata_clone(&tuple->rdata, rdata);
888
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);
895
896         CHECK(dns_message_gettemprdataset(msg, &rds));
897         dns_rdataset_init(rds);
898         CHECK(dns_rdatalist_tordataset(rdl, rds));
899
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);
904
905         *target = name;
906         return (ISC_R_SUCCESS);
907
908  failure:
909
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);
916         }
917         if (rdata != NULL)
918                 dns_message_puttemprdata(msg, &rdata);
919
920         return (result);
921 }
922
923
924 /*
925  * Build an *XFR request and send its length prefix.
926  */
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;
939
940         /* Create the request message */
941         CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg));
942         CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
943
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);
948
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;
955
956         dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
957         qname = NULL;
958
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);
969
970                 CHECK(tuple2msgname(soatuple, msg, &msgsoaname));
971                 dns_message_addname(msg, msgsoaname, DNS_SECTION_AUTHORITY);
972         }
973
974         xfr->checkid = ISC_TRUE;
975         xfr->id++;
976         msg->id = xfr->id;
977
978         CHECK(render(msg, xfr->mctx, &xfr->qbuffer));
979
980         /*
981          * Free the last tsig, if there is one.
982          */
983         if (xfr->lasttsig != NULL)
984                 isc_buffer_free(&xfr->lasttsig);
985
986         /*
987          * Save the query TSIG and don't let message_destroy free it.
988          */
989         CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
990
991         isc_buffer_usedregion(&xfr->qbuffer, &region);
992         INSIST(region.length <= 65535);
993
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++;
1001
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);
1014 }
1015
1016 /* XXX there should be library support for sending DNS TCP messages */
1017
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;
1025
1026         REQUIRE(VALID_XFRIN(xfr));
1027
1028         UNUSED(task);
1029
1030         INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1031         isc_event_free(&event);
1032
1033         xfr->sends--;
1034         if (xfr->shuttingdown) {
1035                 maybe_free(xfr);
1036                 return;
1037         }
1038
1039         xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request length prefix");
1040         CHECK(evresult);
1041
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");
1049 }
1050
1051
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;
1057
1058         REQUIRE(VALID_XFRIN(xfr));
1059
1060         UNUSED(task);
1061
1062         INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1063
1064         xfr->sends--;
1065         xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request data");
1066         CHECK(sev->result);
1067
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");
1075 }
1076
1077
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;
1086
1087         REQUIRE(VALID_XFRIN(xfr));
1088
1089         UNUSED(task);
1090
1091         INSIST(ev->ev_type == DNS_EVENT_TCPMSG);
1092         tcpmsg = ev->ev_sender;
1093         isc_event_free(&ev);
1094
1095         xfr->recvs--;
1096         if (xfr->shuttingdown) {
1097                 maybe_free(xfr);
1098                 return;
1099         }
1100
1101         CHECK(tcpmsg->result);
1102
1103         xfrin_log(xfr, ISC_LOG_DEBUG(7), "received %u bytes",
1104                   tcpmsg->buffer.used);
1105
1106         CHECK(isc_timer_touch(xfr->timer));
1107
1108         CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTPARSE, &msg));
1109
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;
1115
1116         result = dns_message_parse(msg, &tcpmsg->buffer,
1117                                    DNS_MESSAGEPARSE_PRESERVEORDER);
1118
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;
1137         }
1138
1139         /*
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.
1144          */
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;
1151         }
1152
1153
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);
1159         }
1160
1161         for (result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
1162              result == ISC_R_SUCCESS;
1163              result = dns_message_nextname(msg, DNS_SECTION_ANSWER))
1164         {
1165                 dns_rdataset_t *rds;
1166
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))
1172                 {
1173                         for (result = dns_rdataset_first(rds);
1174                              result == ISC_R_SUCCESS;
1175                              result = dns_rdataset_next(rds))
1176                         {
1177                                 dns_rdata_t rdata = DNS_RDATA_INIT;
1178                                 dns_rdataset_current(rds, &rdata);
1179                                 CHECK(xfr_rr(xfr, name, rds->ttl, &rdata));
1180                         }
1181                 }
1182         }
1183         if (result != ISC_R_NOMORE)
1184                 goto failure;
1185
1186         if (dns_message_gettsig(msg, &tsigowner) != NULL) {
1187                 /*
1188                  * Reset the counter.
1189                  */
1190                 xfr->sincetsig = 0;
1191
1192                 /*
1193                  * Free the last tsig, if there is one.
1194                  */
1195                 if (xfr->lasttsig != NULL)
1196                         isc_buffer_free(&xfr->lasttsig);
1197
1198                 /*
1199                  * Update the last tsig pointer.
1200                  */
1201                 CHECK(dns_message_getquerytsig(msg, xfr->mctx,
1202                                                &xfr->lasttsig));
1203
1204         } else if (dns_message_gettsigkey(msg) != NULL) {
1205                 xfr->sincetsig++;
1206                 if (xfr->sincetsig > 100 ||
1207                     xfr->nmsg == 0 || xfr->state == XFRST_END)
1208                 {
1209                         result = DNS_R_EXPECTEDTSIG;
1210                         goto failure;
1211                 }
1212         }
1213
1214         /*
1215          * Update the number of messages received.
1216          */
1217         xfr->nmsg++;
1218
1219         /*
1220          * Copy the context back.
1221          */
1222         xfr->tsigctx = msg->tsigctx;
1223
1224         dns_message_destroy(&msg);
1225
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) {
1231                 /*
1232                  * Inform the caller we succeeded.
1233                  */
1234                 if (xfr->done != NULL) {
1235                         (xfr->done)(xfr->zone, ISC_R_SUCCESS);
1236                         xfr->done = NULL;
1237                 }
1238                 /*
1239                  * We should have no outstanding events at this
1240                  * point, thus maybe_free() should succeed.
1241                  */
1242                 xfr->shuttingdown = ISC_TRUE;
1243                 maybe_free(xfr);
1244         } else {
1245                 /*
1246                  * Read the next message.
1247                  */
1248                 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
1249                                              xfrin_recv_done, xfr));
1250                 xfr->recvs++;
1251         }
1252         return;
1253
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");
1259 }
1260
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;
1264
1265         REQUIRE(VALID_XFRIN(xfr));
1266
1267         UNUSED(task);
1268
1269         isc_event_free(&event);
1270         /*
1271          * This will log "giving up: timeout".
1272          */
1273         xfrin_fail(xfr, ISC_R_TIMEDOUT, "giving up");
1274 }
1275
1276 static void
1277 maybe_free(dns_xfrin_ctx_t *xfr) {
1278         REQUIRE(VALID_XFRIN(xfr));
1279
1280         if (! xfr->shuttingdown || xfr->refcount != 0 ||
1281             xfr->connects != 0 || xfr->sends != 0 ||
1282             xfr->recvs != 0)
1283                 return;
1284
1285         xfrin_log(xfr, ISC_LOG_INFO, "end of transfer");
1286
1287         if (xfr->socket != NULL)
1288                 isc_socket_detach(&xfr->socket);
1289
1290         if (xfr->timer != NULL)
1291                 isc_timer_detach(&xfr->timer);
1292
1293         if (xfr->task != NULL)
1294                 isc_task_detach(&xfr->task);
1295
1296         if (xfr->tsigkey != NULL)
1297                 dns_tsigkey_detach(&xfr->tsigkey);
1298
1299         if (xfr->lasttsig != NULL)
1300                 isc_buffer_free(&xfr->lasttsig);
1301
1302         dns_diff_clear(&xfr->diff);
1303
1304         if (xfr->ixfr.journal != NULL)
1305                 dns_journal_destroy(&xfr->ixfr.journal);
1306
1307         if (xfr->axfr.add_private != NULL)
1308                 (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
1309
1310         if (xfr->tcpmsg_valid)
1311                 dns_tcpmsg_invalidate(&xfr->tcpmsg);
1312
1313         if ((xfr->name.attributes & DNS_NAMEATTR_DYNAMIC) != 0)
1314                 dns_name_free(&xfr->name, xfr->mctx);
1315
1316         if (xfr->ver != NULL)
1317                 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
1318
1319         if (xfr->db != NULL)
1320                 dns_db_detach(&xfr->db);
1321
1322         if (xfr->zone != NULL)
1323                 dns_zone_idetach(&xfr->zone);
1324
1325         isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
1326 }
1327
1328 /*
1329  * Log incoming zone transfer messages in a format like
1330  * transfer of <zone> from <address>: <message>
1331  */
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)
1335 {
1336         char zntext[DNS_NAME_FORMATSIZE];
1337         char mastertext[ISC_SOCKADDR_FORMATSIZE];
1338         char classtext[DNS_RDATACLASS_FORMATSIZE];
1339         char msgtext[2048];
1340
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);
1345
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);
1350 }
1351
1352 /*
1353  * Logging function for use when a xfrin_ctx_t has not yet been created.
1354  */
1355
1356 static void
1357 xfrin_log1(int level, dns_name_t *zonename, dns_rdataclass_t rdclass,
1358            isc_sockaddr_t *masteraddr, const char *fmt, ...)
1359 {
1360         va_list ap;
1361
1362         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
1363                 return;
1364
1365         va_start(ap, fmt);
1366         xfrin_logv(level, zonename, rdclass, masteraddr, fmt, ap);
1367         va_end(ap);
1368 }
1369
1370 /*
1371  * Logging function for use when there is a xfrin_ctx_t.
1372  */
1373
1374 static void
1375 xfrin_log(dns_xfrin_ctx_t *xfr, unsigned int level, const char *fmt, ...)
1376 {
1377         va_list ap;
1378
1379         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
1380                 return;
1381
1382         va_start(ap, fmt);
1383         xfrin_logv(level, &xfr->name, xfr->rdclass, &xfr->masteraddr, fmt, ap);
1384         va_end(ap);
1385 }