Sun Oct 9 14:53:54 2016 UTC ()
PR/51542: Henning Petersen: replace , with ;


(christos)
diff -r1.11 -r1.12 src/external/bsd/bind/dist/bin/named/xfrout.c

cvs diff -r1.11 -r1.12 src/external/bsd/bind/dist/bin/named/Attic/xfrout.c (switch to unified diff)

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