]> CyberLeo.Net >> Repos - FreeBSD/releng/8.1.git/blob - contrib/bind9/lib/dns/xfrin.c
Copy stable/8 to releng/8.1 in preparation for 8.1-RC1.
[FreeBSD/releng/8.1.git] / contrib / bind9 / lib / dns / xfrin.c
1 /*
2  * Copyright (C) 2004-2008  Internet Systems Consortium, Inc. ("ISC")
3  * Copyright (C) 1999-2003  Internet Software Consortium.
4  *
5  * Permission to use, copy, modify, and/or 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.166 2008/09/25 04:12:39 marka Exp $ */
19
20 /*! \file */
21
22 #include <config.h>
23
24 #include <isc/mem.h>
25 #include <isc/print.h>
26 #include <isc/random.h>
27 #include <isc/string.h>         /* Required for HP/UX (and others?) */
28 #include <isc/task.h>
29 #include <isc/timer.h>
30 #include <isc/util.h>
31
32 #include <dns/db.h>
33 #include <dns/diff.h>
34 #include <dns/events.h>
35 #include <dns/journal.h>
36 #include <dns/log.h>
37 #include <dns/message.h>
38 #include <dns/rdataclass.h>
39 #include <dns/rdatalist.h>
40 #include <dns/rdataset.h>
41 #include <dns/result.h>
42 #include <dns/soa.h>
43 #include <dns/tcpmsg.h>
44 #include <dns/timer.h>
45 #include <dns/tsig.h>
46 #include <dns/view.h>
47 #include <dns/xfrin.h>
48 #include <dns/zone.h>
49
50 #include <dst/dst.h>
51
52 /*
53  * Incoming AXFR and IXFR.
54  */
55
56 /*%
57  * It would be non-sensical (or at least obtuse) to use FAIL() with an
58  * ISC_R_SUCCESS code, but the test is there to keep the Solaris compiler
59  * from complaining about "end-of-loop code not reached".
60  */
61 #define FAIL(code) \
62         do { result = (code);                                   \
63                 if (result != ISC_R_SUCCESS) goto failure;      \
64         } while (0)
65
66 #define CHECK(op) \
67         do { result = (op);                                     \
68                 if (result != ISC_R_SUCCESS) goto failure;      \
69         } while (0)
70
71 /*%
72  * The states of the *XFR state machine.  We handle both IXFR and AXFR
73  * with a single integrated state machine because they cannot be distinguished
74  * immediately - an AXFR response to an IXFR request can only be detected
75  * when the first two (2) response RRs have already been received.
76  */
77 typedef enum {
78         XFRST_SOAQUERY,
79         XFRST_GOTSOA,
80         XFRST_INITIALSOA,
81         XFRST_FIRSTDATA,
82         XFRST_IXFR_DELSOA,
83         XFRST_IXFR_DEL,
84         XFRST_IXFR_ADDSOA,
85         XFRST_IXFR_ADD,
86         XFRST_AXFR,
87         XFRST_END
88 } xfrin_state_t;
89
90 /*%
91  * Incoming zone transfer context.
92  */
93
94 struct dns_xfrin_ctx {
95         unsigned int            magic;
96         isc_mem_t               *mctx;
97         dns_zone_t              *zone;
98
99         int                     refcount;
100
101         isc_task_t              *task;
102         isc_timer_t             *timer;
103         isc_socketmgr_t         *socketmgr;
104
105         int                     connects;       /*%< Connect in progress */
106         int                     sends;          /*%< Send in progress */
107         int                     recvs;          /*%< Receive in progress */
108         isc_boolean_t           shuttingdown;
109
110         dns_name_t              name;           /*%< Name of zone to transfer */
111         dns_rdataclass_t        rdclass;
112
113         isc_boolean_t           checkid;
114         dns_messageid_t         id;
115
116         /*%
117          * Requested transfer type (dns_rdatatype_axfr or
118          * dns_rdatatype_ixfr).  The actual transfer type
119          * may differ due to IXFR->AXFR fallback.
120          */
121         dns_rdatatype_t         reqtype;
122
123         isc_sockaddr_t          masteraddr;
124         isc_sockaddr_t          sourceaddr;
125         isc_socket_t            *socket;
126
127         /*% Buffer for IXFR/AXFR request message */
128         isc_buffer_t            qbuffer;
129         unsigned char           qbuffer_data[512];
130
131         /*% Incoming reply TCP message */
132         dns_tcpmsg_t            tcpmsg;
133         isc_boolean_t           tcpmsg_valid;
134
135         dns_db_t                *db;
136         dns_dbversion_t         *ver;
137         dns_diff_t              diff;           /*%< Pending database changes */
138         int                     difflen;        /*%< Number of pending tuples */
139
140         xfrin_state_t           state;
141         isc_uint32_t            end_serial;
142         isc_boolean_t           is_ixfr;
143
144         unsigned int            nmsg;           /*%< Number of messages recvd */
145         unsigned int            nrecs;          /*%< Number of records recvd */
146         isc_uint64_t            nbytes;         /*%< Number of bytes received */
147
148         isc_time_t              start;          /*%< Start time of the transfer */
149         isc_time_t              end;            /*%< End time of the transfer */
150
151         dns_tsigkey_t           *tsigkey;       /*%< Key used to create TSIG */
152         isc_buffer_t            *lasttsig;      /*%< The last TSIG */
153         dst_context_t           *tsigctx;       /*%< TSIG verification context */
154         unsigned int            sincetsig;      /*%< recvd since the last TSIG */
155         dns_xfrindone_t         done;
156
157         /*%
158          * AXFR- and IXFR-specific data.  Only one is used at a time
159          * according to the is_ixfr flag, so this could be a union,
160          * but keeping them separate makes it a bit simpler to clean
161          * things up when destroying the context.
162          */
163         struct {
164                 dns_addrdatasetfunc_t add_func;
165                 dns_dbload_t          *add_private;
166         } axfr;
167
168         struct {
169                 isc_uint32_t    request_serial;
170                 isc_uint32_t    current_serial;
171                 dns_journal_t   *journal;
172
173         } ixfr;
174 };
175
176 #define XFRIN_MAGIC               ISC_MAGIC('X', 'f', 'r', 'I')
177 #define VALID_XFRIN(x)            ISC_MAGIC_VALID(x, XFRIN_MAGIC)
178
179 /**************************************************************************/
180 /*
181  * Forward declarations.
182  */
183
184 static isc_result_t
185 xfrin_create(isc_mem_t *mctx,
186              dns_zone_t *zone,
187              dns_db_t *db,
188              isc_task_t *task,
189              isc_timermgr_t *timermgr,
190              isc_socketmgr_t *socketmgr,
191              dns_name_t *zonename,
192              dns_rdataclass_t rdclass,
193              dns_rdatatype_t reqtype,
194              isc_sockaddr_t *masteraddr,
195              isc_sockaddr_t *sourceaddr,
196              dns_tsigkey_t *tsigkey,
197              dns_xfrin_ctx_t **xfrp);
198
199 static isc_result_t axfr_init(dns_xfrin_ctx_t *xfr);
200 static isc_result_t axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp);
201 static isc_result_t axfr_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 axfr_apply(dns_xfrin_ctx_t *xfr);
205 static isc_result_t axfr_commit(dns_xfrin_ctx_t *xfr);
206
207 static isc_result_t ixfr_init(dns_xfrin_ctx_t *xfr);
208 static isc_result_t ixfr_apply(dns_xfrin_ctx_t *xfr);
209 static isc_result_t ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
210                                  dns_name_t *name, dns_ttl_t ttl,
211                                  dns_rdata_t *rdata);
212 static isc_result_t ixfr_commit(dns_xfrin_ctx_t *xfr);
213
214 static isc_result_t xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name,
215                            isc_uint32_t ttl, dns_rdata_t *rdata);
216
217 static isc_result_t xfrin_start(dns_xfrin_ctx_t *xfr);
218
219 static void xfrin_connect_done(isc_task_t *task, isc_event_t *event);
220 static isc_result_t xfrin_send_request(dns_xfrin_ctx_t *xfr);
221 static void xfrin_send_done(isc_task_t *task, isc_event_t *event);
222 static void xfrin_sendlen_done(isc_task_t *task, isc_event_t *event);
223 static void xfrin_recv_done(isc_task_t *task, isc_event_t *event);
224 static void xfrin_timeout(isc_task_t *task, isc_event_t *event);
225
226 static void maybe_free(dns_xfrin_ctx_t *xfr);
227
228 static void
229 xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg);
230 static isc_result_t
231 render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf);
232
233 static void
234 xfrin_logv(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
235            const char *fmt, va_list ap)
236      ISC_FORMAT_PRINTF(4, 0);
237
238 static void
239 xfrin_log1(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
240            const char *fmt, ...)
241      ISC_FORMAT_PRINTF(4, 5);
242
243 static void
244 xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
245      ISC_FORMAT_PRINTF(3, 4);
246
247 /**************************************************************************/
248 /*
249  * AXFR handling
250  */
251
252 static isc_result_t
253 axfr_init(dns_xfrin_ctx_t *xfr) {
254         isc_result_t result;
255
256         xfr->is_ixfr = ISC_FALSE;
257
258         if (xfr->db != NULL)
259                 dns_db_detach(&xfr->db);
260
261         CHECK(axfr_makedb(xfr, &xfr->db));
262         CHECK(dns_db_beginload(xfr->db, &xfr->axfr.add_func,
263                                &xfr->axfr.add_private));
264         result = ISC_R_SUCCESS;
265  failure:
266         return (result);
267 }
268
269 static isc_result_t
270 axfr_makedb(dns_xfrin_ctx_t *xfr, dns_db_t **dbp) {
271         return (dns_db_create(xfr->mctx, /* XXX */
272                               "rbt", /* XXX guess */
273                               &xfr->name,
274                               dns_dbtype_zone,
275                               xfr->rdclass,
276                               0, NULL, /* XXX guess */
277                               dbp));
278 }
279
280 static isc_result_t
281 axfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
282              dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
283 {
284         isc_result_t result;
285
286         dns_difftuple_t *tuple = NULL;
287
288         CHECK(dns_zone_checknames(xfr->zone, name, rdata));
289         CHECK(dns_difftuple_create(xfr->diff.mctx, op,
290                                    name, ttl, rdata, &tuple));
291         dns_diff_append(&xfr->diff, &tuple);
292         if (++xfr->difflen > 100)
293                 CHECK(axfr_apply(xfr));
294         result = ISC_R_SUCCESS;
295  failure:
296         return (result);
297 }
298
299 /*
300  * Store a set of AXFR RRs in the database.
301  */
302 static isc_result_t
303 axfr_apply(dns_xfrin_ctx_t *xfr) {
304         isc_result_t result;
305
306         CHECK(dns_diff_load(&xfr->diff,
307                             xfr->axfr.add_func, xfr->axfr.add_private));
308         xfr->difflen = 0;
309         dns_diff_clear(&xfr->diff);
310         result = ISC_R_SUCCESS;
311  failure:
312         return (result);
313 }
314
315 static isc_result_t
316 axfr_commit(dns_xfrin_ctx_t *xfr) {
317         isc_result_t result;
318
319         CHECK(axfr_apply(xfr));
320         CHECK(dns_db_endload(xfr->db, &xfr->axfr.add_private));
321         CHECK(dns_zone_replacedb(xfr->zone, xfr->db, ISC_TRUE));
322
323         result = ISC_R_SUCCESS;
324  failure:
325         return (result);
326 }
327
328 /**************************************************************************/
329 /*
330  * IXFR handling
331  */
332
333 static isc_result_t
334 ixfr_init(dns_xfrin_ctx_t *xfr) {
335         isc_result_t result;
336         char *journalfile;
337
338         if (xfr->reqtype != dns_rdatatype_ixfr) {
339                 xfrin_log(xfr, ISC_LOG_ERROR,
340                           "got incremental response to AXFR request");
341                 return (DNS_R_FORMERR);
342         }
343
344         xfr->is_ixfr = ISC_TRUE;
345         INSIST(xfr->db != NULL);
346         xfr->difflen = 0;
347
348         journalfile = dns_zone_getjournal(xfr->zone);
349         if (journalfile != NULL)
350                 CHECK(dns_journal_open(xfr->mctx, journalfile,
351                                        ISC_TRUE, &xfr->ixfr.journal));
352
353         result = ISC_R_SUCCESS;
354  failure:
355         return (result);
356 }
357
358 static isc_result_t
359 ixfr_putdata(dns_xfrin_ctx_t *xfr, dns_diffop_t op,
360              dns_name_t *name, dns_ttl_t ttl, dns_rdata_t *rdata)
361 {
362         isc_result_t result;
363
364         dns_difftuple_t *tuple = NULL;
365         if (op == DNS_DIFFOP_ADD)
366                 CHECK(dns_zone_checknames(xfr->zone, name, rdata));
367         CHECK(dns_difftuple_create(xfr->diff.mctx, op,
368                                    name, ttl, rdata, &tuple));
369         dns_diff_append(&xfr->diff, &tuple);
370         if (++xfr->difflen > 100)
371                 CHECK(ixfr_apply(xfr));
372         result = ISC_R_SUCCESS;
373  failure:
374         return (result);
375 }
376
377 /*
378  * Apply a set of IXFR changes to the database.
379  */
380 static isc_result_t
381 ixfr_apply(dns_xfrin_ctx_t *xfr) {
382         isc_result_t result;
383
384         if (xfr->ver == NULL) {
385                 CHECK(dns_db_newversion(xfr->db, &xfr->ver));
386                 if (xfr->ixfr.journal != NULL)
387                         CHECK(dns_journal_begin_transaction(xfr->ixfr.journal));
388         }
389         CHECK(dns_diff_apply(&xfr->diff, xfr->db, xfr->ver));
390         if (xfr->ixfr.journal != NULL) {
391                 result = dns_journal_writediff(xfr->ixfr.journal, &xfr->diff);
392                 if (result != ISC_R_SUCCESS)
393                         goto failure;
394         }
395         dns_diff_clear(&xfr->diff);
396         xfr->difflen = 0;
397         result = ISC_R_SUCCESS;
398  failure:
399         return (result);
400 }
401
402 static isc_result_t
403 ixfr_commit(dns_xfrin_ctx_t *xfr) {
404         isc_result_t result;
405
406         CHECK(ixfr_apply(xfr));
407         if (xfr->ver != NULL) {
408                 /* XXX enter ready-to-commit state here */
409                 if (xfr->ixfr.journal != NULL)
410                         CHECK(dns_journal_commit(xfr->ixfr.journal));
411                 dns_db_closeversion(xfr->db, &xfr->ver, ISC_TRUE);
412                 dns_zone_markdirty(xfr->zone);
413         }
414         result = ISC_R_SUCCESS;
415  failure:
416         return (result);
417 }
418
419 /**************************************************************************/
420 /*
421  * Common AXFR/IXFR protocol code
422  */
423
424 /*
425  * Handle a single incoming resource record according to the current
426  * state.
427  */
428 static isc_result_t
429 xfr_rr(dns_xfrin_ctx_t *xfr, dns_name_t *name, isc_uint32_t ttl,
430        dns_rdata_t *rdata)
431 {
432         isc_result_t result;
433
434         xfr->nrecs++;
435
436         if (rdata->type == dns_rdatatype_none ||
437             dns_rdatatype_ismeta(rdata->type))
438                 FAIL(DNS_R_FORMERR);
439
440  redo:
441         switch (xfr->state) {
442         case XFRST_SOAQUERY:
443                 if (rdata->type != dns_rdatatype_soa) {
444                         xfrin_log(xfr, ISC_LOG_ERROR,
445                                   "non-SOA response to SOA query");
446                         FAIL(DNS_R_FORMERR);
447                 }
448                 xfr->end_serial = dns_soa_getserial(rdata);
449                 if (!DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial) &&
450                     !dns_zone_isforced(xfr->zone)) {
451                         xfrin_log(xfr, ISC_LOG_DEBUG(3),
452                                   "requested serial %u, "
453                                   "master has %u, not updating",
454                                   xfr->ixfr.request_serial, xfr->end_serial);
455                         FAIL(DNS_R_UPTODATE);
456                 }
457                 xfr->state = XFRST_GOTSOA;
458                 break;
459
460         case XFRST_GOTSOA:
461                 /*
462                  * Skip other records in the answer section.
463                  */
464                 break;
465
466         case XFRST_INITIALSOA:
467                 if (rdata->type != dns_rdatatype_soa) {
468                         xfrin_log(xfr, ISC_LOG_ERROR,
469                                   "first RR in zone transfer must be SOA");
470                         FAIL(DNS_R_FORMERR);
471                 }
472                 /*
473                  * Remember the serial number in the initial SOA.
474                  * We need it to recognize the end of an IXFR.
475                  */
476                 xfr->end_serial = dns_soa_getserial(rdata);
477                 if (xfr->reqtype == dns_rdatatype_ixfr &&
478                     ! DNS_SERIAL_GT(xfr->end_serial, xfr->ixfr.request_serial)
479                     && !dns_zone_isforced(xfr->zone))
480                 {
481                         /*
482                          * This must be the single SOA record that is
483                          * sent when the current version on the master
484                          * is not newer than the version in the request.
485                          */
486                         xfrin_log(xfr, ISC_LOG_DEBUG(3),
487                                   "requested serial %u, "
488                                   "master has %u, not updating",
489                                   xfr->ixfr.request_serial, xfr->end_serial);
490                         FAIL(DNS_R_UPTODATE);
491                 }
492                 if (xfr->reqtype == dns_rdatatype_axfr)
493                         xfr->checkid = ISC_FALSE;
494                 xfr->state = XFRST_FIRSTDATA;
495                 break;
496
497         case XFRST_FIRSTDATA:
498                 /*
499                  * If the transfer begins with one SOA record, it is an AXFR,
500                  * if it begins with two SOAs, it is an IXFR.
501                  */
502                 if (xfr->reqtype == dns_rdatatype_ixfr &&
503                     rdata->type == dns_rdatatype_soa &&
504                     xfr->ixfr.request_serial == dns_soa_getserial(rdata)) {
505                         xfrin_log(xfr, ISC_LOG_DEBUG(3),
506                                   "got incremental response");
507                         CHECK(ixfr_init(xfr));
508                         xfr->state = XFRST_IXFR_DELSOA;
509                 } else {
510                         xfrin_log(xfr, ISC_LOG_DEBUG(3),
511                                   "got nonincremental response");
512                         CHECK(axfr_init(xfr));
513                         xfr->state = XFRST_AXFR;
514                 }
515                 goto redo;
516
517         case XFRST_IXFR_DELSOA:
518                 INSIST(rdata->type == dns_rdatatype_soa);
519                 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
520                 xfr->state = XFRST_IXFR_DEL;
521                 break;
522
523         case XFRST_IXFR_DEL:
524                 if (rdata->type == dns_rdatatype_soa) {
525                         isc_uint32_t soa_serial = dns_soa_getserial(rdata);
526                         xfr->state = XFRST_IXFR_ADDSOA;
527                         xfr->ixfr.current_serial = soa_serial;
528                         goto redo;
529                 }
530                 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_DEL, name, ttl, rdata));
531                 break;
532
533         case XFRST_IXFR_ADDSOA:
534                 INSIST(rdata->type == dns_rdatatype_soa);
535                 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
536                 xfr->state = XFRST_IXFR_ADD;
537                 break;
538
539         case XFRST_IXFR_ADD:
540                 if (rdata->type == dns_rdatatype_soa) {
541                         isc_uint32_t soa_serial = dns_soa_getserial(rdata);
542                         if (soa_serial == xfr->end_serial) {
543                                 CHECK(ixfr_commit(xfr));
544                                 xfr->state = XFRST_END;
545                                 break;
546                         } else if (soa_serial != xfr->ixfr.current_serial) {
547                                 xfrin_log(xfr, ISC_LOG_ERROR,
548                                           "IXFR out of sync: "
549                                           "expected serial %u, got %u",
550                                           xfr->ixfr.current_serial, soa_serial);
551                                 FAIL(DNS_R_FORMERR);
552                         } else {
553                                 CHECK(ixfr_commit(xfr));
554                                 xfr->state = XFRST_IXFR_DELSOA;
555                                 goto redo;
556                         }
557                 }
558                 if (rdata->type == dns_rdatatype_ns &&
559                     dns_name_iswildcard(name))
560                         FAIL(DNS_R_INVALIDNS);
561                 CHECK(ixfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
562                 break;
563
564         case XFRST_AXFR:
565                 /*
566                  * Old BINDs sent cross class A records for non IN classes.
567                  */
568                 if (rdata->type == dns_rdatatype_a &&
569                     rdata->rdclass != xfr->rdclass &&
570                     xfr->rdclass != dns_rdataclass_in)
571                         break;
572                 CHECK(axfr_putdata(xfr, DNS_DIFFOP_ADD, name, ttl, rdata));
573                 if (rdata->type == dns_rdatatype_soa) {
574                         CHECK(axfr_commit(xfr));
575                         xfr->state = XFRST_END;
576                         break;
577                 }
578                 break;
579         case XFRST_END:
580                 FAIL(DNS_R_EXTRADATA);
581         default:
582                 INSIST(0);
583                 break;
584         }
585         result = ISC_R_SUCCESS;
586  failure:
587         return (result);
588 }
589
590 isc_result_t
591 dns_xfrin_create(dns_zone_t *zone, dns_rdatatype_t xfrtype,
592                  isc_sockaddr_t *masteraddr, dns_tsigkey_t *tsigkey,
593                  isc_mem_t *mctx, isc_timermgr_t *timermgr,
594                  isc_socketmgr_t *socketmgr, isc_task_t *task,
595                  dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
596 {
597         isc_sockaddr_t sourceaddr;
598
599         switch (isc_sockaddr_pf(masteraddr)) {
600         case PF_INET:
601                 sourceaddr = *dns_zone_getxfrsource4(zone);
602                 break;
603         case PF_INET6:
604                 sourceaddr = *dns_zone_getxfrsource6(zone);
605                 break;
606         default:
607                 INSIST(0);
608         }
609
610         return(dns_xfrin_create2(zone, xfrtype, masteraddr, &sourceaddr,
611                                  tsigkey, mctx, timermgr, socketmgr,
612                                  task, done, xfrp));
613 }
614
615 isc_result_t
616 dns_xfrin_create2(dns_zone_t *zone, dns_rdatatype_t xfrtype,
617                   isc_sockaddr_t *masteraddr, isc_sockaddr_t *sourceaddr,
618                   dns_tsigkey_t *tsigkey, isc_mem_t *mctx,
619                   isc_timermgr_t *timermgr, isc_socketmgr_t *socketmgr,
620                   isc_task_t *task, dns_xfrindone_t done, dns_xfrin_ctx_t **xfrp)
621 {
622         dns_name_t *zonename = dns_zone_getorigin(zone);
623         dns_xfrin_ctx_t *xfr = NULL;
624         isc_result_t result;
625         dns_db_t *db = NULL;
626
627         REQUIRE(xfrp != NULL && *xfrp == NULL);
628
629         (void)dns_zone_getdb(zone, &db);
630
631         if (xfrtype == dns_rdatatype_soa || xfrtype == dns_rdatatype_ixfr)
632                 REQUIRE(db != NULL);
633
634         CHECK(xfrin_create(mctx, zone, db, task, timermgr, socketmgr, zonename,
635                            dns_zone_getclass(zone), xfrtype, masteraddr,
636                            sourceaddr, tsigkey, &xfr));
637
638         CHECK(xfrin_start(xfr));
639
640         xfr->done = done;
641         xfr->refcount++;
642         *xfrp = xfr;
643
644  failure:
645         if (db != NULL)
646                 dns_db_detach(&db);
647         if (result != ISC_R_SUCCESS) {
648                 char zonetext[DNS_NAME_MAXTEXT+32];
649                 dns_zone_name(zone, zonetext, sizeof(zonetext));
650                 xfrin_log1(ISC_LOG_ERROR, zonetext, masteraddr,
651                            "zone transfer setup failed");
652         }
653         return (result);
654 }
655
656 void
657 dns_xfrin_shutdown(dns_xfrin_ctx_t *xfr) {
658         if (! xfr->shuttingdown)
659                 xfrin_fail(xfr, ISC_R_CANCELED, "shut down");
660 }
661
662 void
663 dns_xfrin_attach(dns_xfrin_ctx_t *source, dns_xfrin_ctx_t **target) {
664         REQUIRE(target != NULL && *target == NULL);
665         source->refcount++;
666         *target = source;
667 }
668
669 void
670 dns_xfrin_detach(dns_xfrin_ctx_t **xfrp) {
671         dns_xfrin_ctx_t *xfr = *xfrp;
672         INSIST(xfr->refcount > 0);
673         xfr->refcount--;
674         maybe_free(xfr);
675         *xfrp = NULL;
676 }
677
678 static void
679 xfrin_cancelio(dns_xfrin_ctx_t *xfr) {
680         if (xfr->connects > 0) {
681                 isc_socket_cancel(xfr->socket, xfr->task,
682                                   ISC_SOCKCANCEL_CONNECT);
683         } else if (xfr->recvs > 0) {
684                 dns_tcpmsg_cancelread(&xfr->tcpmsg);
685         } else if (xfr->sends > 0) {
686                 isc_socket_cancel(xfr->socket, xfr->task,
687                                   ISC_SOCKCANCEL_SEND);
688         }
689 }
690
691 static void
692 xfrin_reset(dns_xfrin_ctx_t *xfr) {
693         REQUIRE(VALID_XFRIN(xfr));
694
695         xfrin_log(xfr, ISC_LOG_INFO, "resetting");
696
697         xfrin_cancelio(xfr);
698
699         if (xfr->socket != NULL)
700                 isc_socket_detach(&xfr->socket);
701
702         if (xfr->lasttsig != NULL)
703                 isc_buffer_free(&xfr->lasttsig);
704
705         dns_diff_clear(&xfr->diff);
706         xfr->difflen = 0;
707
708         if (xfr->ixfr.journal != NULL)
709                 dns_journal_destroy(&xfr->ixfr.journal);
710
711         if (xfr->axfr.add_private != NULL) {
712                 (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
713                 xfr->axfr.add_func = NULL;
714         }
715
716         if (xfr->tcpmsg_valid) {
717                 dns_tcpmsg_invalidate(&xfr->tcpmsg);
718                 xfr->tcpmsg_valid = ISC_FALSE;
719         }
720
721         if (xfr->ver != NULL)
722                 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
723 }
724
725
726 static void
727 xfrin_fail(dns_xfrin_ctx_t *xfr, isc_result_t result, const char *msg) {
728         if (result != DNS_R_UPTODATE) {
729                 xfrin_log(xfr, ISC_LOG_ERROR, "%s: %s",
730                           msg, isc_result_totext(result));
731                 if (xfr->is_ixfr)
732                         /* Pass special result code to force AXFR retry */
733                         result = DNS_R_BADIXFR;
734         }
735         xfrin_cancelio(xfr);
736         /*
737          * Close the journal.
738          */
739         if (xfr->ixfr.journal != NULL)
740                 dns_journal_destroy(&xfr->ixfr.journal);
741         if (xfr->done != NULL) {
742                 (xfr->done)(xfr->zone, result);
743                 xfr->done = NULL;
744         }
745         xfr->shuttingdown = ISC_TRUE;
746         maybe_free(xfr);
747 }
748
749 static isc_result_t
750 xfrin_create(isc_mem_t *mctx,
751              dns_zone_t *zone,
752              dns_db_t *db,
753              isc_task_t *task,
754              isc_timermgr_t *timermgr,
755              isc_socketmgr_t *socketmgr,
756              dns_name_t *zonename,
757              dns_rdataclass_t rdclass,
758              dns_rdatatype_t reqtype,
759              isc_sockaddr_t *masteraddr,
760              isc_sockaddr_t *sourceaddr,
761              dns_tsigkey_t *tsigkey,
762              dns_xfrin_ctx_t **xfrp)
763 {
764         dns_xfrin_ctx_t *xfr = NULL;
765         isc_result_t result;
766         isc_uint32_t tmp;
767
768         xfr = isc_mem_get(mctx, sizeof(*xfr));
769         if (xfr == NULL)
770                 return (ISC_R_NOMEMORY);
771         xfr->mctx = mctx;
772         xfr->refcount = 0;
773         xfr->zone = NULL;
774         dns_zone_iattach(zone, &xfr->zone);
775         xfr->task = NULL;
776         isc_task_attach(task, &xfr->task);
777         xfr->timer = NULL;
778         xfr->socketmgr = socketmgr;
779         xfr->done = NULL;
780
781         xfr->connects = 0;
782         xfr->sends = 0;
783         xfr->recvs = 0;
784         xfr->shuttingdown = ISC_FALSE;
785
786         dns_name_init(&xfr->name, NULL);
787         xfr->rdclass = rdclass;
788         isc_random_get(&tmp);
789         xfr->checkid = ISC_TRUE;
790         xfr->id = (isc_uint16_t)(tmp & 0xffff);
791         xfr->reqtype = reqtype;
792
793         /* sockaddr */
794         xfr->socket = NULL;
795         /* qbuffer */
796         /* qbuffer_data */
797         /* tcpmsg */
798         xfr->tcpmsg_valid = ISC_FALSE;
799
800         xfr->db = NULL;
801         if (db != NULL)
802                 dns_db_attach(db, &xfr->db);
803         xfr->ver = NULL;
804         dns_diff_init(xfr->mctx, &xfr->diff);
805         xfr->difflen = 0;
806
807         if (reqtype == dns_rdatatype_soa)
808                 xfr->state = XFRST_SOAQUERY;
809         else
810                 xfr->state = XFRST_INITIALSOA;
811         /* end_serial */
812
813         xfr->nmsg = 0;
814         xfr->nrecs = 0;
815         xfr->nbytes = 0;
816         isc_time_now(&xfr->start);
817
818         xfr->tsigkey = NULL;
819         if (tsigkey != NULL)
820                 dns_tsigkey_attach(tsigkey, &xfr->tsigkey);
821         xfr->lasttsig = NULL;
822         xfr->tsigctx = NULL;
823         xfr->sincetsig = 0;
824         xfr->is_ixfr = ISC_FALSE;
825
826         /* ixfr.request_serial */
827         /* ixfr.current_serial */
828         xfr->ixfr.journal = NULL;
829
830         xfr->axfr.add_func = NULL;
831         xfr->axfr.add_private = NULL;
832
833         CHECK(dns_name_dup(zonename, mctx, &xfr->name));
834
835         CHECK(isc_timer_create(timermgr, isc_timertype_inactive, NULL, NULL,
836                                task, xfrin_timeout, xfr, &xfr->timer));
837         CHECK(dns_timer_setidle(xfr->timer,
838                                 dns_zone_getmaxxfrin(xfr->zone),
839                                 dns_zone_getidlein(xfr->zone),
840                                 ISC_FALSE));
841
842         xfr->masteraddr = *masteraddr;
843
844         INSIST(isc_sockaddr_pf(masteraddr) == isc_sockaddr_pf(sourceaddr));
845         xfr->sourceaddr = *sourceaddr;
846         isc_sockaddr_setport(&xfr->sourceaddr, 0);
847
848         isc_buffer_init(&xfr->qbuffer, xfr->qbuffer_data,
849                         sizeof(xfr->qbuffer_data));
850
851         xfr->magic = XFRIN_MAGIC;
852         *xfrp = xfr;
853         return (ISC_R_SUCCESS);
854
855  failure:
856         if (xfr->timer != NULL)
857                 isc_timer_detach(&xfr->timer);
858         if (dns_name_dynamic(&xfr->name))
859                 dns_name_free(&xfr->name, xfr->mctx);
860         if (xfr->tsigkey != NULL)
861                 dns_tsigkey_detach(&xfr->tsigkey);
862         if (xfr->db != NULL)
863                 dns_db_detach(&xfr->db);
864         isc_task_detach(&xfr->task);
865         dns_zone_idetach(&xfr->zone);
866         isc_mem_put(mctx, xfr, sizeof(*xfr));
867
868         return (result);
869 }
870
871 static isc_result_t
872 xfrin_start(dns_xfrin_ctx_t *xfr) {
873         isc_result_t result;
874         CHECK(isc_socket_create(xfr->socketmgr,
875                                 isc_sockaddr_pf(&xfr->sourceaddr),
876                                 isc_sockettype_tcp,
877                                 &xfr->socket));
878         isc_socket_setname(xfr->socket, "xfrin", NULL);
879 #ifndef BROKEN_TCP_BIND_BEFORE_CONNECT
880         CHECK(isc_socket_bind(xfr->socket, &xfr->sourceaddr,
881                               ISC_SOCKET_REUSEADDRESS));
882 #endif
883         CHECK(isc_socket_connect(xfr->socket, &xfr->masteraddr, xfr->task,
884                                  xfrin_connect_done, xfr));
885         xfr->connects++;
886         return (ISC_R_SUCCESS);
887  failure:
888         xfrin_fail(xfr, result, "failed setting up socket");
889         return (result);
890 }
891
892 /* XXX the resolver could use this, too */
893
894 static isc_result_t
895 render(dns_message_t *msg, isc_mem_t *mctx, isc_buffer_t *buf) {
896         dns_compress_t cctx;
897         isc_boolean_t cleanup_cctx = ISC_FALSE;
898         isc_result_t result;
899
900         CHECK(dns_compress_init(&cctx, -1, mctx));
901         cleanup_cctx = ISC_TRUE;
902         CHECK(dns_message_renderbegin(msg, &cctx, buf));
903         CHECK(dns_message_rendersection(msg, DNS_SECTION_QUESTION, 0));
904         CHECK(dns_message_rendersection(msg, DNS_SECTION_ANSWER, 0));
905         CHECK(dns_message_rendersection(msg, DNS_SECTION_AUTHORITY, 0));
906         CHECK(dns_message_rendersection(msg, DNS_SECTION_ADDITIONAL, 0));
907         CHECK(dns_message_renderend(msg));
908         result = ISC_R_SUCCESS;
909  failure:
910         if (cleanup_cctx)
911                 dns_compress_invalidate(&cctx);
912         return (result);
913 }
914
915 /*
916  * A connection has been established.
917  */
918 static void
919 xfrin_connect_done(isc_task_t *task, isc_event_t *event) {
920         isc_socket_connev_t *cev = (isc_socket_connev_t *) event;
921         dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
922         isc_result_t result = cev->result;
923         char sourcetext[ISC_SOCKADDR_FORMATSIZE];
924         isc_sockaddr_t sockaddr;
925
926         REQUIRE(VALID_XFRIN(xfr));
927
928         UNUSED(task);
929
930         INSIST(event->ev_type == ISC_SOCKEVENT_CONNECT);
931         isc_event_free(&event);
932
933         xfr->connects--;
934         if (xfr->shuttingdown) {
935                 maybe_free(xfr);
936                 return;
937         }
938
939         if (result != ISC_R_SUCCESS) {
940                 dns_zonemgr_t * zmgr = dns_zone_getmgr(xfr->zone);
941                 isc_time_t now;
942
943                 if (zmgr != NULL) {
944                         TIME_NOW(&now);
945                         dns_zonemgr_unreachableadd(zmgr, &xfr->masteraddr,
946                                                    &xfr->sourceaddr, &now);
947                 }
948                 goto failure;
949         }
950
951         result = isc_socket_getsockname(xfr->socket, &sockaddr);
952         if (result == ISC_R_SUCCESS) {
953                 isc_sockaddr_format(&sockaddr, sourcetext, sizeof(sourcetext));
954         } else
955                 strcpy(sourcetext, "<UNKNOWN>");
956         xfrin_log(xfr, ISC_LOG_INFO, "connected using %s", sourcetext);
957
958         dns_tcpmsg_init(xfr->mctx, xfr->socket, &xfr->tcpmsg);
959         xfr->tcpmsg_valid = ISC_TRUE;
960
961         CHECK(xfrin_send_request(xfr));
962  failure:
963         if (result != ISC_R_SUCCESS)
964                 xfrin_fail(xfr, result, "failed to connect");
965 }
966
967 /*
968  * Convert a tuple into a dns_name_t suitable for inserting
969  * into the given dns_message_t.
970  */
971 static isc_result_t
972 tuple2msgname(dns_difftuple_t *tuple, dns_message_t *msg, dns_name_t **target)
973 {
974         isc_result_t result;
975         dns_rdata_t *rdata = NULL;
976         dns_rdatalist_t *rdl = NULL;
977         dns_rdataset_t *rds = NULL;
978         dns_name_t *name = NULL;
979
980         REQUIRE(target != NULL && *target == NULL);
981
982         CHECK(dns_message_gettemprdata(msg, &rdata));
983         dns_rdata_init(rdata);
984         dns_rdata_clone(&tuple->rdata, rdata);
985
986         CHECK(dns_message_gettemprdatalist(msg, &rdl));
987         dns_rdatalist_init(rdl);
988         rdl->type = tuple->rdata.type;
989         rdl->rdclass = tuple->rdata.rdclass;
990         rdl->ttl = tuple->ttl;
991         ISC_LIST_APPEND(rdl->rdata, rdata, link);
992
993         CHECK(dns_message_gettemprdataset(msg, &rds));
994         dns_rdataset_init(rds);
995         CHECK(dns_rdatalist_tordataset(rdl, rds));
996
997         CHECK(dns_message_gettempname(msg, &name));
998         dns_name_init(name, NULL);
999         dns_name_clone(&tuple->name, name);
1000         ISC_LIST_APPEND(name->list, rds, link);
1001
1002         *target = name;
1003         return (ISC_R_SUCCESS);
1004
1005  failure:
1006
1007         if (rds != NULL) {
1008                 dns_rdataset_disassociate(rds);
1009                 dns_message_puttemprdataset(msg, &rds);
1010         }
1011         if (rdl != NULL) {
1012                 ISC_LIST_UNLINK(rdl->rdata, rdata, link);
1013                 dns_message_puttemprdatalist(msg, &rdl);
1014         }
1015         if (rdata != NULL)
1016                 dns_message_puttemprdata(msg, &rdata);
1017
1018         return (result);
1019 }
1020
1021
1022 /*
1023  * Build an *XFR request and send its length prefix.
1024  */
1025 static isc_result_t
1026 xfrin_send_request(dns_xfrin_ctx_t *xfr) {
1027         isc_result_t result;
1028         isc_region_t region;
1029         isc_region_t lregion;
1030         dns_rdataset_t *qrdataset = NULL;
1031         dns_message_t *msg = NULL;
1032         unsigned char length[2];
1033         dns_difftuple_t *soatuple = NULL;
1034         dns_name_t *qname = NULL;
1035         dns_dbversion_t *ver = NULL;
1036         dns_name_t *msgsoaname = NULL;
1037
1038         /* Create the request message */
1039         CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTRENDER, &msg));
1040         CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
1041
1042         /* Create a name for the question section. */
1043         CHECK(dns_message_gettempname(msg, &qname));
1044         dns_name_init(qname, NULL);
1045         dns_name_clone(&xfr->name, qname);
1046
1047         /* Formulate the question and attach it to the question name. */
1048         CHECK(dns_message_gettemprdataset(msg, &qrdataset));
1049         dns_rdataset_init(qrdataset);
1050         dns_rdataset_makequestion(qrdataset, xfr->rdclass, xfr->reqtype);
1051         ISC_LIST_APPEND(qname->list, qrdataset, link);
1052         qrdataset = NULL;
1053
1054         dns_message_addname(msg, qname, DNS_SECTION_QUESTION);
1055         qname = NULL;
1056
1057         if (xfr->reqtype == dns_rdatatype_ixfr) {
1058                 /* Get the SOA and add it to the authority section. */
1059                 /* XXX is using the current version the right thing? */
1060                 dns_db_currentversion(xfr->db, &ver);
1061                 CHECK(dns_db_createsoatuple(xfr->db, ver, xfr->mctx,
1062                                             DNS_DIFFOP_EXISTS, &soatuple));
1063                 xfr->ixfr.request_serial = dns_soa_getserial(&soatuple->rdata);
1064                 xfr->ixfr.current_serial = xfr->ixfr.request_serial;
1065                 xfrin_log(xfr, ISC_LOG_DEBUG(3),
1066                           "requesting IXFR for serial %u",
1067                           xfr->ixfr.request_serial);
1068
1069                 CHECK(tuple2msgname(soatuple, msg, &msgsoaname));
1070                 dns_message_addname(msg, msgsoaname, DNS_SECTION_AUTHORITY);
1071         } else if (xfr->reqtype == dns_rdatatype_soa)
1072                 CHECK(dns_db_getsoaserial(xfr->db, NULL,
1073                                           &xfr->ixfr.request_serial));
1074
1075         xfr->checkid = ISC_TRUE;
1076         xfr->id++;
1077         xfr->nmsg = 0;
1078         xfr->nrecs = 0;
1079         xfr->nbytes = 0;
1080         isc_time_now(&xfr->start);
1081         msg->id = xfr->id;
1082         if (xfr->tsigctx != NULL)
1083                 dst_context_destroy(&xfr->tsigctx);
1084
1085         CHECK(render(msg, xfr->mctx, &xfr->qbuffer));
1086
1087         /*
1088          * Free the last tsig, if there is one.
1089          */
1090         if (xfr->lasttsig != NULL)
1091                 isc_buffer_free(&xfr->lasttsig);
1092
1093         /*
1094          * Save the query TSIG and don't let message_destroy free it.
1095          */
1096         CHECK(dns_message_getquerytsig(msg, xfr->mctx, &xfr->lasttsig));
1097
1098         isc_buffer_usedregion(&xfr->qbuffer, &region);
1099         INSIST(region.length <= 65535);
1100
1101         length[0] = region.length >> 8;
1102         length[1] = region.length & 0xFF;
1103         lregion.base = length;
1104         lregion.length = 2;
1105         CHECK(isc_socket_send(xfr->socket, &lregion, xfr->task,
1106                               xfrin_sendlen_done, xfr));
1107         xfr->sends++;
1108
1109  failure:
1110         if (qname != NULL)
1111                 dns_message_puttempname(msg, &qname);
1112         if (qrdataset != NULL)
1113                 dns_message_puttemprdataset(msg, &qrdataset);
1114         if (msg != NULL)
1115                 dns_message_destroy(&msg);
1116         if (soatuple != NULL)
1117                 dns_difftuple_free(&soatuple);
1118         if (ver != NULL)
1119                 dns_db_closeversion(xfr->db, &ver, ISC_FALSE);
1120         return (result);
1121 }
1122
1123 /* XXX there should be library support for sending DNS TCP messages */
1124
1125 static void
1126 xfrin_sendlen_done(isc_task_t *task, isc_event_t *event) {
1127         isc_socketevent_t *sev = (isc_socketevent_t *) event;
1128         dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1129         isc_result_t evresult = sev->result;
1130         isc_result_t result;
1131         isc_region_t region;
1132
1133         REQUIRE(VALID_XFRIN(xfr));
1134
1135         UNUSED(task);
1136
1137         INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1138         isc_event_free(&event);
1139
1140         xfr->sends--;
1141         if (xfr->shuttingdown) {
1142                 maybe_free(xfr);
1143                 return;
1144         }
1145
1146         xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request length prefix");
1147         CHECK(evresult);
1148
1149         isc_buffer_usedregion(&xfr->qbuffer, &region);
1150         CHECK(isc_socket_send(xfr->socket, &region, xfr->task,
1151                               xfrin_send_done, xfr));
1152         xfr->sends++;
1153  failure:
1154         if (result != ISC_R_SUCCESS)
1155                 xfrin_fail(xfr, result, "failed sending request length prefix");
1156 }
1157
1158
1159 static void
1160 xfrin_send_done(isc_task_t *task, isc_event_t *event) {
1161         isc_socketevent_t *sev = (isc_socketevent_t *) event;
1162         dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1163         isc_result_t result;
1164
1165         REQUIRE(VALID_XFRIN(xfr));
1166
1167         UNUSED(task);
1168
1169         INSIST(event->ev_type == ISC_SOCKEVENT_SENDDONE);
1170
1171         xfr->sends--;
1172         xfrin_log(xfr, ISC_LOG_DEBUG(3), "sent request data");
1173         CHECK(sev->result);
1174
1175         CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
1176                                      xfrin_recv_done, xfr));
1177         xfr->recvs++;
1178  failure:
1179         isc_event_free(&event);
1180         if (result != ISC_R_SUCCESS)
1181                 xfrin_fail(xfr, result, "failed sending request data");
1182 }
1183
1184
1185 static void
1186 xfrin_recv_done(isc_task_t *task, isc_event_t *ev) {
1187         dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) ev->ev_arg;
1188         isc_result_t result;
1189         dns_message_t *msg = NULL;
1190         dns_name_t *name;
1191         dns_tcpmsg_t *tcpmsg;
1192         dns_name_t *tsigowner = NULL;
1193
1194         REQUIRE(VALID_XFRIN(xfr));
1195
1196         UNUSED(task);
1197
1198         INSIST(ev->ev_type == DNS_EVENT_TCPMSG);
1199         tcpmsg = ev->ev_sender;
1200         isc_event_free(&ev);
1201
1202         xfr->recvs--;
1203         if (xfr->shuttingdown) {
1204                 maybe_free(xfr);
1205                 return;
1206         }
1207
1208         CHECK(tcpmsg->result);
1209
1210         xfrin_log(xfr, ISC_LOG_DEBUG(7), "received %u bytes",
1211                   tcpmsg->buffer.used);
1212
1213         CHECK(isc_timer_touch(xfr->timer));
1214
1215         CHECK(dns_message_create(xfr->mctx, DNS_MESSAGE_INTENTPARSE, &msg));
1216
1217         CHECK(dns_message_settsigkey(msg, xfr->tsigkey));
1218         CHECK(dns_message_setquerytsig(msg, xfr->lasttsig));
1219
1220         msg->tsigctx = xfr->tsigctx;
1221         xfr->tsigctx = NULL;
1222
1223         if (xfr->nmsg > 0)
1224                 msg->tcp_continuation = 1;
1225
1226         result = dns_message_parse(msg, &tcpmsg->buffer,
1227                                    DNS_MESSAGEPARSE_PRESERVEORDER);
1228
1229         if (result != ISC_R_SUCCESS || msg->rcode != dns_rcode_noerror ||
1230             (xfr->checkid && msg->id != xfr->id)) {
1231                 if (result == ISC_R_SUCCESS)
1232                         result = ISC_RESULTCLASS_DNSRCODE + msg->rcode; /*XXX*/
1233                 if (result == ISC_R_SUCCESS || result == DNS_R_NOERROR)
1234                         result = DNS_R_UNEXPECTEDID;
1235                 if (xfr->reqtype == dns_rdatatype_axfr ||
1236                     xfr->reqtype == dns_rdatatype_soa)
1237                         FAIL(result);
1238                 xfrin_log(xfr, ISC_LOG_DEBUG(3), "got %s, retrying with AXFR",
1239                        isc_result_totext(result));
1240  try_axfr:
1241                 dns_message_destroy(&msg);
1242                 xfrin_reset(xfr);
1243                 xfr->reqtype = dns_rdatatype_soa;
1244                 xfr->state = XFRST_SOAQUERY;
1245                 (void)xfrin_start(xfr);
1246                 return;
1247         }
1248
1249         /*
1250          * Does the server know about IXFR?  If it doesn't we will get
1251          * a message with a empty answer section or a potentially a CNAME /
1252          * DNAME, the later is handled by xfr_rr() which will return FORMERR
1253          * if the first RR in the answer section is not a SOA record.
1254          */
1255         if (xfr->reqtype == dns_rdatatype_ixfr &&
1256             xfr->state == XFRST_INITIALSOA &&
1257             msg->counts[DNS_SECTION_ANSWER] == 0) {
1258                 xfrin_log(xfr, ISC_LOG_DEBUG(3),
1259                           "empty answer section, retrying with AXFR");
1260                 goto try_axfr;
1261         }
1262
1263         if (xfr->reqtype == dns_rdatatype_soa &&
1264             (msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
1265                 FAIL(DNS_R_NOTAUTHORITATIVE);
1266         }
1267
1268
1269         result = dns_message_checksig(msg, dns_zone_getview(xfr->zone));
1270         if (result != ISC_R_SUCCESS) {
1271                 xfrin_log(xfr, ISC_LOG_DEBUG(3), "TSIG check failed: %s",
1272                        isc_result_totext(result));
1273                 FAIL(result);
1274         }
1275
1276         for (result = dns_message_firstname(msg, DNS_SECTION_ANSWER);
1277              result == ISC_R_SUCCESS;
1278              result = dns_message_nextname(msg, DNS_SECTION_ANSWER))
1279         {
1280                 dns_rdataset_t *rds;
1281
1282                 name = NULL;
1283                 dns_message_currentname(msg, DNS_SECTION_ANSWER, &name);
1284                 for (rds = ISC_LIST_HEAD(name->list);
1285                      rds != NULL;
1286                      rds = ISC_LIST_NEXT(rds, link))
1287                 {
1288                         for (result = dns_rdataset_first(rds);
1289                              result == ISC_R_SUCCESS;
1290                              result = dns_rdataset_next(rds))
1291                         {
1292                                 dns_rdata_t rdata = DNS_RDATA_INIT;
1293                                 dns_rdataset_current(rds, &rdata);
1294                                 CHECK(xfr_rr(xfr, name, rds->ttl, &rdata));
1295                         }
1296                 }
1297         }
1298         if (result != ISC_R_NOMORE)
1299                 goto failure;
1300
1301         if (dns_message_gettsig(msg, &tsigowner) != NULL) {
1302                 /*
1303                  * Reset the counter.
1304                  */
1305                 xfr->sincetsig = 0;
1306
1307                 /*
1308                  * Free the last tsig, if there is one.
1309                  */
1310                 if (xfr->lasttsig != NULL)
1311                         isc_buffer_free(&xfr->lasttsig);
1312
1313                 /*
1314                  * Update the last tsig pointer.
1315                  */
1316                 CHECK(dns_message_getquerytsig(msg, xfr->mctx,
1317                                                &xfr->lasttsig));
1318
1319         } else if (dns_message_gettsigkey(msg) != NULL) {
1320                 xfr->sincetsig++;
1321                 if (xfr->sincetsig > 100 ||
1322                     xfr->nmsg == 0 || xfr->state == XFRST_END)
1323                 {
1324                         result = DNS_R_EXPECTEDTSIG;
1325                         goto failure;
1326                 }
1327         }
1328
1329         /*
1330          * Update the number of messages received.
1331          */
1332         xfr->nmsg++;
1333
1334         /*
1335          * Update the number of bytes received.
1336          */
1337         xfr->nbytes += tcpmsg->buffer.used;
1338
1339         /*
1340          * Take the context back.
1341          */
1342         INSIST(xfr->tsigctx == NULL);
1343         xfr->tsigctx = msg->tsigctx;
1344         msg->tsigctx = NULL;
1345
1346         dns_message_destroy(&msg);
1347
1348         if (xfr->state == XFRST_GOTSOA) {
1349                 xfr->reqtype = dns_rdatatype_axfr;
1350                 xfr->state = XFRST_INITIALSOA;
1351                 CHECK(xfrin_send_request(xfr));
1352         } else if (xfr->state == XFRST_END) {
1353                 /*
1354                  * Close the journal.
1355                  */
1356                 if (xfr->ixfr.journal != NULL)
1357                         dns_journal_destroy(&xfr->ixfr.journal);
1358                 /*
1359                  * Inform the caller we succeeded.
1360                  */
1361                 if (xfr->done != NULL) {
1362                         (xfr->done)(xfr->zone, ISC_R_SUCCESS);
1363                         xfr->done = NULL;
1364                 }
1365                 /*
1366                  * We should have no outstanding events at this
1367                  * point, thus maybe_free() should succeed.
1368                  */
1369                 xfr->shuttingdown = ISC_TRUE;
1370                 maybe_free(xfr);
1371         } else {
1372                 /*
1373                  * Read the next message.
1374                  */
1375                 CHECK(dns_tcpmsg_readmessage(&xfr->tcpmsg, xfr->task,
1376                                              xfrin_recv_done, xfr));
1377                 xfr->recvs++;
1378         }
1379         return;
1380
1381  failure:
1382         if (msg != NULL)
1383                 dns_message_destroy(&msg);
1384         if (result != ISC_R_SUCCESS)
1385                 xfrin_fail(xfr, result, "failed while receiving responses");
1386 }
1387
1388 static void
1389 xfrin_timeout(isc_task_t *task, isc_event_t *event) {
1390         dns_xfrin_ctx_t *xfr = (dns_xfrin_ctx_t *) event->ev_arg;
1391
1392         REQUIRE(VALID_XFRIN(xfr));
1393
1394         UNUSED(task);
1395
1396         isc_event_free(&event);
1397         /*
1398          * This will log "giving up: timeout".
1399          */
1400         xfrin_fail(xfr, ISC_R_TIMEDOUT, "giving up");
1401 }
1402
1403 static void
1404 maybe_free(dns_xfrin_ctx_t *xfr) {
1405         isc_uint64_t msecs;
1406         isc_uint64_t persec;
1407
1408         REQUIRE(VALID_XFRIN(xfr));
1409
1410         if (! xfr->shuttingdown || xfr->refcount != 0 ||
1411             xfr->connects != 0 || xfr->sends != 0 ||
1412             xfr->recvs != 0)
1413                 return;
1414
1415         /*
1416          * Calculate the length of time the transfer took,
1417          * and print a log message with the bytes and rate.
1418          */
1419         isc_time_now(&xfr->end);
1420         msecs = isc_time_microdiff(&xfr->end, &xfr->start) / 1000;
1421         if (msecs == 0)
1422                 msecs = 1;
1423         persec = (xfr->nbytes * 1000) / msecs;
1424         xfrin_log(xfr, ISC_LOG_INFO,
1425                   "Transfer completed: %d messages, %d records, "
1426                   "%" ISC_PRINT_QUADFORMAT "u bytes, "
1427                   "%u.%03u secs (%u bytes/sec)",
1428                   xfr->nmsg, xfr->nrecs, xfr->nbytes,
1429                   (unsigned int) (msecs / 1000), (unsigned int) (msecs % 1000),
1430                   (unsigned int) persec);
1431
1432         if (xfr->socket != NULL)
1433                 isc_socket_detach(&xfr->socket);
1434
1435         if (xfr->timer != NULL)
1436                 isc_timer_detach(&xfr->timer);
1437
1438         if (xfr->task != NULL)
1439                 isc_task_detach(&xfr->task);
1440
1441         if (xfr->tsigkey != NULL)
1442                 dns_tsigkey_detach(&xfr->tsigkey);
1443
1444         if (xfr->lasttsig != NULL)
1445                 isc_buffer_free(&xfr->lasttsig);
1446
1447         dns_diff_clear(&xfr->diff);
1448
1449         if (xfr->ixfr.journal != NULL)
1450                 dns_journal_destroy(&xfr->ixfr.journal);
1451
1452         if (xfr->axfr.add_private != NULL)
1453                 (void)dns_db_endload(xfr->db, &xfr->axfr.add_private);
1454
1455         if (xfr->tcpmsg_valid)
1456                 dns_tcpmsg_invalidate(&xfr->tcpmsg);
1457
1458         if (xfr->tsigctx != NULL)
1459                 dst_context_destroy(&xfr->tsigctx);
1460
1461         if ((xfr->name.attributes & DNS_NAMEATTR_DYNAMIC) != 0)
1462                 dns_name_free(&xfr->name, xfr->mctx);
1463
1464         if (xfr->ver != NULL)
1465                 dns_db_closeversion(xfr->db, &xfr->ver, ISC_FALSE);
1466
1467         if (xfr->db != NULL)
1468                 dns_db_detach(&xfr->db);
1469
1470         if (xfr->zone != NULL)
1471                 dns_zone_idetach(&xfr->zone);
1472
1473         isc_mem_put(xfr->mctx, xfr, sizeof(*xfr));
1474 }
1475
1476 /*
1477  * Log incoming zone transfer messages in a format like
1478  * transfer of <zone> from <address>: <message>
1479  */
1480 static void
1481 xfrin_logv(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
1482            const char *fmt, va_list ap)
1483 {
1484         char mastertext[ISC_SOCKADDR_FORMATSIZE];
1485         char msgtext[2048];
1486
1487         isc_sockaddr_format(masteraddr, mastertext, sizeof(mastertext));
1488         vsnprintf(msgtext, sizeof(msgtext), fmt, ap);
1489
1490         isc_log_write(dns_lctx, DNS_LOGCATEGORY_XFER_IN,
1491                       DNS_LOGMODULE_XFER_IN, level,
1492                       "transfer of '%s' from %s: %s",
1493                       zonetext, mastertext, msgtext);
1494 }
1495
1496 /*
1497  * Logging function for use when a xfrin_ctx_t has not yet been created.
1498  */
1499
1500 static void
1501 xfrin_log1(int level, const char *zonetext, isc_sockaddr_t *masteraddr,
1502            const char *fmt, ...)
1503 {
1504         va_list ap;
1505
1506         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
1507                 return;
1508
1509         va_start(ap, fmt);
1510         xfrin_logv(level, zonetext, masteraddr, fmt, ap);
1511         va_end(ap);
1512 }
1513
1514 /*
1515  * Logging function for use when there is a xfrin_ctx_t.
1516  */
1517
1518 static void
1519 xfrin_log(dns_xfrin_ctx_t *xfr, int level, const char *fmt, ...)
1520 {
1521         va_list ap;
1522         char zonetext[DNS_NAME_MAXTEXT+32];
1523
1524         if (isc_log_wouldlog(dns_lctx, level) == ISC_FALSE)
1525                 return;
1526
1527         dns_zone_name(xfr->zone, zonetext, sizeof(zonetext));
1528
1529         va_start(ap, fmt);
1530         xfrin_logv(level, zonetext, &xfr->masteraddr, fmt, ap);
1531         va_end(ap);
1532 }