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