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