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