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