ixfr.c revision 1.1 1 1.1 christos /*
2 1.1 christos * ixfr.c -- generating IXFR responses.
3 1.1 christos *
4 1.1 christos * Copyright (c) 2021, NLnet Labs. All rights reserved.
5 1.1 christos *
6 1.1 christos * See LICENSE for the license.
7 1.1 christos *
8 1.1 christos */
9 1.1 christos
10 1.1 christos #include "config.h"
11 1.1 christos
12 1.1 christos #include <errno.h>
13 1.1 christos #include <string.h>
14 1.1 christos #include <ctype.h>
15 1.1 christos #ifdef HAVE_SYS_TYPES_H
16 1.1 christos # include <sys/types.h>
17 1.1 christos #endif
18 1.1 christos #ifdef HAVE_SYS_STAT_H
19 1.1 christos # include <sys/stat.h>
20 1.1 christos #endif
21 1.1 christos #include <unistd.h>
22 1.1 christos
23 1.1 christos #include "ixfr.h"
24 1.1 christos #include "packet.h"
25 1.1 christos #include "rdata.h"
26 1.1 christos #include "axfr.h"
27 1.1 christos #include "options.h"
28 1.1 christos #include "zonec.h"
29 1.1 christos
30 1.1 christos /*
31 1.1 christos * For optimal compression IXFR response packets are limited in size
32 1.1 christos * to MAX_COMPRESSION_OFFSET.
33 1.1 christos */
34 1.1 christos #define IXFR_MAX_MESSAGE_LEN MAX_COMPRESSION_OFFSET
35 1.1 christos
36 1.1 christos /* draft-ietf-dnsop-rfc2845bis-06, section 5.3.1 says to sign every packet */
37 1.1 christos #define IXFR_TSIG_SIGN_EVERY_NTH 0 /* tsig sign every N packets. */
38 1.1 christos
39 1.1 christos /* initial space in rrs data for storing records */
40 1.1 christos #define IXFR_STORE_INITIAL_SIZE 4096
41 1.1 christos
42 1.1 christos /* store compression for one name */
43 1.1 christos struct rrcompress_entry {
44 1.1 christos /* rbtree node, key is this struct */
45 1.1 christos struct rbnode node;
46 1.1 christos /* the uncompressed domain name */
47 1.1 christos const uint8_t* dname;
48 1.1 christos /* the length of the dname, includes terminating 0 label */
49 1.1 christos uint16_t len;
50 1.1 christos /* the offset of the dname in the packet */
51 1.1 christos uint16_t offset;
52 1.1 christos };
53 1.1 christos
54 1.1 christos /* structure to store compression data for the packet */
55 1.1 christos struct pktcompression {
56 1.1 christos /* rbtree of rrcompress_entry. sorted by dname */
57 1.1 christos struct rbtree tree;
58 1.1 christos /* allocation information, how many bytes allocated now */
59 1.1 christos size_t alloc_now;
60 1.1 christos /* allocation information, total size in block */
61 1.1 christos size_t alloc_max;
62 1.1 christos /* region to use if block full, this is NULL if unused */
63 1.1 christos struct region* region;
64 1.1 christos /* block of temp data for allocation */
65 1.1 christos uint8_t block[sizeof(struct rrcompress_entry)*1024];
66 1.1 christos };
67 1.1 christos
68 1.1 christos /* compare two elements in the compression tree. Returns -1, 0, or 1. */
69 1.1 christos static int compression_cmp(const void* a, const void* b)
70 1.1 christos {
71 1.1 christos struct rrcompress_entry* rra = (struct rrcompress_entry*)a;
72 1.1 christos struct rrcompress_entry* rrb = (struct rrcompress_entry*)b;
73 1.1 christos if(rra->len != rrb->len) {
74 1.1 christos if(rra->len < rrb->len)
75 1.1 christos return -1;
76 1.1 christos return 1;
77 1.1 christos }
78 1.1 christos return memcmp(rra->dname, rrb->dname, rra->len);
79 1.1 christos }
80 1.1 christos
81 1.1 christos /* init the pktcompression to a new packet */
82 1.1 christos static void pktcompression_init(struct pktcompression* pcomp)
83 1.1 christos {
84 1.1 christos pcomp->alloc_now = 0;
85 1.1 christos pcomp->alloc_max = sizeof(pcomp->block);
86 1.1 christos pcomp->region = NULL;
87 1.1 christos pcomp->tree.root = RBTREE_NULL;
88 1.1 christos pcomp->tree.count = 0;
89 1.1 christos pcomp->tree.region = NULL;
90 1.1 christos pcomp->tree.cmp = &compression_cmp;
91 1.1 christos }
92 1.1 christos
93 1.1 christos /* freeup the pktcompression data */
94 1.1 christos static void pktcompression_freeup(struct pktcompression* pcomp)
95 1.1 christos {
96 1.1 christos if(pcomp->region) {
97 1.1 christos region_destroy(pcomp->region);
98 1.1 christos pcomp->region = NULL;
99 1.1 christos }
100 1.1 christos pcomp->alloc_now = 0;
101 1.1 christos pcomp->tree.root = RBTREE_NULL;
102 1.1 christos pcomp->tree.count = 0;
103 1.1 christos }
104 1.1 christos
105 1.1 christos /* alloc data in pktcompression */
106 1.1 christos static void* pktcompression_alloc(struct pktcompression* pcomp, size_t s)
107 1.1 christos {
108 1.1 christos /* first attempt to allocate in the fixed block,
109 1.1 christos * that is very fast and on the stack in the pcomp struct */
110 1.1 christos if(pcomp->alloc_now + s <= pcomp->alloc_max) {
111 1.1 christos void* ret = pcomp->block + pcomp->alloc_now;
112 1.1 christos pcomp->alloc_now += s;
113 1.1 christos return ret;
114 1.1 christos }
115 1.1 christos
116 1.1 christos /* if that fails, create a region to allocate in,
117 1.1 christos * it is freed in the freeup */
118 1.1 christos if(!pcomp->region) {
119 1.1 christos pcomp->region = region_create(xalloc, free);
120 1.1 christos if(!pcomp->region)
121 1.1 christos return NULL;
122 1.1 christos }
123 1.1 christos return region_alloc(pcomp->region, s);
124 1.1 christos }
125 1.1 christos
126 1.1 christos /* find a pktcompression name, return offset if found */
127 1.1 christos static uint16_t pktcompression_find(struct pktcompression* pcomp,
128 1.1 christos const uint8_t* dname, size_t len)
129 1.1 christos {
130 1.1 christos struct rrcompress_entry key, *found;
131 1.1 christos key.node.key = &key;
132 1.1 christos key.dname = dname;
133 1.1 christos key.len = len;
134 1.1 christos found = (struct rrcompress_entry*)rbtree_search(&pcomp->tree, &key);
135 1.1 christos if(found) return found->offset;
136 1.1 christos return 0;
137 1.1 christos }
138 1.1 christos
139 1.1 christos /* insert a new domain name into the compression tree.
140 1.1 christos * it fails silently, no need to compress then. */
141 1.1 christos static void pktcompression_insert(struct pktcompression* pcomp,
142 1.1 christos const uint8_t* dname, size_t len, uint16_t offset)
143 1.1 christos {
144 1.1 christos struct rrcompress_entry* entry;
145 1.1 christos if(len > 65535)
146 1.1 christos return;
147 1.1 christos if(offset > MAX_COMPRESSION_OFFSET)
148 1.1 christos return; /* too far for a compression pointer */
149 1.1 christos entry = pktcompression_alloc(pcomp, sizeof(*entry));
150 1.1 christos if(!entry)
151 1.1 christos return;
152 1.1 christos memset(&entry->node, 0, sizeof(entry->node));
153 1.1 christos entry->node.key = entry;
154 1.1 christos entry->dname = dname;
155 1.1 christos entry->len = len;
156 1.1 christos entry->offset = offset;
157 1.1 christos (void)rbtree_insert(&pcomp->tree, &entry->node);
158 1.1 christos }
159 1.1 christos
160 1.1 christos /* insert all the labels of a domain name */
161 1.1 christos static void pktcompression_insert_with_labels(struct pktcompression* pcomp,
162 1.1 christos uint8_t* dname, size_t len, uint16_t offset)
163 1.1 christos {
164 1.1 christos if(!dname)
165 1.1 christos return;
166 1.1 christos if(offset > MAX_COMPRESSION_OFFSET)
167 1.1 christos return;
168 1.1 christos
169 1.1 christos /* while we have not seen the end root label */
170 1.1 christos while(len > 0 && dname[0] != 0) {
171 1.1 christos size_t lablen;
172 1.1 christos pktcompression_insert(pcomp, dname, len, offset);
173 1.1 christos lablen = (size_t)(dname[0]);
174 1.1 christos if( (lablen&0xc0) )
175 1.1 christos return; /* the dname should be uncompressed */
176 1.1 christos if(lablen+1 > len)
177 1.1 christos return; /* len should be uncompressed wireformat len */
178 1.1 christos if(offset > MAX_COMPRESSION_OFFSET - lablen - 1)
179 1.1 christos return; /* offset moves too far for compression */
180 1.1 christos /* skip label */
181 1.1 christos len -= lablen+1;
182 1.1 christos dname += lablen+1;
183 1.1 christos offset += lablen+1;
184 1.1 christos }
185 1.1 christos }
186 1.1 christos
187 1.1 christos /* calculate length of dname in uncompressed wireformat in buffer */
188 1.1 christos static size_t dname_length(const uint8_t* buf, size_t len)
189 1.1 christos {
190 1.1 christos size_t l = 0;
191 1.1 christos if(!buf || len == 0)
192 1.1 christos return l;
193 1.1 christos while(len > 0 && buf[0] != 0) {
194 1.1 christos size_t lablen = (size_t)(buf[0]);
195 1.1 christos if( (lablen&0xc0) )
196 1.1 christos return 0; /* the name should be uncompressed */
197 1.1 christos if(lablen+1 > len)
198 1.1 christos return 0; /* should fit in the buffer */
199 1.1 christos l += lablen+1;
200 1.1 christos len -= lablen+1;
201 1.1 christos buf += lablen+1;
202 1.1 christos }
203 1.1 christos if(len == 0)
204 1.1 christos return 0; /* end label should fit in buffer */
205 1.1 christos if(buf[0] != 0)
206 1.1 christos return 0; /* must end in root label */
207 1.1 christos l += 1; /* for the end root label */
208 1.1 christos return l;
209 1.1 christos }
210 1.1 christos
211 1.1 christos /* write a compressed domain name into the packet,
212 1.1 christos * returns uncompressed wireformat length,
213 1.1 christos * 0 if it does not fit and -1 on failure, bad dname. */
214 1.1 christos static int pktcompression_write_dname(struct buffer* packet,
215 1.1 christos struct pktcompression* pcomp, const uint8_t* rr, size_t rrlen)
216 1.1 christos {
217 1.1 christos size_t wirelen = 0;
218 1.1 christos size_t dname_len = dname_length(rr, rrlen);
219 1.1 christos if(!rr || rrlen == 0 || dname_len == 0)
220 1.1 christos return 0;
221 1.1 christos while(rrlen > 0 && rr[0] != 0) {
222 1.1 christos size_t lablen = (size_t)(rr[0]);
223 1.1 christos uint16_t offset;
224 1.1 christos if( (lablen&0xc0) )
225 1.1 christos return -1; /* name should be uncompressed */
226 1.1 christos if(lablen+1 > rrlen)
227 1.1 christos return -1; /* name should fit */
228 1.1 christos
229 1.1 christos /* see if the domain name has a compression pointer */
230 1.1 christos if((offset=pktcompression_find(pcomp, rr, dname_len))!=0) {
231 1.1 christos if(!buffer_available(packet, 2))
232 1.1 christos return 0;
233 1.1 christos buffer_write_u16(packet, (uint16_t)(0xc000 | offset));
234 1.1 christos wirelen += dname_len;
235 1.1 christos return wirelen;
236 1.1 christos } else {
237 1.1 christos if(!buffer_available(packet, lablen+1))
238 1.1 christos return 0;
239 1.1 christos /* insert the domain name at this position */
240 1.1 christos pktcompression_insert(pcomp, rr, dname_len,
241 1.1 christos buffer_position(packet));
242 1.1 christos /* write it */
243 1.1 christos buffer_write(packet, rr, lablen+1);
244 1.1 christos }
245 1.1 christos
246 1.1 christos wirelen += lablen+1;
247 1.1 christos rr += lablen+1;
248 1.1 christos rrlen -= lablen+1;
249 1.1 christos dname_len -= lablen+1;
250 1.1 christos }
251 1.1 christos if(rrlen > 0 && rr[0] == 0) {
252 1.1 christos /* write end root label */
253 1.1 christos if(!buffer_available(packet, 1))
254 1.1 christos return 0;
255 1.1 christos buffer_write_u8(packet, 0);
256 1.1 christos wirelen += 1;
257 1.1 christos }
258 1.1 christos return wirelen;
259 1.1 christos }
260 1.1 christos
261 1.1 christos /* write an RR into the packet with compression for domain names,
262 1.1 christos * return 0 and resets position if it does not fit in the packet. */
263 1.1 christos static int ixfr_write_rr_pkt(struct query* query, struct buffer* packet,
264 1.1 christos struct pktcompression* pcomp, const uint8_t* rr, size_t rrlen)
265 1.1 christos {
266 1.1 christos size_t oldpos = buffer_position(packet);
267 1.1 christos size_t rdpos;
268 1.1 christos uint16_t tp;
269 1.1 christos int dname_len;
270 1.1 christos size_t rdlen;
271 1.1 christos size_t i;
272 1.1 christos rrtype_descriptor_type* descriptor;
273 1.1 christos
274 1.1 christos if(buffer_position(packet) > MAX_COMPRESSION_OFFSET
275 1.1 christos || query_overflow(query)) {
276 1.1 christos /* we are past the maximum length */
277 1.1 christos return 0;
278 1.1 christos }
279 1.1 christos
280 1.1 christos /* write owner */
281 1.1 christos dname_len = pktcompression_write_dname(packet, pcomp, rr, rrlen);
282 1.1 christos if(dname_len == -1)
283 1.1 christos return 1; /* attempt to skip this malformed rr, could assert */
284 1.1 christos if(dname_len == 0) {
285 1.1 christos buffer_set_position(packet, oldpos);
286 1.1 christos return 0;
287 1.1 christos }
288 1.1 christos rr += dname_len;
289 1.1 christos rrlen -= dname_len;
290 1.1 christos
291 1.1 christos /* type, class, ttl, rdatalen */
292 1.1 christos if(!buffer_available(packet, 10)) {
293 1.1 christos buffer_set_position(packet, oldpos);
294 1.1 christos return 0;
295 1.1 christos }
296 1.1 christos if(10 > rrlen)
297 1.1 christos return 1; /* attempt to skip this malformed rr, could assert */
298 1.1 christos tp = read_uint16(rr);
299 1.1 christos buffer_write(packet, rr, 8);
300 1.1 christos rr += 8;
301 1.1 christos rrlen -= 8;
302 1.1 christos rdlen = read_uint16(rr);
303 1.1 christos rr += 2;
304 1.1 christos rrlen -= 2;
305 1.1 christos rdpos = buffer_position(packet);
306 1.1 christos buffer_write_u16(packet, 0);
307 1.1 christos if(rdlen > rrlen)
308 1.1 christos return 1; /* attempt to skip this malformed rr, could assert */
309 1.1 christos
310 1.1 christos /* rdata */
311 1.1 christos descriptor = rrtype_descriptor_by_type(tp);
312 1.1 christos for(i=0; i<descriptor->maximum; i++) {
313 1.1 christos size_t copy_len = 0;
314 1.1 christos if(rdlen == 0)
315 1.1 christos break;
316 1.1 christos
317 1.1 christos switch(rdata_atom_wireformat_type(tp, i)) {
318 1.1 christos case RDATA_WF_COMPRESSED_DNAME:
319 1.1 christos dname_len = pktcompression_write_dname(packet, pcomp,
320 1.1 christos rr, rdlen);
321 1.1 christos if(dname_len == -1)
322 1.1 christos return 1; /* attempt to skip malformed rr */
323 1.1 christos if(dname_len == 0) {
324 1.1 christos buffer_set_position(packet, oldpos);
325 1.1 christos return 0;
326 1.1 christos }
327 1.1 christos rr += dname_len;
328 1.1 christos rdlen -= dname_len;
329 1.1 christos break;
330 1.1 christos case RDATA_WF_UNCOMPRESSED_DNAME:
331 1.1 christos case RDATA_WF_LITERAL_DNAME:
332 1.1 christos copy_len = rdlen;
333 1.1 christos break;
334 1.1 christos case RDATA_WF_BYTE:
335 1.1 christos copy_len = 1;
336 1.1 christos break;
337 1.1 christos case RDATA_WF_SHORT:
338 1.1 christos copy_len = 2;
339 1.1 christos break;
340 1.1 christos case RDATA_WF_LONG:
341 1.1 christos copy_len = 4;
342 1.1 christos break;
343 1.1 christos case RDATA_WF_TEXTS:
344 1.1 christos case RDATA_WF_LONG_TEXT:
345 1.1 christos copy_len = rdlen;
346 1.1 christos break;
347 1.1 christos case RDATA_WF_TEXT:
348 1.1 christos case RDATA_WF_BINARYWITHLENGTH:
349 1.1 christos copy_len = 1;
350 1.1 christos if(rdlen > copy_len)
351 1.1 christos copy_len += rr[0];
352 1.1 christos break;
353 1.1 christos case RDATA_WF_A:
354 1.1 christos copy_len = 4;
355 1.1 christos break;
356 1.1 christos case RDATA_WF_AAAA:
357 1.1 christos copy_len = 16;
358 1.1 christos break;
359 1.1 christos case RDATA_WF_ILNP64:
360 1.1 christos copy_len = 8;
361 1.1 christos break;
362 1.1 christos case RDATA_WF_EUI48:
363 1.1 christos copy_len = EUI48ADDRLEN;
364 1.1 christos break;
365 1.1 christos case RDATA_WF_EUI64:
366 1.1 christos copy_len = EUI64ADDRLEN;
367 1.1 christos break;
368 1.1 christos case RDATA_WF_BINARY:
369 1.1 christos copy_len = rdlen;
370 1.1 christos break;
371 1.1 christos case RDATA_WF_APL:
372 1.1 christos copy_len = (sizeof(uint16_t) /* address family */
373 1.1 christos + sizeof(uint8_t) /* prefix */
374 1.1 christos + sizeof(uint8_t)); /* length */
375 1.1 christos if(copy_len <= rdlen)
376 1.1 christos copy_len += (rr[copy_len-1]&APL_LENGTH_MASK);
377 1.1 christos break;
378 1.1 christos case RDATA_WF_IPSECGATEWAY:
379 1.1 christos copy_len = rdlen;
380 1.1 christos break;
381 1.1 christos case RDATA_WF_SVCPARAM:
382 1.1 christos copy_len = 4;
383 1.1 christos if(copy_len <= rdlen)
384 1.1 christos copy_len += read_uint16(rr+2);
385 1.1 christos break;
386 1.1 christos default:
387 1.1 christos copy_len = rdlen;
388 1.1 christos break;
389 1.1 christos }
390 1.1 christos if(copy_len) {
391 1.1 christos if(!buffer_available(packet, copy_len)) {
392 1.1 christos buffer_set_position(packet, oldpos);
393 1.1 christos return 0;
394 1.1 christos }
395 1.1 christos if(copy_len > rdlen)
396 1.1 christos return 1; /* assert of skip malformed */
397 1.1 christos buffer_write(packet, rr, copy_len);
398 1.1 christos rr += copy_len;
399 1.1 christos rdlen -= copy_len;
400 1.1 christos }
401 1.1 christos }
402 1.1 christos /* write compressed rdata length */
403 1.1 christos buffer_write_u16_at(packet, rdpos, buffer_position(packet)-rdpos-2);
404 1.1 christos if(query_overflow(query)) {
405 1.1 christos /* we are past the maximum length */
406 1.1 christos buffer_set_position(packet, oldpos);
407 1.1 christos return 0;
408 1.1 christos }
409 1.1 christos return 1;
410 1.1 christos }
411 1.1 christos
412 1.1 christos /* parse the serial number from the IXFR query */
413 1.1 christos static int parse_qserial(struct buffer* packet, uint32_t* qserial,
414 1.1 christos size_t* snip_pos)
415 1.1 christos {
416 1.1 christos unsigned int i;
417 1.1 christos uint16_t type, rdlen;
418 1.1 christos /* we must have a SOA in the authority section */
419 1.1 christos if(NSCOUNT(packet) == 0)
420 1.1 christos return 0;
421 1.1 christos /* skip over the question section, we want only one */
422 1.1 christos buffer_set_position(packet, QHEADERSZ);
423 1.1 christos if(QDCOUNT(packet) != 1)
424 1.1 christos return 0;
425 1.1 christos if(!packet_skip_rr(packet, 1))
426 1.1 christos return 0;
427 1.1 christos /* set position to snip off the authority section */
428 1.1 christos *snip_pos = buffer_position(packet);
429 1.1 christos /* skip over the authority section RRs until we find the SOA */
430 1.1 christos for(i=0; i<NSCOUNT(packet); i++) {
431 1.1 christos /* is this the SOA record? */
432 1.1 christos if(!packet_skip_dname(packet))
433 1.1 christos return 0; /* malformed name */
434 1.1 christos if(!buffer_available(packet, 10))
435 1.1 christos return 0; /* no type,class,ttl,rdatalen */
436 1.1 christos type = buffer_read_u16(packet);
437 1.1 christos buffer_skip(packet, 6);
438 1.1 christos rdlen = buffer_read_u16(packet);
439 1.1 christos if(!buffer_available(packet, rdlen))
440 1.1 christos return 0;
441 1.1 christos if(type == TYPE_SOA) {
442 1.1 christos /* read serial from rdata, skip two dnames, then
443 1.1 christos * read the 32bit value */
444 1.1 christos if(!packet_skip_dname(packet))
445 1.1 christos return 0; /* malformed nsname */
446 1.1 christos if(!packet_skip_dname(packet))
447 1.1 christos return 0; /* malformed rname */
448 1.1 christos if(!buffer_available(packet, 4))
449 1.1 christos return 0;
450 1.1 christos *qserial = buffer_read_u32(packet);
451 1.1 christos return 1;
452 1.1 christos }
453 1.1 christos buffer_skip(packet, rdlen);
454 1.1 christos }
455 1.1 christos return 0;
456 1.1 christos }
457 1.1 christos
458 1.1 christos /* get serial from SOA RR */
459 1.1 christos static uint32_t soa_rr_get_serial(struct rr* rr)
460 1.1 christos {
461 1.1 christos if(rr->rdata_count < 3)
462 1.1 christos return 0;
463 1.1 christos if(rr->rdatas[2].data[0] < 4)
464 1.1 christos return 0;
465 1.1 christos return read_uint32(&rr->rdatas[2].data[1]);
466 1.1 christos }
467 1.1 christos
468 1.1 christos /* get the current serial from the zone */
469 1.1 christos uint32_t zone_get_current_serial(struct zone* zone)
470 1.1 christos {
471 1.1 christos if(!zone || !zone->soa_rrset)
472 1.1 christos return 0;
473 1.1 christos if(zone->soa_rrset->rr_count == 0)
474 1.1 christos return 0;
475 1.1 christos if(zone->soa_rrset->rrs[0].rdata_count < 3)
476 1.1 christos return 0;
477 1.1 christos if(zone->soa_rrset->rrs[0].rdatas[2].data[0] < 4)
478 1.1 christos return 0;
479 1.1 christos return read_uint32(&zone->soa_rrset->rrs[0].rdatas[2].data[1]);
480 1.1 christos }
481 1.1 christos
482 1.1 christos /* iterator over ixfr data. find first element, eg. oldest zone version
483 1.1 christos * change.
484 1.1 christos * The iterator can be started with the ixfr_data_first, but also with
485 1.1 christos * ixfr_data_last, or with an existing ixfr_data element to start from.
486 1.1 christos * Continue by using ixfr_data_next or ixfr_data_prev to ask for more elements
487 1.1 christos * until that returns NULL. NULL because end of list or loop was detected.
488 1.1 christos * The ixfr_data_prev uses a counter, start it at 0, it returns NULL when
489 1.1 christos * a loop is detected.
490 1.1 christos */
491 1.1 christos static struct ixfr_data* ixfr_data_first(struct zone_ixfr* ixfr)
492 1.1 christos {
493 1.1 christos struct ixfr_data* n;
494 1.1 christos if(!ixfr || !ixfr->data || ixfr->data->count==0)
495 1.1 christos return NULL;
496 1.1 christos n = (struct ixfr_data*)rbtree_search(ixfr->data, &ixfr->oldest_serial);
497 1.1 christos if(!n || n == (struct ixfr_data*)RBTREE_NULL)
498 1.1 christos return NULL;
499 1.1 christos return n;
500 1.1 christos }
501 1.1 christos
502 1.1 christos /* iterator over ixfr data. find last element, eg. newest zone version
503 1.1 christos * change. */
504 1.1 christos static struct ixfr_data* ixfr_data_last(struct zone_ixfr* ixfr)
505 1.1 christos {
506 1.1 christos struct ixfr_data* n;
507 1.1 christos if(!ixfr || !ixfr->data || ixfr->data->count==0)
508 1.1 christos return NULL;
509 1.1 christos n = (struct ixfr_data*)rbtree_search(ixfr->data, &ixfr->newest_serial);
510 1.1 christos if(!n || n == (struct ixfr_data*)RBTREE_NULL)
511 1.1 christos return NULL;
512 1.1 christos return n;
513 1.1 christos }
514 1.1 christos
515 1.1 christos /* iterator over ixfr data. fetch next item. If loop or nothing, NULL */
516 1.1 christos static struct ixfr_data* ixfr_data_next(struct zone_ixfr* ixfr,
517 1.1 christos struct ixfr_data* cur)
518 1.1 christos {
519 1.1 christos struct ixfr_data* n;
520 1.1 christos if(!cur || cur == (struct ixfr_data*)RBTREE_NULL)
521 1.1 christos return NULL;
522 1.1 christos if(cur->oldserial == ixfr->newest_serial)
523 1.1 christos return NULL; /* that was the last element */
524 1.1 christos n = (struct ixfr_data*)rbtree_next(&cur->node);
525 1.1 christos if(n && n != (struct ixfr_data*)RBTREE_NULL &&
526 1.1 christos cur->newserial == n->oldserial) {
527 1.1 christos /* the next rbtree item is the next ixfr data item */
528 1.1 christos return n;
529 1.1 christos }
530 1.1 christos /* If the next item is last of tree, and we have to loop around,
531 1.1 christos * the search performs the lookup for the next item we need.
532 1.1 christos * If the next item exists, but also is not connected, the search
533 1.1 christos * finds the correct connected ixfr in the sorted tree. */
534 1.1 christos /* try searching for the correct ixfr data item */
535 1.1 christos n = (struct ixfr_data*)rbtree_search(ixfr->data, &cur->newserial);
536 1.1 christos if(!n || n == (struct ixfr_data*)RBTREE_NULL)
537 1.1 christos return NULL;
538 1.1 christos return n;
539 1.1 christos }
540 1.1 christos
541 1.1 christos /* iterator over ixfr data. fetch the previous item. If loop or nothing NULL.*/
542 1.1 christos static struct ixfr_data* ixfr_data_prev(struct zone_ixfr* ixfr,
543 1.1 christos struct ixfr_data* cur, size_t* prevcount)
544 1.1 christos {
545 1.1 christos struct ixfr_data* prev;
546 1.1 christos if(!cur || cur == (struct ixfr_data*)RBTREE_NULL)
547 1.1 christos return NULL;
548 1.1 christos if(cur->oldserial == ixfr->oldest_serial)
549 1.1 christos return NULL; /* this was the first element */
550 1.1 christos prev = (struct ixfr_data*)rbtree_previous(&cur->node);
551 1.1 christos if(!prev || prev == (struct ixfr_data*)RBTREE_NULL) {
552 1.1 christos /* We hit the first element in the tree, go again
553 1.1 christos * at the last one. Wrap around. */
554 1.1 christos prev = (struct ixfr_data*)rbtree_last(ixfr->data);
555 1.1 christos }
556 1.1 christos while(prev && prev != (struct ixfr_data*)RBTREE_NULL) {
557 1.1 christos if(prev->newserial == cur->oldserial) {
558 1.1 christos /* This is the correct matching previous ixfr data */
559 1.1 christos /* Increase the prevcounter every time the routine
560 1.1 christos * returns an item, and if that becomes too large, we
561 1.1 christos * are in a loop. in that case, stop. */
562 1.1 christos if(prevcount) {
563 1.1 christos (*prevcount)++;
564 1.1 christos if(*prevcount > ixfr->data->count + 12) {
565 1.1 christos /* Larger than the max number of items
566 1.1 christos * plus a small margin. The longest
567 1.1 christos * chain is all the ixfr elements in
568 1.1 christos * the tree. It loops. */
569 1.1 christos return NULL;
570 1.1 christos }
571 1.1 christos }
572 1.1 christos return prev;
573 1.1 christos }
574 1.1 christos prev = (struct ixfr_data*)rbtree_previous(&prev->node);
575 1.1 christos if(!prev || prev == (struct ixfr_data*)RBTREE_NULL) {
576 1.1 christos /* We hit the first element in the tree, go again
577 1.1 christos * at the last one. Wrap around. */
578 1.1 christos prev = (struct ixfr_data*)rbtree_last(ixfr->data);
579 1.1 christos }
580 1.1 christos }
581 1.1 christos /* no elements in list */
582 1.1 christos return NULL;
583 1.1 christos }
584 1.1 christos
585 1.1 christos /* connect IXFRs, return true if connected, false if not. Return last serial */
586 1.1 christos static int connect_ixfrs(struct zone_ixfr* ixfr, struct ixfr_data* data,
587 1.1 christos uint32_t* end_serial)
588 1.1 christos {
589 1.1 christos struct ixfr_data* p = data;
590 1.1 christos while(p != NULL) {
591 1.1 christos struct ixfr_data* next = ixfr_data_next(ixfr, p);
592 1.1 christos if(next) {
593 1.1 christos if(p->newserial != next->oldserial) {
594 1.1 christos /* These ixfrs are not connected,
595 1.1 christos * during IXFR processing that could already
596 1.1 christos * have been deleted, but we check here
597 1.1 christos * in any case */
598 1.1 christos return 0;
599 1.1 christos }
600 1.1 christos } else {
601 1.1 christos /* the chain of IXFRs ends in this serial number */
602 1.1 christos *end_serial = p->newserial;
603 1.1 christos }
604 1.1 christos p = next;
605 1.1 christos }
606 1.1 christos return 1;
607 1.1 christos }
608 1.1 christos
609 1.1 christos /* Count length of next record in data */
610 1.1 christos static size_t count_rr_length(const uint8_t* data, size_t data_len,
611 1.1 christos size_t current)
612 1.1 christos {
613 1.1 christos uint8_t label_size;
614 1.1 christos uint16_t rdlen;
615 1.1 christos size_t i = current;
616 1.1 christos if(current >= data_len)
617 1.1 christos return 0;
618 1.1 christos /* pass the owner dname */
619 1.1 christos while(1) {
620 1.1 christos if(i+1 > data_len)
621 1.1 christos return 0;
622 1.1 christos label_size = data[i++];
623 1.1 christos if(label_size == 0) {
624 1.1 christos break;
625 1.1 christos } else if((label_size &0xc0) != 0) {
626 1.1 christos return 0; /* uncompressed dnames in IXFR store */
627 1.1 christos } else if(i+label_size > data_len) {
628 1.1 christos return 0;
629 1.1 christos } else {
630 1.1 christos i += label_size;
631 1.1 christos }
632 1.1 christos }
633 1.1 christos /* after dname, we pass type, class, ttl, rdatalen */
634 1.1 christos if(i+10 > data_len)
635 1.1 christos return 0;
636 1.1 christos i += 8;
637 1.1 christos rdlen = read_uint16(data+i);
638 1.1 christos i += 2;
639 1.1 christos /* pass over the rdata */
640 1.1 christos if(i+((size_t)rdlen) > data_len)
641 1.1 christos return 0;
642 1.1 christos i += ((size_t)rdlen);
643 1.1 christos return i-current;
644 1.1 christos }
645 1.1 christos
646 1.1 christos /* Copy RRs into packet until packet full, return number RRs added */
647 1.1 christos static uint16_t ixfr_copy_rrs_into_packet(struct query* query,
648 1.1 christos struct pktcompression* pcomp)
649 1.1 christos {
650 1.1 christos uint16_t total_added = 0;
651 1.1 christos
652 1.1 christos /* Copy RRs into the packet until the answer is full,
653 1.1 christos * when an RR does not fit, we return and add no more. */
654 1.1 christos
655 1.1 christos /* Add first SOA */
656 1.1 christos if(query->ixfr_count_newsoa < query->ixfr_end_data->newsoa_len) {
657 1.1 christos /* the new SOA is added from the end_data segment, it is
658 1.1 christos * the final SOA of the result of the IXFR */
659 1.1 christos if(ixfr_write_rr_pkt(query, query->packet, pcomp,
660 1.1 christos query->ixfr_end_data->newsoa,
661 1.1 christos query->ixfr_end_data->newsoa_len)) {
662 1.1 christos query->ixfr_count_newsoa = query->ixfr_end_data->newsoa_len;
663 1.1 christos total_added++;
664 1.1 christos query->ixfr_pos_of_newsoa = buffer_position(query->packet);
665 1.1 christos } else {
666 1.1 christos /* cannot add another RR, so return */
667 1.1 christos return total_added;
668 1.1 christos }
669 1.1 christos }
670 1.1 christos
671 1.1 christos /* Add second SOA */
672 1.1 christos if(query->ixfr_count_oldsoa < query->ixfr_data->oldsoa_len) {
673 1.1 christos if(ixfr_write_rr_pkt(query, query->packet, pcomp,
674 1.1 christos query->ixfr_data->oldsoa,
675 1.1 christos query->ixfr_data->oldsoa_len)) {
676 1.1 christos query->ixfr_count_oldsoa = query->ixfr_data->oldsoa_len;
677 1.1 christos total_added++;
678 1.1 christos } else {
679 1.1 christos /* cannot add another RR, so return */
680 1.1 christos return total_added;
681 1.1 christos }
682 1.1 christos }
683 1.1 christos
684 1.1 christos /* Add del data, with deleted RRs and a SOA */
685 1.1 christos while(query->ixfr_count_del < query->ixfr_data->del_len) {
686 1.1 christos size_t rrlen = count_rr_length(query->ixfr_data->del,
687 1.1 christos query->ixfr_data->del_len, query->ixfr_count_del);
688 1.1 christos if(rrlen && ixfr_write_rr_pkt(query, query->packet, pcomp,
689 1.1 christos query->ixfr_data->del + query->ixfr_count_del,
690 1.1 christos rrlen)) {
691 1.1 christos query->ixfr_count_del += rrlen;
692 1.1 christos total_added++;
693 1.1 christos } else {
694 1.1 christos /* the next record does not fit in the remaining
695 1.1 christos * space of the packet */
696 1.1 christos return total_added;
697 1.1 christos }
698 1.1 christos }
699 1.1 christos
700 1.1 christos /* Add add data, with added RRs and a SOA */
701 1.1 christos while(query->ixfr_count_add < query->ixfr_data->add_len) {
702 1.1 christos size_t rrlen = count_rr_length(query->ixfr_data->add,
703 1.1 christos query->ixfr_data->add_len, query->ixfr_count_add);
704 1.1 christos if(rrlen && ixfr_write_rr_pkt(query, query->packet, pcomp,
705 1.1 christos query->ixfr_data->add + query->ixfr_count_add,
706 1.1 christos rrlen)) {
707 1.1 christos query->ixfr_count_add += rrlen;
708 1.1 christos total_added++;
709 1.1 christos } else {
710 1.1 christos /* the next record does not fit in the remaining
711 1.1 christos * space of the packet */
712 1.1 christos return total_added;
713 1.1 christos }
714 1.1 christos }
715 1.1 christos return total_added;
716 1.1 christos }
717 1.1 christos
718 1.1 christos query_state_type query_ixfr(struct nsd *nsd, struct query *query)
719 1.1 christos {
720 1.1 christos uint16_t total_added = 0;
721 1.1 christos struct pktcompression pcomp;
722 1.1 christos
723 1.1 christos if (query->ixfr_is_done)
724 1.1 christos return QUERY_PROCESSED;
725 1.1 christos
726 1.1 christos pktcompression_init(&pcomp);
727 1.1 christos if (query->maxlen > IXFR_MAX_MESSAGE_LEN)
728 1.1 christos query->maxlen = IXFR_MAX_MESSAGE_LEN;
729 1.1 christos
730 1.1 christos assert(!query_overflow(query));
731 1.1 christos /* only keep running values for most packets */
732 1.1 christos query->tsig_prepare_it = 0;
733 1.1 christos query->tsig_update_it = 1;
734 1.1 christos if(query->tsig_sign_it) {
735 1.1 christos /* prepare for next updates */
736 1.1 christos query->tsig_prepare_it = 1;
737 1.1 christos query->tsig_sign_it = 0;
738 1.1 christos }
739 1.1 christos
740 1.1 christos if (query->ixfr_data == NULL) {
741 1.1 christos /* This is the first packet, process the query further */
742 1.1 christos uint32_t qserial = 0, current_serial = 0, end_serial = 0;
743 1.1 christos struct zone* zone;
744 1.1 christos struct ixfr_data* ixfr_data;
745 1.1 christos size_t oldpos;
746 1.1 christos
747 1.1 christos STATUP(nsd, rixfr);
748 1.1 christos /* parse the serial number from the IXFR request */
749 1.1 christos oldpos = QHEADERSZ;
750 1.1 christos if(!parse_qserial(query->packet, &qserial, &oldpos)) {
751 1.1 christos NSCOUNT_SET(query->packet, 0);
752 1.1 christos ARCOUNT_SET(query->packet, 0);
753 1.1 christos buffer_set_position(query->packet, oldpos);
754 1.1 christos RCODE_SET(query->packet, RCODE_FORMAT);
755 1.1 christos return QUERY_PROCESSED;
756 1.1 christos }
757 1.1 christos NSCOUNT_SET(query->packet, 0);
758 1.1 christos ARCOUNT_SET(query->packet, 0);
759 1.1 christos buffer_set_position(query->packet, oldpos);
760 1.1 christos DEBUG(DEBUG_XFRD,1, (LOG_INFO, "ixfr query routine, %s IXFR=%u",
761 1.1 christos dname_to_string(query->qname, NULL), (unsigned)qserial));
762 1.1 christos
763 1.1 christos /* do we have an IXFR with this serial number? If not, serve AXFR */
764 1.1 christos zone = namedb_find_zone(nsd->db, query->qname);
765 1.1 christos if(!zone) {
766 1.1 christos /* no zone is present */
767 1.1 christos RCODE_SET(query->packet, RCODE_NOTAUTH);
768 1.1 christos return QUERY_PROCESSED;
769 1.1 christos }
770 1.1 christos ZTATUP(nsd, zone, rixfr);
771 1.1 christos
772 1.1 christos /* if the query is for same or newer serial than our current
773 1.1 christos * serial, then serve a single SOA with our current serial */
774 1.1 christos current_serial = zone_get_current_serial(zone);
775 1.1 christos if(compare_serial(qserial, current_serial) >= 0) {
776 1.1 christos if(!zone->soa_rrset || zone->soa_rrset->rr_count != 1){
777 1.1 christos RCODE_SET(query->packet, RCODE_SERVFAIL);
778 1.1 christos return QUERY_PROCESSED;
779 1.1 christos }
780 1.1 christos query_add_compression_domain(query, zone->apex,
781 1.1 christos QHEADERSZ);
782 1.1 christos if(packet_encode_rr(query, zone->apex,
783 1.1 christos &zone->soa_rrset->rrs[0],
784 1.1 christos zone->soa_rrset->rrs[0].ttl)) {
785 1.1 christos ANCOUNT_SET(query->packet, 1);
786 1.1 christos } else {
787 1.1 christos RCODE_SET(query->packet, RCODE_SERVFAIL);
788 1.1 christos }
789 1.1 christos AA_SET(query->packet);
790 1.1 christos query_clear_compression_tables(query);
791 1.1 christos if(query->tsig.status == TSIG_OK)
792 1.1 christos query->tsig_sign_it = 1;
793 1.1 christos return QUERY_PROCESSED;
794 1.1 christos }
795 1.1 christos
796 1.1 christos if(!zone->ixfr) {
797 1.1 christos /* we have no ixfr information for the zone, make an AXFR */
798 1.1 christos if(query->tsig_prepare_it)
799 1.1 christos query->tsig_sign_it = 1;
800 1.1 christos return query_axfr(nsd, query, 0);
801 1.1 christos }
802 1.1 christos ixfr_data = zone_ixfr_find_serial(zone->ixfr, qserial);
803 1.1 christos if(!ixfr_data) {
804 1.1 christos /* the specific version is not available, make an AXFR */
805 1.1 christos if(query->tsig_prepare_it)
806 1.1 christos query->tsig_sign_it = 1;
807 1.1 christos return query_axfr(nsd, query, 0);
808 1.1 christos }
809 1.1 christos /* see if the IXFRs connect to the next IXFR, and if it ends
810 1.1 christos * at the current served zone, if not, AXFR */
811 1.1 christos if(!connect_ixfrs(zone->ixfr, ixfr_data, &end_serial) ||
812 1.1 christos end_serial != current_serial) {
813 1.1 christos if(query->tsig_prepare_it)
814 1.1 christos query->tsig_sign_it = 1;
815 1.1 christos return query_axfr(nsd, query, 0);
816 1.1 christos }
817 1.1 christos
818 1.1 christos query->zone = zone;
819 1.1 christos query->ixfr_data = ixfr_data;
820 1.1 christos query->ixfr_is_done = 0;
821 1.1 christos /* set up to copy the last version's SOA as first SOA */
822 1.1 christos query->ixfr_end_data = ixfr_data_last(zone->ixfr);
823 1.1 christos query->ixfr_count_newsoa = 0;
824 1.1 christos query->ixfr_count_oldsoa = 0;
825 1.1 christos query->ixfr_count_del = 0;
826 1.1 christos query->ixfr_count_add = 0;
827 1.1 christos query->ixfr_pos_of_newsoa = 0;
828 1.1 christos /* the query name can be compressed to */
829 1.1 christos pktcompression_insert_with_labels(&pcomp,
830 1.1 christos buffer_at(query->packet, QHEADERSZ),
831 1.1 christos query->qname->name_size, QHEADERSZ);
832 1.1 christos if(query->tsig.status == TSIG_OK) {
833 1.1 christos query->tsig_sign_it = 1; /* sign first packet in stream */
834 1.1 christos }
835 1.1 christos } else {
836 1.1 christos /*
837 1.1 christos * Query name need not be repeated after the
838 1.1 christos * first response packet.
839 1.1 christos */
840 1.1 christos buffer_set_limit(query->packet, QHEADERSZ);
841 1.1 christos QDCOUNT_SET(query->packet, 0);
842 1.1 christos query_prepare_response(query);
843 1.1 christos }
844 1.1 christos
845 1.1 christos total_added = ixfr_copy_rrs_into_packet(query, &pcomp);
846 1.1 christos
847 1.1 christos while(query->ixfr_count_add >= query->ixfr_data->add_len) {
848 1.1 christos struct ixfr_data* next = ixfr_data_next(query->zone->ixfr,
849 1.1 christos query->ixfr_data);
850 1.1 christos /* finished the ixfr_data */
851 1.1 christos if(next) {
852 1.1 christos /* move to the next IXFR */
853 1.1 christos query->ixfr_data = next;
854 1.1 christos /* we need to skip the SOA records, set len to done*/
855 1.1 christos /* the newsoa count is already done, at end_data len */
856 1.1 christos query->ixfr_count_oldsoa = next->oldsoa_len;
857 1.1 christos /* and then set up to copy the del and add sections */
858 1.1 christos query->ixfr_count_del = 0;
859 1.1 christos query->ixfr_count_add = 0;
860 1.1 christos total_added += ixfr_copy_rrs_into_packet(query, &pcomp);
861 1.1 christos } else {
862 1.1 christos /* we finished the IXFR */
863 1.1 christos /* sign the last packet */
864 1.1 christos query->tsig_sign_it = 1;
865 1.1 christos query->ixfr_is_done = 1;
866 1.1 christos break;
867 1.1 christos }
868 1.1 christos }
869 1.1 christos
870 1.1 christos /* return the answer */
871 1.1 christos AA_SET(query->packet);
872 1.1 christos ANCOUNT_SET(query->packet, total_added);
873 1.1 christos NSCOUNT_SET(query->packet, 0);
874 1.1 christos ARCOUNT_SET(query->packet, 0);
875 1.1 christos
876 1.1 christos if(!query->tcp && !query->ixfr_is_done) {
877 1.1 christos TC_SET(query->packet);
878 1.1 christos if(query->ixfr_pos_of_newsoa) {
879 1.1 christos /* if we recorded the newsoa in the result, snip off
880 1.1 christos * the rest of the response, the RFC1995 response for
881 1.1 christos * when it does not fit is only the latest SOA */
882 1.1 christos buffer_set_position(query->packet, query->ixfr_pos_of_newsoa);
883 1.1 christos ANCOUNT_SET(query->packet, 1);
884 1.1 christos }
885 1.1 christos query->ixfr_is_done = 1;
886 1.1 christos }
887 1.1 christos
888 1.1 christos /* check if it needs tsig signatures */
889 1.1 christos if(query->tsig.status == TSIG_OK) {
890 1.1 christos #if IXFR_TSIG_SIGN_EVERY_NTH > 0
891 1.1 christos if(query->tsig.updates_since_last_prepare >= IXFR_TSIG_SIGN_EVERY_NTH) {
892 1.1 christos #endif
893 1.1 christos query->tsig_sign_it = 1;
894 1.1 christos #if IXFR_TSIG_SIGN_EVERY_NTH > 0
895 1.1 christos }
896 1.1 christos #endif
897 1.1 christos }
898 1.1 christos pktcompression_freeup(&pcomp);
899 1.1 christos return QUERY_IN_IXFR;
900 1.1 christos }
901 1.1 christos
902 1.1 christos /* free ixfr_data structure */
903 1.1 christos static void ixfr_data_free(struct ixfr_data* data)
904 1.1 christos {
905 1.1 christos if(!data)
906 1.1 christos return;
907 1.1 christos free(data->newsoa);
908 1.1 christos free(data->oldsoa);
909 1.1 christos free(data->del);
910 1.1 christos free(data->add);
911 1.1 christos free(data->log_str);
912 1.1 christos free(data);
913 1.1 christos }
914 1.1 christos
915 1.1 christos size_t ixfr_data_size(struct ixfr_data* data)
916 1.1 christos {
917 1.1 christos return sizeof(struct ixfr_data) + data->newsoa_len + data->oldsoa_len
918 1.1 christos + data->del_len + data->add_len;
919 1.1 christos }
920 1.1 christos
921 1.1 christos struct ixfr_store* ixfr_store_start(struct zone* zone,
922 1.1 christos struct ixfr_store* ixfr_store_mem, uint32_t old_serial,
923 1.1 christos uint32_t new_serial)
924 1.1 christos {
925 1.1 christos struct ixfr_store* ixfr_store = ixfr_store_mem;
926 1.1 christos memset(ixfr_store, 0, sizeof(*ixfr_store));
927 1.1 christos ixfr_store->zone = zone;
928 1.1 christos ixfr_store->data = xalloc_zero(sizeof(*ixfr_store->data));
929 1.1 christos ixfr_store->data->oldserial = old_serial;
930 1.1 christos ixfr_store->data->newserial = new_serial;
931 1.1 christos return ixfr_store;
932 1.1 christos }
933 1.1 christos
934 1.1 christos void ixfr_store_cancel(struct ixfr_store* ixfr_store)
935 1.1 christos {
936 1.1 christos ixfr_store->cancelled = 1;
937 1.1 christos ixfr_data_free(ixfr_store->data);
938 1.1 christos ixfr_store->data = NULL;
939 1.1 christos }
940 1.1 christos
941 1.1 christos void ixfr_store_free(struct ixfr_store* ixfr_store)
942 1.1 christos {
943 1.1 christos if(!ixfr_store)
944 1.1 christos return;
945 1.1 christos ixfr_data_free(ixfr_store->data);
946 1.1 christos }
947 1.1 christos
948 1.1 christos /* make space in record data for the new size, grows the allocation */
949 1.1 christos static void ixfr_rrs_make_space(uint8_t** rrs, size_t* len, size_t* capacity,
950 1.1 christos size_t added)
951 1.1 christos {
952 1.1 christos size_t newsize = 0;
953 1.1 christos if(*rrs == NULL) {
954 1.1 christos newsize = IXFR_STORE_INITIAL_SIZE;
955 1.1 christos } else {
956 1.1 christos if(*len + added <= *capacity)
957 1.1 christos return; /* already enough space */
958 1.1 christos newsize = (*capacity)*2;
959 1.1 christos }
960 1.1 christos if(*len + added > newsize)
961 1.1 christos newsize = *len + added;
962 1.1 christos if(*rrs == NULL) {
963 1.1 christos *rrs = xalloc(newsize);
964 1.1 christos } else {
965 1.1 christos *rrs = xrealloc(*rrs, newsize);
966 1.1 christos }
967 1.1 christos *capacity = newsize;
968 1.1 christos }
969 1.1 christos
970 1.1 christos /* put new SOA record after delrrs and addrrs */
971 1.1 christos static void ixfr_put_newsoa(struct ixfr_store* ixfr_store, uint8_t** rrs,
972 1.1 christos size_t* len, size_t* capacity)
973 1.1 christos {
974 1.1 christos uint8_t* soa;
975 1.1 christos size_t soa_len;
976 1.1 christos if(!ixfr_store->data)
977 1.1 christos return; /* data should be nonNULL, we are not cancelled */
978 1.1 christos soa = ixfr_store->data->newsoa;
979 1.1 christos soa_len= ixfr_store->data->newsoa_len;
980 1.1 christos ixfr_rrs_make_space(rrs, len, capacity, soa_len);
981 1.1 christos if(!*rrs || *len + soa_len > *capacity) {
982 1.1 christos log_msg(LOG_ERR, "ixfr_store addrr: cannot allocate space");
983 1.1 christos ixfr_store_cancel(ixfr_store);
984 1.1 christos return;
985 1.1 christos }
986 1.1 christos memmove(*rrs + *len, soa, soa_len);
987 1.1 christos *len += soa_len;
988 1.1 christos }
989 1.1 christos
990 1.1 christos /* trim unused storage from the rrs data */
991 1.1 christos static void ixfr_trim_capacity(uint8_t** rrs, size_t* len, size_t* capacity)
992 1.1 christos {
993 1.1 christos if(*rrs == NULL)
994 1.1 christos return;
995 1.1 christos if(*capacity == *len)
996 1.1 christos return;
997 1.1 christos *rrs = xrealloc(*rrs, *len);
998 1.1 christos *capacity = *len;
999 1.1 christos }
1000 1.1 christos
1001 1.1 christos void ixfr_store_finish_data(struct ixfr_store* ixfr_store)
1002 1.1 christos {
1003 1.1 christos if(ixfr_store->data_trimmed)
1004 1.1 christos return;
1005 1.1 christos ixfr_store->data_trimmed = 1;
1006 1.1 christos
1007 1.1 christos /* put new serial SOA record after delrrs and addrrs */
1008 1.1 christos ixfr_put_newsoa(ixfr_store, &ixfr_store->data->del,
1009 1.1 christos &ixfr_store->data->del_len, &ixfr_store->del_capacity);
1010 1.1 christos ixfr_put_newsoa(ixfr_store, &ixfr_store->data->add,
1011 1.1 christos &ixfr_store->data->add_len, &ixfr_store->add_capacity);
1012 1.1 christos
1013 1.1 christos /* trim the data in the store, the overhead from capacity is
1014 1.1 christos * removed */
1015 1.1 christos if(!ixfr_store->data)
1016 1.1 christos return; /* data should be nonNULL, we are not cancelled */
1017 1.1 christos ixfr_trim_capacity(&ixfr_store->data->del,
1018 1.1 christos &ixfr_store->data->del_len, &ixfr_store->del_capacity);
1019 1.1 christos ixfr_trim_capacity(&ixfr_store->data->add,
1020 1.1 christos &ixfr_store->data->add_len, &ixfr_store->add_capacity);
1021 1.1 christos }
1022 1.1 christos
1023 1.1 christos void ixfr_store_finish(struct ixfr_store* ixfr_store, struct nsd* nsd,
1024 1.1 christos char* log_buf)
1025 1.1 christos {
1026 1.1 christos if(ixfr_store->cancelled) {
1027 1.1 christos ixfr_store_free(ixfr_store);
1028 1.1 christos return;
1029 1.1 christos }
1030 1.1 christos
1031 1.1 christos ixfr_store_finish_data(ixfr_store);
1032 1.1 christos
1033 1.1 christos if(ixfr_store->cancelled) {
1034 1.1 christos ixfr_store_free(ixfr_store);
1035 1.1 christos return;
1036 1.1 christos }
1037 1.1 christos
1038 1.1 christos if(log_buf && !ixfr_store->data->log_str)
1039 1.1 christos ixfr_store->data->log_str = strdup(log_buf);
1040 1.1 christos
1041 1.1 christos /* store the data in the zone */
1042 1.1 christos if(!ixfr_store->zone->ixfr)
1043 1.1 christos ixfr_store->zone->ixfr = zone_ixfr_create(nsd);
1044 1.1 christos zone_ixfr_make_space(ixfr_store->zone->ixfr, ixfr_store->zone,
1045 1.1 christos ixfr_store->data, ixfr_store);
1046 1.1 christos if(ixfr_store->cancelled) {
1047 1.1 christos ixfr_store_free(ixfr_store);
1048 1.1 christos return;
1049 1.1 christos }
1050 1.1 christos zone_ixfr_add(ixfr_store->zone->ixfr, ixfr_store->data, 1);
1051 1.1 christos ixfr_store->data = NULL;
1052 1.1 christos
1053 1.1 christos /* free structure */
1054 1.1 christos ixfr_store_free(ixfr_store);
1055 1.1 christos }
1056 1.1 christos
1057 1.1 christos /* read SOA rdata section for SOA storage */
1058 1.1 christos static int read_soa_rdata(struct buffer* packet, uint8_t* primns,
1059 1.1 christos int* primns_len, uint8_t* email, int* email_len,
1060 1.1 christos uint32_t* serial, uint32_t* refresh, uint32_t* retry,
1061 1.1 christos uint32_t* expire, uint32_t* minimum, size_t* sz)
1062 1.1 christos {
1063 1.1 christos if(!(*primns_len = dname_make_wire_from_packet(primns, packet, 1))) {
1064 1.1 christos log_msg(LOG_ERR, "ixfr_store: cannot parse soa nsname in packet");
1065 1.1 christos return 0;
1066 1.1 christos }
1067 1.1 christos *sz += *primns_len;
1068 1.1 christos if(!(*email_len = dname_make_wire_from_packet(email, packet, 1))) {
1069 1.1 christos log_msg(LOG_ERR, "ixfr_store: cannot parse soa maintname in packet");
1070 1.1 christos return 0;
1071 1.1 christos }
1072 1.1 christos *sz += *email_len;
1073 1.1 christos *serial = buffer_read_u32(packet);
1074 1.1 christos *sz += 4;
1075 1.1 christos *refresh = buffer_read_u32(packet);
1076 1.1 christos *sz += 4;
1077 1.1 christos *retry = buffer_read_u32(packet);
1078 1.1 christos *sz += 4;
1079 1.1 christos *expire = buffer_read_u32(packet);
1080 1.1 christos *sz += 4;
1081 1.1 christos *minimum = buffer_read_u32(packet);
1082 1.1 christos *sz += 4;
1083 1.1 christos return 1;
1084 1.1 christos }
1085 1.1 christos
1086 1.1 christos /* store SOA record data in memory buffer */
1087 1.1 christos static void store_soa(uint8_t* soa, struct zone* zone, uint32_t ttl,
1088 1.1 christos uint16_t rdlen_uncompressed, uint8_t* primns, int primns_len,
1089 1.1 christos uint8_t* email, int email_len, uint32_t serial, uint32_t refresh,
1090 1.1 christos uint32_t retry, uint32_t expire, uint32_t minimum)
1091 1.1 christos {
1092 1.1 christos uint8_t* sp = soa;
1093 1.1 christos memmove(sp, dname_name(domain_dname(zone->apex)),
1094 1.1 christos domain_dname(zone->apex)->name_size);
1095 1.1 christos sp += domain_dname(zone->apex)->name_size;
1096 1.1 christos write_uint16(sp, TYPE_SOA);
1097 1.1 christos sp += 2;
1098 1.1 christos write_uint16(sp, CLASS_IN);
1099 1.1 christos sp += 2;
1100 1.1 christos write_uint32(sp, ttl);
1101 1.1 christos sp += 4;
1102 1.1 christos write_uint16(sp, rdlen_uncompressed);
1103 1.1 christos sp += 2;
1104 1.1 christos memmove(sp, primns, primns_len);
1105 1.1 christos sp += primns_len;
1106 1.1 christos memmove(sp, email, email_len);
1107 1.1 christos sp += email_len;
1108 1.1 christos write_uint32(sp, serial);
1109 1.1 christos sp += 4;
1110 1.1 christos write_uint32(sp, refresh);
1111 1.1 christos sp += 4;
1112 1.1 christos write_uint32(sp, retry);
1113 1.1 christos sp += 4;
1114 1.1 christos write_uint32(sp, expire);
1115 1.1 christos sp += 4;
1116 1.1 christos write_uint32(sp, minimum);
1117 1.1 christos }
1118 1.1 christos
1119 1.1 christos void ixfr_store_add_newsoa(struct ixfr_store* ixfr_store,
1120 1.1 christos struct buffer* packet, size_t ttlpos)
1121 1.1 christos {
1122 1.1 christos size_t oldpos, sz = 0;
1123 1.1 christos uint32_t ttl, serial, refresh, retry, expire, minimum;
1124 1.1 christos uint16_t rdlen_uncompressed, rdlen_wire;
1125 1.1 christos int primns_len = 0, email_len = 0;
1126 1.1 christos uint8_t primns[MAXDOMAINLEN + 1], email[MAXDOMAINLEN + 1];
1127 1.1 christos
1128 1.1 christos if(ixfr_store->cancelled)
1129 1.1 christos return;
1130 1.1 christos if(ixfr_store->data->newsoa) {
1131 1.1 christos free(ixfr_store->data->newsoa);
1132 1.1 christos ixfr_store->data->newsoa = NULL;
1133 1.1 christos ixfr_store->data->newsoa_len = 0;
1134 1.1 christos }
1135 1.1 christos oldpos = buffer_position(packet);
1136 1.1 christos buffer_set_position(packet, ttlpos);
1137 1.1 christos
1138 1.1 christos /* calculate the length */
1139 1.1 christos sz = domain_dname(ixfr_store->zone->apex)->name_size;
1140 1.1 christos sz += 2 /* type */ + 2 /* class */;
1141 1.1 christos /* read ttl */
1142 1.1 christos if(!buffer_available(packet, 4/*ttl*/+2/*rdlen*/)) {
1143 1.1 christos /* not possible already parsed, but fail nicely anyway */
1144 1.1 christos log_msg(LOG_ERR, "ixfr_store: not enough space in packet");
1145 1.1 christos ixfr_store_cancel(ixfr_store);
1146 1.1 christos buffer_set_position(packet, oldpos);
1147 1.1 christos return;
1148 1.1 christos }
1149 1.1 christos ttl = buffer_read_u32(packet);
1150 1.1 christos sz += 4;
1151 1.1 christos rdlen_wire = buffer_read_u16(packet);
1152 1.1 christos sz += 2;
1153 1.1 christos if(!buffer_available(packet, rdlen_wire)) {
1154 1.1 christos /* not possible already parsed, but fail nicely anyway */
1155 1.1 christos log_msg(LOG_ERR, "ixfr_store: not enough rdata space in packet");
1156 1.1 christos ixfr_store_cancel(ixfr_store);
1157 1.1 christos buffer_set_position(packet, oldpos);
1158 1.1 christos return;
1159 1.1 christos }
1160 1.1 christos if(!read_soa_rdata(packet, primns, &primns_len, email, &email_len,
1161 1.1 christos &serial, &refresh, &retry, &expire, &minimum, &sz)) {
1162 1.1 christos log_msg(LOG_ERR, "ixfr_store newsoa: cannot parse packet");
1163 1.1 christos ixfr_store_cancel(ixfr_store);
1164 1.1 christos buffer_set_position(packet, oldpos);
1165 1.1 christos return;
1166 1.1 christos }
1167 1.1 christos rdlen_uncompressed = primns_len + email_len + 4 + 4 + 4 + 4 + 4;
1168 1.1 christos
1169 1.1 christos /* store the soa record */
1170 1.1 christos ixfr_store->data->newsoa = xalloc(sz);
1171 1.1 christos ixfr_store->data->newsoa_len = sz;
1172 1.1 christos store_soa(ixfr_store->data->newsoa, ixfr_store->zone, ttl,
1173 1.1 christos rdlen_uncompressed, primns, primns_len, email, email_len,
1174 1.1 christos serial, refresh, retry, expire, minimum);
1175 1.1 christos
1176 1.1 christos buffer_set_position(packet, oldpos);
1177 1.1 christos }
1178 1.1 christos
1179 1.1 christos void ixfr_store_add_oldsoa(struct ixfr_store* ixfr_store, uint32_t ttl,
1180 1.1 christos struct buffer* packet, size_t rrlen)
1181 1.1 christos {
1182 1.1 christos size_t oldpos, sz = 0;
1183 1.1 christos uint32_t serial, refresh, retry, expire, minimum;
1184 1.1 christos uint16_t rdlen_uncompressed;
1185 1.1 christos int primns_len = 0, email_len = 0;
1186 1.1 christos uint8_t primns[MAXDOMAINLEN + 1], email[MAXDOMAINLEN + 1];
1187 1.1 christos
1188 1.1 christos if(ixfr_store->cancelled)
1189 1.1 christos return;
1190 1.1 christos if(ixfr_store->data->oldsoa) {
1191 1.1 christos free(ixfr_store->data->oldsoa);
1192 1.1 christos ixfr_store->data->oldsoa = NULL;
1193 1.1 christos ixfr_store->data->oldsoa_len = 0;
1194 1.1 christos }
1195 1.1 christos /* we have the old SOA and thus we are sure it is an IXFR, make space*/
1196 1.1 christos zone_ixfr_make_space(ixfr_store->zone->ixfr, ixfr_store->zone,
1197 1.1 christos ixfr_store->data, ixfr_store);
1198 1.1 christos if(ixfr_store->cancelled)
1199 1.1 christos return;
1200 1.1 christos oldpos = buffer_position(packet);
1201 1.1 christos
1202 1.1 christos /* calculate the length */
1203 1.1 christos sz = domain_dname(ixfr_store->zone->apex)->name_size;
1204 1.1 christos sz += 2 /*type*/ + 2 /*class*/ + 4 /*ttl*/ + 2 /*rdlen*/;
1205 1.1 christos if(!buffer_available(packet, rrlen)) {
1206 1.1 christos /* not possible already parsed, but fail nicely anyway */
1207 1.1 christos log_msg(LOG_ERR, "ixfr_store oldsoa: not enough rdata space in packet");
1208 1.1 christos ixfr_store_cancel(ixfr_store);
1209 1.1 christos buffer_set_position(packet, oldpos);
1210 1.1 christos return;
1211 1.1 christos }
1212 1.1 christos if(!read_soa_rdata(packet, primns, &primns_len, email, &email_len,
1213 1.1 christos &serial, &refresh, &retry, &expire, &minimum, &sz)) {
1214 1.1 christos log_msg(LOG_ERR, "ixfr_store oldsoa: cannot parse packet");
1215 1.1 christos ixfr_store_cancel(ixfr_store);
1216 1.1 christos buffer_set_position(packet, oldpos);
1217 1.1 christos return;
1218 1.1 christos }
1219 1.1 christos rdlen_uncompressed = primns_len + email_len + 4 + 4 + 4 + 4 + 4;
1220 1.1 christos
1221 1.1 christos /* store the soa record */
1222 1.1 christos ixfr_store->data->oldsoa = xalloc(sz);
1223 1.1 christos ixfr_store->data->oldsoa_len = sz;
1224 1.1 christos store_soa(ixfr_store->data->oldsoa, ixfr_store->zone, ttl,
1225 1.1 christos rdlen_uncompressed, primns, primns_len, email, email_len,
1226 1.1 christos serial, refresh, retry, expire, minimum);
1227 1.1 christos
1228 1.1 christos buffer_set_position(packet, oldpos);
1229 1.1 christos }
1230 1.1 christos
1231 1.1 christos /* store RR in data segment */
1232 1.1 christos static int ixfr_putrr(const struct dname* dname, uint16_t type, uint16_t klass,
1233 1.1 christos uint32_t ttl, rdata_atom_type* rdatas, ssize_t rdata_num,
1234 1.1 christos uint8_t** rrs, size_t* rrs_len, size_t* rrs_capacity)
1235 1.1 christos {
1236 1.1 christos size_t rdlen_uncompressed, sz;
1237 1.1 christos uint8_t* sp;
1238 1.1 christos int i;
1239 1.1 christos
1240 1.1 christos /* find rdatalen */
1241 1.1 christos rdlen_uncompressed = 0;
1242 1.1 christos for(i=0; i<rdata_num; i++) {
1243 1.1 christos if(rdata_atom_is_domain(type, i)) {
1244 1.1 christos rdlen_uncompressed += domain_dname(rdatas[i].domain)
1245 1.1 christos ->name_size;
1246 1.1 christos } else {
1247 1.1 christos rdlen_uncompressed += rdatas[i].data[0];
1248 1.1 christos }
1249 1.1 christos }
1250 1.1 christos sz = dname->name_size + 2 /*type*/ + 2 /*class*/ + 4 /*ttl*/ +
1251 1.1 christos 2 /*rdlen*/ + rdlen_uncompressed;
1252 1.1 christos
1253 1.1 christos /* store RR in IXFR data */
1254 1.1 christos ixfr_rrs_make_space(rrs, rrs_len, rrs_capacity, sz);
1255 1.1 christos if(!*rrs || *rrs_len + sz > *rrs_capacity) {
1256 1.1 christos return 0;
1257 1.1 christos }
1258 1.1 christos /* copy data into add */
1259 1.1 christos sp = *rrs + *rrs_len;
1260 1.1 christos *rrs_len += sz;
1261 1.1 christos memmove(sp, dname_name(dname), dname->name_size);
1262 1.1 christos sp += dname->name_size;
1263 1.1 christos write_uint16(sp, type);
1264 1.1 christos sp += 2;
1265 1.1 christos write_uint16(sp, klass);
1266 1.1 christos sp += 2;
1267 1.1 christos write_uint32(sp, ttl);
1268 1.1 christos sp += 4;
1269 1.1 christos write_uint16(sp, rdlen_uncompressed);
1270 1.1 christos sp += 2;
1271 1.1 christos for(i=0; i<rdata_num; i++) {
1272 1.1 christos if(rdata_atom_is_domain(type, i)) {
1273 1.1 christos memmove(sp, dname_name(domain_dname(rdatas[i].domain)),
1274 1.1 christos domain_dname(rdatas[i].domain)->name_size);
1275 1.1 christos sp += domain_dname(rdatas[i].domain)->name_size;
1276 1.1 christos } else {
1277 1.1 christos memmove(sp, &rdatas[i].data[1], rdatas[i].data[0]);
1278 1.1 christos sp += rdatas[i].data[0];
1279 1.1 christos }
1280 1.1 christos }
1281 1.1 christos return 1;
1282 1.1 christos }
1283 1.1 christos
1284 1.1 christos void ixfr_store_putrr(struct ixfr_store* ixfr_store, const struct dname* dname,
1285 1.1 christos uint16_t type, uint16_t klass, uint32_t ttl, struct buffer* packet,
1286 1.1 christos uint16_t rrlen, struct region* temp_region, uint8_t** rrs,
1287 1.1 christos size_t* rrs_len, size_t* rrs_capacity)
1288 1.1 christos {
1289 1.1 christos domain_table_type *temptable;
1290 1.1 christos rdata_atom_type *rdatas;
1291 1.1 christos ssize_t rdata_num;
1292 1.1 christos size_t oldpos;
1293 1.1 christos
1294 1.1 christos if(ixfr_store->cancelled)
1295 1.1 christos return;
1296 1.1 christos
1297 1.1 christos /* The SOA data is stored with separate calls. And then appended
1298 1.1 christos * during the finish operation. We do not have to store it here
1299 1.1 christos * when called from difffile's IXFR processing with type SOA. */
1300 1.1 christos if(type == TYPE_SOA)
1301 1.1 christos return;
1302 1.1 christos /* make space for these RRs we have now; basically once we
1303 1.1 christos * grow beyond the current allowed amount an older IXFR is deleted. */
1304 1.1 christos zone_ixfr_make_space(ixfr_store->zone->ixfr, ixfr_store->zone,
1305 1.1 christos ixfr_store->data, ixfr_store);
1306 1.1 christos if(ixfr_store->cancelled)
1307 1.1 christos return;
1308 1.1 christos
1309 1.1 christos /* parse rdata */
1310 1.1 christos oldpos = buffer_position(packet);
1311 1.1 christos temptable = domain_table_create(temp_region);
1312 1.1 christos rdata_num = rdata_wireformat_to_rdata_atoms(temp_region, temptable,
1313 1.1 christos type, rrlen, packet, &rdatas);
1314 1.1 christos buffer_set_position(packet, oldpos);
1315 1.1 christos if(rdata_num == -1) {
1316 1.1 christos log_msg(LOG_ERR, "ixfr_store addrr: cannot parse packet");
1317 1.1 christos ixfr_store_cancel(ixfr_store);
1318 1.1 christos return;
1319 1.1 christos }
1320 1.1 christos
1321 1.1 christos if(!ixfr_putrr(dname, type, klass, ttl, rdatas, rdata_num,
1322 1.1 christos rrs, rrs_len, rrs_capacity)) {
1323 1.1 christos log_msg(LOG_ERR, "ixfr_store addrr: cannot allocate space");
1324 1.1 christos ixfr_store_cancel(ixfr_store);
1325 1.1 christos return;
1326 1.1 christos }
1327 1.1 christos }
1328 1.1 christos
1329 1.1 christos void ixfr_store_delrr(struct ixfr_store* ixfr_store, const struct dname* dname,
1330 1.1 christos uint16_t type, uint16_t klass, uint32_t ttl, struct buffer* packet,
1331 1.1 christos uint16_t rrlen, struct region* temp_region)
1332 1.1 christos {
1333 1.1 christos ixfr_store_putrr(ixfr_store, dname, type, klass, ttl, packet, rrlen,
1334 1.1 christos temp_region, &ixfr_store->data->del,
1335 1.1 christos &ixfr_store->data->del_len, &ixfr_store->del_capacity);
1336 1.1 christos }
1337 1.1 christos
1338 1.1 christos void ixfr_store_addrr(struct ixfr_store* ixfr_store, const struct dname* dname,
1339 1.1 christos uint16_t type, uint16_t klass, uint32_t ttl, struct buffer* packet,
1340 1.1 christos uint16_t rrlen, struct region* temp_region)
1341 1.1 christos {
1342 1.1 christos ixfr_store_putrr(ixfr_store, dname, type, klass, ttl, packet, rrlen,
1343 1.1 christos temp_region, &ixfr_store->data->add,
1344 1.1 christos &ixfr_store->data->add_len, &ixfr_store->add_capacity);
1345 1.1 christos }
1346 1.1 christos
1347 1.1 christos int ixfr_store_addrr_rdatas(struct ixfr_store* ixfr_store,
1348 1.1 christos const struct dname* dname, uint16_t type, uint16_t klass,
1349 1.1 christos uint32_t ttl, rdata_atom_type* rdatas, ssize_t rdata_num)
1350 1.1 christos {
1351 1.1 christos if(ixfr_store->cancelled)
1352 1.1 christos return 1;
1353 1.1 christos if(type == TYPE_SOA)
1354 1.1 christos return 1;
1355 1.1 christos return ixfr_putrr(dname, type, klass, ttl, rdatas, rdata_num,
1356 1.1 christos &ixfr_store->data->add, &ixfr_store->data->add_len,
1357 1.1 christos &ixfr_store->add_capacity);
1358 1.1 christos }
1359 1.1 christos
1360 1.1 christos int ixfr_store_add_newsoa_rdatas(struct ixfr_store* ixfr_store,
1361 1.1 christos const struct dname* dname, uint16_t type, uint16_t klass,
1362 1.1 christos uint32_t ttl, rdata_atom_type* rdatas, ssize_t rdata_num)
1363 1.1 christos {
1364 1.1 christos size_t capacity = 0;
1365 1.1 christos if(ixfr_store->cancelled)
1366 1.1 christos return 1;
1367 1.1 christos if(!ixfr_putrr(dname, type, klass, ttl, rdatas, rdata_num,
1368 1.1 christos &ixfr_store->data->newsoa, &ixfr_store->data->newsoa_len,
1369 1.1 christos &ixfr_store->add_capacity))
1370 1.1 christos return 0;
1371 1.1 christos ixfr_trim_capacity(&ixfr_store->data->newsoa,
1372 1.1 christos &ixfr_store->data->newsoa_len, &capacity);
1373 1.1 christos return 1;
1374 1.1 christos }
1375 1.1 christos
1376 1.1 christos /* store rr uncompressed */
1377 1.1 christos int ixfr_storerr_uncompressed(uint8_t* dname, size_t dname_len, uint16_t type,
1378 1.1 christos uint16_t klass, uint32_t ttl, uint8_t* rdata, size_t rdata_len,
1379 1.1 christos uint8_t** rrs, size_t* rrs_len, size_t* rrs_capacity)
1380 1.1 christos {
1381 1.1 christos size_t sz;
1382 1.1 christos uint8_t* sp;
1383 1.1 christos
1384 1.1 christos /* find rdatalen */
1385 1.1 christos sz = dname_len + 2 /*type*/ + 2 /*class*/ + 4 /*ttl*/ +
1386 1.1 christos 2 /*rdlen*/ + rdata_len;
1387 1.1 christos
1388 1.1 christos /* store RR in IXFR data */
1389 1.1 christos ixfr_rrs_make_space(rrs, rrs_len, rrs_capacity, sz);
1390 1.1 christos if(!*rrs || *rrs_len + sz > *rrs_capacity) {
1391 1.1 christos return 0;
1392 1.1 christos }
1393 1.1 christos /* copy data into add */
1394 1.1 christos sp = *rrs + *rrs_len;
1395 1.1 christos *rrs_len += sz;
1396 1.1 christos memmove(sp, dname, dname_len);
1397 1.1 christos sp += dname_len;
1398 1.1 christos write_uint16(sp, type);
1399 1.1 christos sp += 2;
1400 1.1 christos write_uint16(sp, klass);
1401 1.1 christos sp += 2;
1402 1.1 christos write_uint32(sp, ttl);
1403 1.1 christos sp += 4;
1404 1.1 christos write_uint16(sp, rdata_len);
1405 1.1 christos sp += 2;
1406 1.1 christos memmove(sp, rdata, rdata_len);
1407 1.1 christos return 1;
1408 1.1 christos }
1409 1.1 christos
1410 1.1 christos int ixfr_store_delrr_uncompressed(struct ixfr_store* ixfr_store,
1411 1.1 christos uint8_t* dname, size_t dname_len, uint16_t type, uint16_t klass,
1412 1.1 christos uint32_t ttl, uint8_t* rdata, size_t rdata_len)
1413 1.1 christos {
1414 1.1 christos if(ixfr_store->cancelled)
1415 1.1 christos return 1;
1416 1.1 christos if(type == TYPE_SOA)
1417 1.1 christos return 1;
1418 1.1 christos return ixfr_storerr_uncompressed(dname, dname_len, type, klass,
1419 1.1 christos ttl, rdata, rdata_len, &ixfr_store->data->del,
1420 1.1 christos &ixfr_store->data->del_len, &ixfr_store->del_capacity);
1421 1.1 christos }
1422 1.1 christos
1423 1.1 christos int ixfr_store_oldsoa_uncompressed(struct ixfr_store* ixfr_store,
1424 1.1 christos uint8_t* dname, size_t dname_len, uint16_t type, uint16_t klass,
1425 1.1 christos uint32_t ttl, uint8_t* rdata, size_t rdata_len)
1426 1.1 christos {
1427 1.1 christos size_t capacity = 0;
1428 1.1 christos if(ixfr_store->cancelled)
1429 1.1 christos return 1;
1430 1.1 christos if(!ixfr_storerr_uncompressed(dname, dname_len, type, klass,
1431 1.1 christos ttl, rdata, rdata_len, &ixfr_store->data->oldsoa,
1432 1.1 christos &ixfr_store->data->oldsoa_len, &capacity))
1433 1.1 christos return 0;
1434 1.1 christos ixfr_trim_capacity(&ixfr_store->data->oldsoa,
1435 1.1 christos &ixfr_store->data->oldsoa_len, &capacity);
1436 1.1 christos return 1;
1437 1.1 christos }
1438 1.1 christos
1439 1.1 christos int zone_is_ixfr_enabled(struct zone* zone)
1440 1.1 christos {
1441 1.1 christos return zone->opts->pattern->store_ixfr;
1442 1.1 christos }
1443 1.1 christos
1444 1.1 christos /* compare ixfr elements */
1445 1.1 christos static int ixfrcompare(const void* x, const void* y)
1446 1.1 christos {
1447 1.1 christos uint32_t* serial_x = (uint32_t*)x;
1448 1.1 christos uint32_t* serial_y = (uint32_t*)y;
1449 1.1 christos if(*serial_x < *serial_y)
1450 1.1 christos return -1;
1451 1.1 christos if(*serial_x > *serial_y)
1452 1.1 christos return 1;
1453 1.1 christos return 0;
1454 1.1 christos }
1455 1.1 christos
1456 1.1 christos struct zone_ixfr* zone_ixfr_create(struct nsd* nsd)
1457 1.1 christos {
1458 1.1 christos struct zone_ixfr* ixfr = xalloc_zero(sizeof(struct zone_ixfr));
1459 1.1 christos ixfr->data = rbtree_create(nsd->region, &ixfrcompare);
1460 1.1 christos return ixfr;
1461 1.1 christos }
1462 1.1 christos
1463 1.1 christos /* traverse tree postorder */
1464 1.1 christos static void ixfr_tree_del(struct rbnode* node)
1465 1.1 christos {
1466 1.1 christos if(node == NULL || node == RBTREE_NULL)
1467 1.1 christos return;
1468 1.1 christos ixfr_tree_del(node->left);
1469 1.1 christos ixfr_tree_del(node->right);
1470 1.1 christos ixfr_data_free((struct ixfr_data*)node);
1471 1.1 christos }
1472 1.1 christos
1473 1.1 christos /* clear the ixfr data elements */
1474 1.1 christos static void zone_ixfr_clear(struct zone_ixfr* ixfr)
1475 1.1 christos {
1476 1.1 christos if(!ixfr)
1477 1.1 christos return;
1478 1.1 christos if(ixfr->data) {
1479 1.1 christos ixfr_tree_del(ixfr->data->root);
1480 1.1 christos ixfr->data->root = RBTREE_NULL;
1481 1.1 christos ixfr->data->count = 0;
1482 1.1 christos }
1483 1.1 christos ixfr->total_size = 0;
1484 1.1 christos ixfr->oldest_serial = 0;
1485 1.1 christos ixfr->newest_serial = 0;
1486 1.1 christos }
1487 1.1 christos
1488 1.1 christos void zone_ixfr_free(struct zone_ixfr* ixfr)
1489 1.1 christos {
1490 1.1 christos if(!ixfr)
1491 1.1 christos return;
1492 1.1 christos if(ixfr->data) {
1493 1.1 christos ixfr_tree_del(ixfr->data->root);
1494 1.1 christos ixfr->data = NULL;
1495 1.1 christos }
1496 1.1 christos free(ixfr);
1497 1.1 christos }
1498 1.1 christos
1499 1.1 christos void ixfr_store_delixfrs(struct zone* zone)
1500 1.1 christos {
1501 1.1 christos if(!zone)
1502 1.1 christos return;
1503 1.1 christos zone_ixfr_clear(zone->ixfr);
1504 1.1 christos }
1505 1.1 christos
1506 1.1 christos /* remove the oldest data entry from the ixfr versions */
1507 1.1 christos static void zone_ixfr_remove_oldest(struct zone_ixfr* ixfr)
1508 1.1 christos {
1509 1.1 christos if(ixfr->data->count > 0) {
1510 1.1 christos struct ixfr_data* oldest = ixfr_data_first(ixfr);
1511 1.1 christos if(ixfr->oldest_serial == oldest->oldserial) {
1512 1.1 christos if(ixfr->data->count > 1) {
1513 1.1 christos struct ixfr_data* next = ixfr_data_next(ixfr, oldest);
1514 1.1 christos assert(next);
1515 1.1 christos if(next)
1516 1.1 christos ixfr->oldest_serial = next->oldserial;
1517 1.1 christos else ixfr->oldest_serial = oldest->newserial;
1518 1.1 christos } else {
1519 1.1 christos ixfr->oldest_serial = 0;
1520 1.1 christos }
1521 1.1 christos }
1522 1.1 christos if(ixfr->newest_serial == oldest->oldserial) {
1523 1.1 christos ixfr->newest_serial = 0;
1524 1.1 christos }
1525 1.1 christos zone_ixfr_remove(ixfr, oldest);
1526 1.1 christos }
1527 1.1 christos }
1528 1.1 christos
1529 1.1 christos void zone_ixfr_make_space(struct zone_ixfr* ixfr, struct zone* zone,
1530 1.1 christos struct ixfr_data* data, struct ixfr_store* ixfr_store)
1531 1.1 christos {
1532 1.1 christos size_t addsize;
1533 1.1 christos if(!ixfr || !data)
1534 1.1 christos return;
1535 1.1 christos if(zone->opts->pattern->ixfr_number == 0) {
1536 1.1 christos ixfr_store_cancel(ixfr_store);
1537 1.1 christos return;
1538 1.1 christos }
1539 1.1 christos
1540 1.1 christos /* Check the number of IXFRs allowed for this zone, if too many,
1541 1.1 christos * shorten the number to make space for another one */
1542 1.1 christos while(ixfr->data->count >= zone->opts->pattern->ixfr_number) {
1543 1.1 christos zone_ixfr_remove_oldest(ixfr);
1544 1.1 christos }
1545 1.1 christos
1546 1.1 christos if(zone->opts->pattern->ixfr_size == 0) {
1547 1.1 christos /* no size limits imposed */
1548 1.1 christos return;
1549 1.1 christos }
1550 1.1 christos
1551 1.1 christos /* Check the size of the current added data element 'data', and
1552 1.1 christos * see if that overflows the maximum storage size for IXFRs for
1553 1.1 christos * this zone, and if so, delete the oldest IXFR to make space */
1554 1.1 christos addsize = ixfr_data_size(data);
1555 1.1 christos while(ixfr->data->count > 0 && ixfr->total_size + addsize >
1556 1.1 christos zone->opts->pattern->ixfr_size) {
1557 1.1 christos zone_ixfr_remove_oldest(ixfr);
1558 1.1 christos }
1559 1.1 christos
1560 1.1 christos /* if deleting the oldest elements does not work, then this
1561 1.1 christos * IXFR is too big to store and we cancel it */
1562 1.1 christos if(ixfr->data->count == 0 && ixfr->total_size + addsize >
1563 1.1 christos zone->opts->pattern->ixfr_size) {
1564 1.1 christos ixfr_store_cancel(ixfr_store);
1565 1.1 christos return;
1566 1.1 christos }
1567 1.1 christos }
1568 1.1 christos
1569 1.1 christos void zone_ixfr_remove(struct zone_ixfr* ixfr, struct ixfr_data* data)
1570 1.1 christos {
1571 1.1 christos rbtree_delete(ixfr->data, data->node.key);
1572 1.1 christos ixfr->total_size -= ixfr_data_size(data);
1573 1.1 christos ixfr_data_free(data);
1574 1.1 christos }
1575 1.1 christos
1576 1.1 christos void zone_ixfr_add(struct zone_ixfr* ixfr, struct ixfr_data* data, int isnew)
1577 1.1 christos {
1578 1.1 christos memset(&data->node, 0, sizeof(data->node));
1579 1.1 christos if(ixfr->data->count == 0) {
1580 1.1 christos ixfr->oldest_serial = data->oldserial;
1581 1.1 christos ixfr->newest_serial = data->oldserial;
1582 1.1 christos } else if(isnew) {
1583 1.1 christos /* newest entry is last there is */
1584 1.1 christos ixfr->newest_serial = data->oldserial;
1585 1.1 christos } else {
1586 1.1 christos /* added older entry, before the others */
1587 1.1 christos ixfr->oldest_serial = data->oldserial;
1588 1.1 christos }
1589 1.1 christos data->node.key = &data->oldserial;
1590 1.1 christos rbtree_insert(ixfr->data, &data->node);
1591 1.1 christos ixfr->total_size += ixfr_data_size(data);
1592 1.1 christos }
1593 1.1 christos
1594 1.1 christos struct ixfr_data* zone_ixfr_find_serial(struct zone_ixfr* ixfr,
1595 1.1 christos uint32_t qserial)
1596 1.1 christos {
1597 1.1 christos struct ixfr_data* data;
1598 1.1 christos if(!ixfr)
1599 1.1 christos return NULL;
1600 1.1 christos if(!ixfr->data)
1601 1.1 christos return NULL;
1602 1.1 christos data = (struct ixfr_data*)rbtree_search(ixfr->data, &qserial);
1603 1.1 christos if(data) {
1604 1.1 christos assert(data->oldserial == qserial);
1605 1.1 christos return data;
1606 1.1 christos }
1607 1.1 christos /* not found */
1608 1.1 christos return NULL;
1609 1.1 christos }
1610 1.1 christos
1611 1.1 christos /* calculate the number of files we want */
1612 1.1 christos static int ixfr_target_number_files(struct zone* zone)
1613 1.1 christos {
1614 1.1 christos int dest_num_files;
1615 1.1 christos if(!zone->ixfr || !zone->ixfr->data)
1616 1.1 christos return 0;
1617 1.1 christos if(!zone_is_ixfr_enabled(zone))
1618 1.1 christos return 0;
1619 1.1 christos /* if we store ixfr, it is the configured number of files */
1620 1.1 christos dest_num_files = (int)zone->opts->pattern->ixfr_number;
1621 1.1 christos /* but if the number of available transfers is smaller, store less */
1622 1.1 christos if(dest_num_files > (int)zone->ixfr->data->count)
1623 1.1 christos dest_num_files = (int)zone->ixfr->data->count;
1624 1.1 christos return dest_num_files;
1625 1.1 christos }
1626 1.1 christos
1627 1.1 christos /* create ixfrfile name in buffer for file_num. The num is 1 .. number. */
1628 1.1 christos static void make_ixfr_name(char* buf, size_t len, const char* zfile,
1629 1.1 christos int file_num)
1630 1.1 christos {
1631 1.1 christos if(file_num == 1)
1632 1.1 christos snprintf(buf, len, "%s.ixfr", zfile);
1633 1.1 christos else snprintf(buf, len, "%s.ixfr.%d", zfile, file_num);
1634 1.1 christos }
1635 1.1 christos
1636 1.1 christos /* create temp ixfrfile name in buffer for file_num. The num is 1 .. number. */
1637 1.1 christos static void make_ixfr_name_temp(char* buf, size_t len, const char* zfile,
1638 1.1 christos int file_num, int temp)
1639 1.1 christos {
1640 1.1 christos if(file_num == 1)
1641 1.1 christos snprintf(buf, len, "%s.ixfr%s", zfile, (temp?".temp":""));
1642 1.1 christos else snprintf(buf, len, "%s.ixfr.%d%s", zfile, file_num,
1643 1.1 christos (temp?".temp":""));
1644 1.1 christos }
1645 1.1 christos
1646 1.1 christos /* see if ixfr file exists */
1647 1.1 christos static int ixfr_file_exists_ctmp(const char* zfile, int file_num, int temp)
1648 1.1 christos {
1649 1.1 christos struct stat statbuf;
1650 1.1 christos char ixfrfile[1024+24];
1651 1.1 christos make_ixfr_name_temp(ixfrfile, sizeof(ixfrfile), zfile, file_num, temp);
1652 1.1 christos memset(&statbuf, 0, sizeof(statbuf));
1653 1.1 christos if(stat(ixfrfile, &statbuf) < 0) {
1654 1.1 christos if(errno == ENOENT)
1655 1.1 christos return 0;
1656 1.1 christos /* file is not usable */
1657 1.1 christos return 0;
1658 1.1 christos }
1659 1.1 christos return 1;
1660 1.1 christos }
1661 1.1 christos
1662 1.1 christos int ixfr_file_exists(const char* zfile, int file_num)
1663 1.1 christos {
1664 1.1 christos return ixfr_file_exists_ctmp(zfile, file_num, 0);
1665 1.1 christos }
1666 1.1 christos
1667 1.1 christos /* see if ixfr file exists */
1668 1.1 christos static int ixfr_file_exists_temp(const char* zfile, int file_num)
1669 1.1 christos {
1670 1.1 christos return ixfr_file_exists_ctmp(zfile, file_num, 1);
1671 1.1 christos }
1672 1.1 christos
1673 1.1 christos /* unlink an ixfr file */
1674 1.1 christos static int ixfr_unlink_it_ctmp(const char* zname, const char* zfile,
1675 1.1 christos int file_num, int silent_enoent, int temp)
1676 1.1 christos {
1677 1.1 christos char ixfrfile[1024+24];
1678 1.1 christos make_ixfr_name_temp(ixfrfile, sizeof(ixfrfile), zfile, file_num, temp);
1679 1.1 christos VERBOSITY(3, (LOG_INFO, "delete zone %s IXFR data file %s",
1680 1.1 christos zname, ixfrfile));
1681 1.1 christos if(unlink(ixfrfile) < 0) {
1682 1.1 christos if(silent_enoent && errno == ENOENT)
1683 1.1 christos return 0;
1684 1.1 christos log_msg(LOG_ERR, "error to delete file %s: %s", ixfrfile,
1685 1.1 christos strerror(errno));
1686 1.1 christos return 0;
1687 1.1 christos }
1688 1.1 christos return 1;
1689 1.1 christos }
1690 1.1 christos
1691 1.1 christos int ixfr_unlink_it(const char* zname, const char* zfile, int file_num,
1692 1.1 christos int silent_enoent)
1693 1.1 christos {
1694 1.1 christos return ixfr_unlink_it_ctmp(zname, zfile, file_num, silent_enoent, 0);
1695 1.1 christos }
1696 1.1 christos
1697 1.1 christos /* unlink an ixfr file */
1698 1.1 christos static int ixfr_unlink_it_temp(const char* zname, const char* zfile,
1699 1.1 christos int file_num, int silent_enoent)
1700 1.1 christos {
1701 1.1 christos return ixfr_unlink_it_ctmp(zname, zfile, file_num, silent_enoent, 1);
1702 1.1 christos }
1703 1.1 christos
1704 1.1 christos /* read ixfr file header */
1705 1.1 christos int ixfr_read_file_header(const char* zname, const char* zfile,
1706 1.1 christos int file_num, uint32_t* oldserial, uint32_t* newserial,
1707 1.1 christos size_t* data_size, int enoent_is_err)
1708 1.1 christos {
1709 1.1 christos char ixfrfile[1024+24];
1710 1.1 christos char buf[1024];
1711 1.1 christos FILE* in;
1712 1.1 christos int num_lines = 0, got_old = 0, got_new = 0, got_datasize = 0;
1713 1.1 christos make_ixfr_name(ixfrfile, sizeof(ixfrfile), zfile, file_num);
1714 1.1 christos in = fopen(ixfrfile, "r");
1715 1.1 christos if(!in) {
1716 1.1 christos if((errno == ENOENT && enoent_is_err) || (errno != ENOENT))
1717 1.1 christos log_msg(LOG_ERR, "could not open %s: %s", ixfrfile,
1718 1.1 christos strerror(errno));
1719 1.1 christos return 0;
1720 1.1 christos }
1721 1.1 christos /* read about 10 lines, this is where the header is */
1722 1.1 christos while(!(got_old && got_new && got_datasize) && num_lines < 10) {
1723 1.1 christos buf[0]=0;
1724 1.1 christos buf[sizeof(buf)-1]=0;
1725 1.1 christos if(!fgets(buf, sizeof(buf), in)) {
1726 1.1 christos log_msg(LOG_ERR, "could not read %s: %s", ixfrfile,
1727 1.1 christos strerror(errno));
1728 1.1 christos fclose(in);
1729 1.1 christos return 0;
1730 1.1 christos }
1731 1.1 christos num_lines++;
1732 1.1 christos if(buf[0]!=0 && buf[strlen(buf)-1]=='\n')
1733 1.1 christos buf[strlen(buf)-1]=0;
1734 1.1 christos if(strncmp(buf, "; zone ", 7) == 0) {
1735 1.1 christos if(strcmp(buf+7, zname) != 0) {
1736 1.1 christos log_msg(LOG_ERR, "file has wrong zone, expected zone %s, but found %s in file %s",
1737 1.1 christos zname, buf+7, ixfrfile);
1738 1.1 christos fclose(in);
1739 1.1 christos return 0;
1740 1.1 christos }
1741 1.1 christos } else if(strncmp(buf, "; from_serial ", 14) == 0) {
1742 1.1 christos *oldserial = atoi(buf+14);
1743 1.1 christos got_old = 1;
1744 1.1 christos } else if(strncmp(buf, "; to_serial ", 12) == 0) {
1745 1.1 christos *newserial = atoi(buf+12);
1746 1.1 christos got_new = 1;
1747 1.1 christos } else if(strncmp(buf, "; data_size ", 12) == 0) {
1748 1.1 christos *data_size = (size_t)atoi(buf+12);
1749 1.1 christos got_datasize = 1;
1750 1.1 christos }
1751 1.1 christos }
1752 1.1 christos fclose(in);
1753 1.1 christos if(!got_old)
1754 1.1 christos return 0;
1755 1.1 christos if(!got_new)
1756 1.1 christos return 0;
1757 1.1 christos if(!got_datasize)
1758 1.1 christos return 0;
1759 1.1 christos return 1;
1760 1.1 christos }
1761 1.1 christos
1762 1.1 christos /* delete rest ixfr files, that are after the current item */
1763 1.1 christos static void ixfr_delete_rest_files(struct zone* zone, struct ixfr_data* from,
1764 1.1 christos const char* zfile, int temp)
1765 1.1 christos {
1766 1.1 christos size_t prevcount = 0;
1767 1.1 christos struct ixfr_data* data = from;
1768 1.1 christos while(data) {
1769 1.1 christos if(data->file_num != 0) {
1770 1.1 christos (void)ixfr_unlink_it_ctmp(zone->opts->name, zfile,
1771 1.1 christos data->file_num, 0, temp);
1772 1.1 christos data->file_num = 0;
1773 1.1 christos }
1774 1.1 christos data = ixfr_data_prev(zone->ixfr, data, &prevcount);
1775 1.1 christos }
1776 1.1 christos }
1777 1.1 christos
1778 1.1 christos void ixfr_delete_superfluous_files(struct zone* zone, const char* zfile,
1779 1.1 christos int dest_num_files)
1780 1.1 christos {
1781 1.1 christos int i = dest_num_files + 1;
1782 1.1 christos if(!ixfr_file_exists(zfile, i))
1783 1.1 christos return;
1784 1.1 christos while(ixfr_unlink_it(zone->opts->name, zfile, i, 1)) {
1785 1.1 christos i++;
1786 1.1 christos }
1787 1.1 christos }
1788 1.1 christos
1789 1.1 christos int ixfr_rename_it(const char* zname, const char* zfile, int oldnum,
1790 1.1 christos int oldtemp, int newnum, int newtemp)
1791 1.1 christos {
1792 1.1 christos char ixfrfile_old[1024+24];
1793 1.1 christos char ixfrfile_new[1024+24];
1794 1.1 christos make_ixfr_name_temp(ixfrfile_old, sizeof(ixfrfile_old), zfile, oldnum,
1795 1.1 christos oldtemp);
1796 1.1 christos make_ixfr_name_temp(ixfrfile_new, sizeof(ixfrfile_new), zfile, newnum,
1797 1.1 christos newtemp);
1798 1.1 christos VERBOSITY(3, (LOG_INFO, "rename zone %s IXFR data file %s to %s",
1799 1.1 christos zname, ixfrfile_old, ixfrfile_new));
1800 1.1 christos if(rename(ixfrfile_old, ixfrfile_new) < 0) {
1801 1.1 christos log_msg(LOG_ERR, "error to rename file %s: %s", ixfrfile_old,
1802 1.1 christos strerror(errno));
1803 1.1 christos return 0;
1804 1.1 christos }
1805 1.1 christos return 1;
1806 1.1 christos }
1807 1.1 christos
1808 1.1 christos /* delete if we have too many items in memory */
1809 1.1 christos static void ixfr_delete_memory_items(struct zone* zone, int dest_num_files)
1810 1.1 christos {
1811 1.1 christos if(!zone->ixfr || !zone->ixfr->data)
1812 1.1 christos return;
1813 1.1 christos if(dest_num_files == (int)zone->ixfr->data->count)
1814 1.1 christos return;
1815 1.1 christos if(dest_num_files > (int)zone->ixfr->data->count) {
1816 1.1 christos /* impossible, dest_num_files should be smaller */
1817 1.1 christos return;
1818 1.1 christos }
1819 1.1 christos
1820 1.1 christos /* delete oldest ixfr, until we have dest_num_files entries */
1821 1.1 christos while(dest_num_files < (int)zone->ixfr->data->count) {
1822 1.1 christos zone_ixfr_remove_oldest(zone->ixfr);
1823 1.1 christos }
1824 1.1 christos }
1825 1.1 christos
1826 1.1 christos /* rename the ixfr files that need to change name */
1827 1.1 christos static int ixfr_rename_files(struct zone* zone, const char* zfile,
1828 1.1 christos int dest_num_files)
1829 1.1 christos {
1830 1.1 christos struct ixfr_data* data, *startspot = NULL;
1831 1.1 christos size_t prevcount = 0;
1832 1.1 christos int destnum;
1833 1.1 christos if(!zone->ixfr || !zone->ixfr->data)
1834 1.1 christos return 1;
1835 1.1 christos
1836 1.1 christos /* the oldest file is at the largest number */
1837 1.1 christos data = ixfr_data_first(zone->ixfr);
1838 1.1 christos destnum = dest_num_files;
1839 1.1 christos if(!data)
1840 1.1 christos return 1; /* nothing to do */
1841 1.1 christos if(data->file_num == destnum)
1842 1.1 christos return 1; /* nothing to do for rename */
1843 1.1 christos
1844 1.1 christos /* rename the files to temporary files, because otherwise the
1845 1.1 christos * items would overwrite each other when the list touches itself.
1846 1.1 christos * On fail, the temporary files are removed and we end up with
1847 1.1 christos * the newly written data plus the remaining files, in order.
1848 1.1 christos * Thus, start the temporary rename at the oldest, then rename
1849 1.1 christos * to the final names starting from the newest. */
1850 1.1 christos while(data && data->file_num != 0) {
1851 1.1 christos /* if existing file at temporary name, delete that */
1852 1.1 christos if(ixfr_file_exists_temp(zfile, data->file_num)) {
1853 1.1 christos (void)ixfr_unlink_it_temp(zone->opts->name, zfile,
1854 1.1 christos data->file_num, 0);
1855 1.1 christos }
1856 1.1 christos
1857 1.1 christos /* rename to temporary name */
1858 1.1 christos if(!ixfr_rename_it(zone->opts->name, zfile, data->file_num, 0,
1859 1.1 christos data->file_num, 1)) {
1860 1.1 christos /* failure, we cannot store files */
1861 1.1 christos /* delete the renamed files */
1862 1.1 christos ixfr_delete_rest_files(zone, data, zfile, 1);
1863 1.1 christos return 0;
1864 1.1 christos }
1865 1.1 christos
1866 1.1 christos /* the next cycle should start at the newest file that
1867 1.1 christos * has been renamed to a temporary name */
1868 1.1 christos startspot = data;
1869 1.1 christos data = ixfr_data_next(zone->ixfr, data);
1870 1.1 christos destnum--;
1871 1.1 christos }
1872 1.1 christos
1873 1.1 christos /* rename the files to their final name position */
1874 1.1 christos data = startspot;
1875 1.1 christos while(data && data->file_num != 0) {
1876 1.1 christos destnum++;
1877 1.1 christos
1878 1.1 christos /* if there is an existing file, delete it */
1879 1.1 christos if(ixfr_file_exists(zfile, destnum)) {
1880 1.1 christos (void)ixfr_unlink_it(zone->opts->name, zfile,
1881 1.1 christos destnum, 0);
1882 1.1 christos }
1883 1.1 christos
1884 1.1 christos if(!ixfr_rename_it(zone->opts->name, zfile, data->file_num, 1, destnum, 0)) {
1885 1.1 christos /* failure, we cannot store files */
1886 1.1 christos ixfr_delete_rest_files(zone, data, zfile, 1);
1887 1.1 christos /* delete the previously renamed files, so in
1888 1.1 christos * memory stays as is, on disk we have the current
1889 1.1 christos * item (and newer transfers) okay. */
1890 1.1 christos return 0;
1891 1.1 christos }
1892 1.1 christos data->file_num = destnum;
1893 1.1 christos
1894 1.1 christos data = ixfr_data_prev(zone->ixfr, data, &prevcount);
1895 1.1 christos }
1896 1.1 christos return 1;
1897 1.1 christos }
1898 1.1 christos
1899 1.1 christos /* write the ixfr data file header */
1900 1.1 christos static int ixfr_write_file_header(struct zone* zone, struct ixfr_data* data,
1901 1.1 christos FILE* out)
1902 1.1 christos {
1903 1.1 christos if(!fprintf(out, "; IXFR data file\n"))
1904 1.1 christos return 0;
1905 1.1 christos if(!fprintf(out, "; zone %s\n", zone->opts->name))
1906 1.1 christos return 0;
1907 1.1 christos if(!fprintf(out, "; from_serial %u\n", (unsigned)data->oldserial))
1908 1.1 christos return 0;
1909 1.1 christos if(!fprintf(out, "; to_serial %u\n", (unsigned)data->newserial))
1910 1.1 christos return 0;
1911 1.1 christos if(!fprintf(out, "; data_size %u\n", (unsigned)ixfr_data_size(data)))
1912 1.1 christos return 0;
1913 1.1 christos if(data->log_str) {
1914 1.1 christos if(!fprintf(out, "; %s\n", data->log_str))
1915 1.1 christos return 0;
1916 1.1 christos }
1917 1.1 christos return 1;
1918 1.1 christos }
1919 1.1 christos
1920 1.1 christos /* print rdata on one line */
1921 1.1 christos static int
1922 1.1 christos oneline_print_rdata(buffer_type *output, rrtype_descriptor_type *descriptor,
1923 1.1 christos rr_type* record)
1924 1.1 christos {
1925 1.1 christos size_t i;
1926 1.1 christos size_t saved_position = buffer_position(output);
1927 1.1 christos
1928 1.1 christos for (i = 0; i < record->rdata_count; ++i) {
1929 1.1 christos if (i == 0) {
1930 1.1 christos buffer_printf(output, "\t");
1931 1.1 christos } else {
1932 1.1 christos buffer_printf(output, " ");
1933 1.1 christos }
1934 1.1 christos if (!rdata_atom_to_string(
1935 1.1 christos output,
1936 1.1 christos (rdata_zoneformat_type) descriptor->zoneformat[i],
1937 1.1 christos record->rdatas[i], record))
1938 1.1 christos {
1939 1.1 christos buffer_set_position(output, saved_position);
1940 1.1 christos return 0;
1941 1.1 christos }
1942 1.1 christos }
1943 1.1 christos
1944 1.1 christos return 1;
1945 1.1 christos }
1946 1.1 christos
1947 1.1 christos /* parse wireformat RR into a struct RR in temp region */
1948 1.1 christos static int parse_wirerr_into_temp(struct zone* zone, char* fname,
1949 1.1 christos struct region* temp, uint8_t* buf, size_t len,
1950 1.1 christos const dname_type** dname, struct rr* rr)
1951 1.1 christos {
1952 1.1 christos size_t bufpos = 0;
1953 1.1 christos uint16_t rdlen;
1954 1.1 christos ssize_t rdata_num;
1955 1.1 christos buffer_type packet;
1956 1.1 christos domain_table_type* owners;
1957 1.1 christos owners = domain_table_create(temp);
1958 1.1 christos memset(rr, 0, sizeof(*rr));
1959 1.1 christos *dname = dname_make(temp, buf, 1);
1960 1.1 christos if(!*dname) {
1961 1.1 christos log_msg(LOG_ERR, "failed to write zone %s IXFR data %s: failed to parse dname", zone->opts->name, fname);
1962 1.1 christos return 0;
1963 1.1 christos }
1964 1.1 christos bufpos = (*dname)->name_size;
1965 1.1 christos if(bufpos+10 > len) {
1966 1.1 christos log_msg(LOG_ERR, "failed to write zone %s IXFR data %s: buffer too short", zone->opts->name, fname);
1967 1.1 christos return 0;
1968 1.1 christos }
1969 1.1 christos rr->type = read_uint16(buf+bufpos);
1970 1.1 christos bufpos += 2;
1971 1.1 christos rr->klass = read_uint16(buf+bufpos);
1972 1.1 christos bufpos += 2;
1973 1.1 christos rr->ttl = read_uint32(buf+bufpos);
1974 1.1 christos bufpos += 4;
1975 1.1 christos rdlen = read_uint16(buf+bufpos);
1976 1.1 christos bufpos += 2;
1977 1.1 christos if(bufpos + rdlen > len) {
1978 1.1 christos log_msg(LOG_ERR, "failed to write zone %s IXFR data %s: buffer too short for rdatalen", zone->opts->name, fname);
1979 1.1 christos return 0;
1980 1.1 christos }
1981 1.1 christos buffer_create_from(&packet, buf+bufpos, rdlen);
1982 1.1 christos rdata_num = rdata_wireformat_to_rdata_atoms(
1983 1.1 christos temp, owners, rr->type, rdlen, &packet, &rr->rdatas);
1984 1.1 christos if(rdata_num == -1) {
1985 1.1 christos log_msg(LOG_ERR, "failed to write zone %s IXFR data %s: cannot parse rdata", zone->opts->name, fname);
1986 1.1 christos return 0;
1987 1.1 christos }
1988 1.1 christos rr->rdata_count = rdata_num;
1989 1.1 christos return 1;
1990 1.1 christos }
1991 1.1 christos
1992 1.1 christos /* print RR on one line in output buffer. caller must zeroterminate, if
1993 1.1 christos * that is needed. */
1994 1.1 christos static int print_rr_oneline(struct buffer* rr_buffer, const dname_type* dname,
1995 1.1 christos struct rr* rr)
1996 1.1 christos {
1997 1.1 christos rrtype_descriptor_type *descriptor;
1998 1.1 christos descriptor = rrtype_descriptor_by_type(rr->type);
1999 1.1 christos buffer_printf(rr_buffer, "%s", dname_to_string(dname, NULL));
2000 1.1 christos buffer_printf(rr_buffer, "\t%lu\t%s\t%s", (unsigned long)rr->ttl,
2001 1.1 christos rrclass_to_string(rr->klass), rrtype_to_string(rr->type));
2002 1.1 christos if(!oneline_print_rdata(rr_buffer, descriptor, rr)) {
2003 1.1 christos if(!rdata_atoms_to_unknown_string(rr_buffer,
2004 1.1 christos descriptor, rr->rdata_count, rr->rdatas)) {
2005 1.1 christos return 0;
2006 1.1 christos }
2007 1.1 christos }
2008 1.1 christos return 1;
2009 1.1 christos }
2010 1.1 christos
2011 1.1 christos /* write one RR to file, on one line */
2012 1.1 christos static int ixfr_write_rr(struct zone* zone, FILE* out, char* fname,
2013 1.1 christos uint8_t* buf, size_t len, struct region* temp, buffer_type* rr_buffer)
2014 1.1 christos {
2015 1.1 christos const dname_type* dname;
2016 1.1 christos struct rr rr;
2017 1.1 christos
2018 1.1 christos if(!parse_wirerr_into_temp(zone, fname, temp, buf, len, &dname, &rr)) {
2019 1.1 christos region_free_all(temp);
2020 1.1 christos return 0;
2021 1.1 christos }
2022 1.1 christos
2023 1.1 christos buffer_clear(rr_buffer);
2024 1.1 christos if(!print_rr_oneline(rr_buffer, dname, &rr)) {
2025 1.1 christos log_msg(LOG_ERR, "failed to write zone %s IXFR data %s: cannot spool RR string into buffer", zone->opts->name, fname);
2026 1.1 christos region_free_all(temp);
2027 1.1 christos return 0;
2028 1.1 christos }
2029 1.1 christos buffer_write_u8(rr_buffer, 0);
2030 1.1 christos buffer_flip(rr_buffer);
2031 1.1 christos
2032 1.1 christos if(!fprintf(out, "%s\n", buffer_begin(rr_buffer))) {
2033 1.1 christos log_msg(LOG_ERR, "failed to write zone %s IXFR data %s: cannot print RR string to file: %s", zone->opts->name, fname, strerror(errno));
2034 1.1 christos region_free_all(temp);
2035 1.1 christos return 0;
2036 1.1 christos }
2037 1.1 christos region_free_all(temp);
2038 1.1 christos return 1;
2039 1.1 christos }
2040 1.1 christos
2041 1.1 christos /* write ixfr RRs to file */
2042 1.1 christos static int ixfr_write_rrs(struct zone* zone, FILE* out, char* fname,
2043 1.1 christos uint8_t* buf, size_t len, struct region* temp, buffer_type* rr_buffer)
2044 1.1 christos {
2045 1.1 christos size_t current = 0;
2046 1.1 christos if(!buf || len == 0)
2047 1.1 christos return 1;
2048 1.1 christos while(current < len) {
2049 1.1 christos size_t rrlen = count_rr_length(buf, len, current);
2050 1.1 christos if(rrlen == 0)
2051 1.1 christos return 0;
2052 1.1 christos if(current + rrlen > len)
2053 1.1 christos return 0;
2054 1.1 christos if(!ixfr_write_rr(zone, out, fname, buf+current, rrlen,
2055 1.1 christos temp, rr_buffer))
2056 1.1 christos return 0;
2057 1.1 christos current += rrlen;
2058 1.1 christos }
2059 1.1 christos return 1;
2060 1.1 christos }
2061 1.1 christos
2062 1.1 christos /* write the ixfr data file data */
2063 1.1 christos static int ixfr_write_file_data(struct zone* zone, struct ixfr_data* data,
2064 1.1 christos FILE* out, char* fname)
2065 1.1 christos {
2066 1.1 christos struct region* temp, *rrtemp;
2067 1.1 christos buffer_type* rr_buffer;
2068 1.1 christos temp = region_create(xalloc, free);
2069 1.1 christos rrtemp = region_create(xalloc, free);
2070 1.1 christos rr_buffer = buffer_create(rrtemp, MAX_RDLENGTH);
2071 1.1 christos
2072 1.1 christos if(!ixfr_write_rrs(zone, out, fname, data->newsoa, data->newsoa_len,
2073 1.1 christos temp, rr_buffer)) {
2074 1.1 christos region_destroy(temp);
2075 1.1 christos region_destroy(rrtemp);
2076 1.1 christos return 0;
2077 1.1 christos }
2078 1.1 christos if(!ixfr_write_rrs(zone, out, fname, data->oldsoa, data->oldsoa_len,
2079 1.1 christos temp, rr_buffer)) {
2080 1.1 christos region_destroy(temp);
2081 1.1 christos region_destroy(rrtemp);
2082 1.1 christos return 0;
2083 1.1 christos }
2084 1.1 christos if(!ixfr_write_rrs(zone, out, fname, data->del, data->del_len,
2085 1.1 christos temp, rr_buffer)) {
2086 1.1 christos region_destroy(temp);
2087 1.1 christos region_destroy(rrtemp);
2088 1.1 christos return 0;
2089 1.1 christos }
2090 1.1 christos if(!ixfr_write_rrs(zone, out, fname, data->add, data->add_len,
2091 1.1 christos temp, rr_buffer)) {
2092 1.1 christos region_destroy(temp);
2093 1.1 christos region_destroy(rrtemp);
2094 1.1 christos return 0;
2095 1.1 christos }
2096 1.1 christos region_destroy(temp);
2097 1.1 christos region_destroy(rrtemp);
2098 1.1 christos return 1;
2099 1.1 christos }
2100 1.1 christos
2101 1.1 christos int ixfr_write_file(struct zone* zone, struct ixfr_data* data,
2102 1.1 christos const char* zfile, int file_num)
2103 1.1 christos {
2104 1.1 christos char ixfrfile[1024+24];
2105 1.1 christos FILE* out;
2106 1.1 christos make_ixfr_name(ixfrfile, sizeof(ixfrfile), zfile, file_num);
2107 1.1 christos VERBOSITY(1, (LOG_INFO, "writing zone %s IXFR data to file %s",
2108 1.1 christos zone->opts->name, ixfrfile));
2109 1.1 christos out = fopen(ixfrfile, "w");
2110 1.1 christos if(!out) {
2111 1.1 christos log_msg(LOG_ERR, "could not open for writing zone %s IXFR file %s: %s",
2112 1.1 christos zone->opts->name, ixfrfile, strerror(errno));
2113 1.1 christos return 0;
2114 1.1 christos }
2115 1.1 christos
2116 1.1 christos if(!ixfr_write_file_header(zone, data, out)) {
2117 1.1 christos log_msg(LOG_ERR, "could not write file header for zone %s IXFR file %s: %s",
2118 1.1 christos zone->opts->name, ixfrfile, strerror(errno));
2119 1.1 christos fclose(out);
2120 1.1 christos return 0;
2121 1.1 christos }
2122 1.1 christos if(!ixfr_write_file_data(zone, data, out, ixfrfile)) {
2123 1.1 christos fclose(out);
2124 1.1 christos return 0;
2125 1.1 christos }
2126 1.1 christos
2127 1.1 christos fclose(out);
2128 1.1 christos data->file_num = file_num;
2129 1.1 christos return 1;
2130 1.1 christos }
2131 1.1 christos
2132 1.1 christos /* write the ixfr files that need to be stored on disk */
2133 1.1 christos static void ixfr_write_files(struct zone* zone, const char* zfile)
2134 1.1 christos {
2135 1.1 christos size_t prevcount = 0;
2136 1.1 christos int num;
2137 1.1 christos struct ixfr_data* data;
2138 1.1 christos if(!zone->ixfr || !zone->ixfr->data)
2139 1.1 christos return; /* nothing to write */
2140 1.1 christos
2141 1.1 christos /* write unwritten files to disk */
2142 1.1 christos data = ixfr_data_last(zone->ixfr);
2143 1.1 christos num=1;
2144 1.1 christos while(data && data->file_num == 0) {
2145 1.1 christos if(!ixfr_write_file(zone, data, zfile, num)) {
2146 1.1 christos /* There could be more files that are sitting on the
2147 1.1 christos * disk, remove them, they are not used without
2148 1.1 christos * this ixfr file.
2149 1.1 christos *
2150 1.1 christos * Give this element a file num, so it can be
2151 1.1 christos * deleted, it failed to write. It may be partial,
2152 1.1 christos * and we do not want to read that back in.
2153 1.1 christos * We are left with the newer transfers, that form
2154 1.1 christos * a correct list of transfers, that are wholly
2155 1.1 christos * written. */
2156 1.1 christos data->file_num = num;
2157 1.1 christos ixfr_delete_rest_files(zone, data, zfile, 0);
2158 1.1 christos return;
2159 1.1 christos }
2160 1.1 christos num++;
2161 1.1 christos data = ixfr_data_prev(zone->ixfr, data, &prevcount);
2162 1.1 christos }
2163 1.1 christos }
2164 1.1 christos
2165 1.1 christos void ixfr_write_to_file(struct zone* zone, const char* zfile)
2166 1.1 christos {
2167 1.1 christos int dest_num_files = 0;
2168 1.1 christos /* we just wrote the zonefile zfile, and it is time to write
2169 1.1 christos * the IXFR contents to the disk too. */
2170 1.1 christos /* find out what the target number of files is that we want on
2171 1.1 christos * the disk */
2172 1.1 christos dest_num_files = ixfr_target_number_files(zone);
2173 1.1 christos
2174 1.1 christos /* delete if we have more than we need */
2175 1.1 christos ixfr_delete_superfluous_files(zone, zfile, dest_num_files);
2176 1.1 christos
2177 1.1 christos /* delete if we have too much in memory */
2178 1.1 christos ixfr_delete_memory_items(zone, dest_num_files);
2179 1.1 christos
2180 1.1 christos /* rename the transfers that we have that already have a file */
2181 1.1 christos if(!ixfr_rename_files(zone, zfile, dest_num_files))
2182 1.1 christos return;
2183 1.1 christos
2184 1.1 christos /* write the transfers that are not written yet */
2185 1.1 christos ixfr_write_files(zone, zfile);
2186 1.1 christos }
2187 1.1 christos
2188 1.1 christos /* skip whitespace */
2189 1.1 christos static char* skipwhite(char* str)
2190 1.1 christos {
2191 1.1 christos while(isspace((unsigned char)*str))
2192 1.1 christos str++;
2193 1.1 christos return str;
2194 1.1 christos }
2195 1.1 christos
2196 1.1 christos /* read one RR from file */
2197 1.1 christos static int ixfr_data_readrr(struct zone* zone, FILE* in, const char* ixfrfile,
2198 1.1 christos struct region* tempregion, struct domain_table* temptable,
2199 1.1 christos struct zone* tempzone, struct rr** rr)
2200 1.1 christos {
2201 1.1 christos char line[65536];
2202 1.1 christos char* str;
2203 1.1 christos struct domain* domain_parsed = NULL;
2204 1.1 christos int num_rrs = 0;
2205 1.1 christos line[sizeof(line)-1]=0;
2206 1.1 christos while(!feof(in)) {
2207 1.1 christos if(!fgets(line, sizeof(line), in)) {
2208 1.1 christos if(errno == 0) {
2209 1.1 christos log_msg(LOG_ERR, "zone %s IXFR data %s: "
2210 1.1 christos "unexpected end of file", zone->opts->name, ixfrfile);
2211 1.1 christos return 0;
2212 1.1 christos }
2213 1.1 christos log_msg(LOG_ERR, "zone %s IXFR data %s: "
2214 1.1 christos "cannot read: %s", zone->opts->name, ixfrfile,
2215 1.1 christos strerror(errno));
2216 1.1 christos return 0;
2217 1.1 christos }
2218 1.1 christos str = skipwhite(line);
2219 1.1 christos if(str[0] == 0) {
2220 1.1 christos /* empty line */
2221 1.1 christos continue;
2222 1.1 christos }
2223 1.1 christos if(str[0] == ';') {
2224 1.1 christos /* comment line */
2225 1.1 christos continue;
2226 1.1 christos }
2227 1.1 christos if(zonec_parse_string(tempregion, temptable, tempzone,
2228 1.1 christos line, &domain_parsed, &num_rrs)) {
2229 1.1 christos log_msg(LOG_ERR, "zone %s IXFR data %s: parse error",
2230 1.1 christos zone->opts->name, ixfrfile);
2231 1.1 christos return 0;
2232 1.1 christos }
2233 1.1 christos if(num_rrs != 1) {
2234 1.1 christos log_msg(LOG_ERR, "zone %s IXFR data %s: parse error",
2235 1.1 christos zone->opts->name, ixfrfile);
2236 1.1 christos return 0;
2237 1.1 christos }
2238 1.1 christos *rr = &domain_parsed->rrsets->rrs[0];
2239 1.1 christos return 1;
2240 1.1 christos }
2241 1.1 christos log_msg(LOG_ERR, "zone %s IXFR data %s: file too short, no newsoa",
2242 1.1 christos zone->opts->name, ixfrfile);
2243 1.1 christos return 0;
2244 1.1 christos }
2245 1.1 christos
2246 1.1 christos /* delete from domain table */
2247 1.1 christos static void domain_table_delete(struct domain_table* table,
2248 1.1 christos struct domain* domain)
2249 1.1 christos {
2250 1.1 christos #ifdef USE_RADIX_TREE
2251 1.1 christos radix_delete(table->nametree, domain->rnode);
2252 1.1 christos #else
2253 1.1 christos rbtree_delete(table->names_to_domains, domain->node.key);
2254 1.1 christos #endif
2255 1.1 christos }
2256 1.1 christos
2257 1.1 christos /* can we delete temp domain */
2258 1.1 christos static int can_del_temp_domain(struct domain* domain)
2259 1.1 christos {
2260 1.1 christos struct domain* n;
2261 1.1 christos /* we want to keep the zone apex */
2262 1.1 christos if(domain->is_apex)
2263 1.1 christos return 0;
2264 1.1 christos if(domain->rrsets)
2265 1.1 christos return 0;
2266 1.1 christos if(domain->usage)
2267 1.1 christos return 0;
2268 1.1 christos /* check if there are domains under it */
2269 1.1 christos n = domain_next(domain);
2270 1.1 christos if(n && domain_is_subdomain(n, domain))
2271 1.1 christos return 0;
2272 1.1 christos return 1;
2273 1.1 christos }
2274 1.1 christos
2275 1.1 christos /* delete temporary domain */
2276 1.1 christos static void ixfr_temp_deldomain(struct domain_table* temptable,
2277 1.1 christos struct domain* domain)
2278 1.1 christos {
2279 1.1 christos struct domain* p;
2280 1.1 christos if(!can_del_temp_domain(domain))
2281 1.1 christos return;
2282 1.1 christos p = domain->parent;
2283 1.1 christos /* see if this domain is someones wildcard-child-closest-match,
2284 1.1 christos * which can only be the parent, and then it should use the
2285 1.1 christos * one-smaller than this domain as closest-match. */
2286 1.1 christos if(domain->parent &&
2287 1.1 christos domain->parent->wildcard_child_closest_match == domain)
2288 1.1 christos domain->parent->wildcard_child_closest_match =
2289 1.1 christos domain_previous_existing_child(domain);
2290 1.1 christos domain_table_delete(temptable, domain);
2291 1.1 christos while(p) {
2292 1.1 christos struct domain* up = p->parent;
2293 1.1 christos if(!can_del_temp_domain(p))
2294 1.1 christos break;
2295 1.1 christos if(p->parent && p->parent->wildcard_child_closest_match == p)
2296 1.1 christos p->parent->wildcard_child_closest_match =
2297 1.1 christos domain_previous_existing_child(p);
2298 1.1 christos domain_table_delete(temptable, p);
2299 1.1 christos p = up;
2300 1.1 christos }
2301 1.1 christos }
2302 1.1 christos
2303 1.1 christos /* clear out the just read RR from the temp table */
2304 1.1 christos static void clear_temp_table_of_rr(struct domain_table* temptable,
2305 1.1 christos struct zone* tempzone, struct rr* rr)
2306 1.1 christos {
2307 1.1 christos #if 0 /* clear out by removing everything, alternate for the cleanout code */
2308 1.1 christos /* clear domains from the tempzone,
2309 1.1 christos * the only domain left is the zone apex and its parents */
2310 1.1 christos domain_type* domain;
2311 1.1 christos #ifdef USE_RADIX_TREE
2312 1.1 christos struct radnode* first = radix_first(temptable->nametree);
2313 1.1 christos domain = first?(domain_type*)first->elem:NULL;
2314 1.1 christos #else
2315 1.1 christos domain = (domain_type*)rbtree_first(temptable->names_to_domains);
2316 1.1 christos #endif
2317 1.1 christos while(domain != (domain_type*)RBTREE_NULL && domain) {
2318 1.1 christos domain_type* next = domain_next(domain);
2319 1.1 christos if(domain != tempzone->apex &&
2320 1.1 christos !domain_is_subdomain(tempzone->apex, domain)) {
2321 1.1 christos domain_table_delete(temptable, domain);
2322 1.1 christos } else {
2323 1.1 christos if(!domain->parent /* is the root */ ||
2324 1.1 christos domain == tempzone->apex)
2325 1.1 christos domain->usage = 1;
2326 1.1 christos else domain->usage = 0;
2327 1.1 christos }
2328 1.1 christos domain = next;
2329 1.1 christos }
2330 1.1 christos
2331 1.1 christos if(rr->owner == tempzone->apex) {
2332 1.1 christos tempzone->apex->rrsets = NULL;
2333 1.1 christos tempzone->soa_rrset = NULL;
2334 1.1 christos tempzone->soa_nx_rrset = NULL;
2335 1.1 christos tempzone->ns_rrset = NULL;
2336 1.1 christos }
2337 1.1 christos return;
2338 1.1 christos #endif
2339 1.1 christos
2340 1.1 christos /* clear domains in the rdata */
2341 1.1 christos unsigned i;
2342 1.1 christos for(i=0; i<rr->rdata_count; i++) {
2343 1.1 christos if(rdata_atom_is_domain(rr->type, i)) {
2344 1.1 christos /* clear out that dname */
2345 1.1 christos struct domain* domain =
2346 1.1 christos rdata_atom_domain(rr->rdatas[i]);
2347 1.1 christos domain->usage --;
2348 1.1 christos if(domain != tempzone->apex && domain->usage == 0)
2349 1.1 christos ixfr_temp_deldomain(temptable, domain);
2350 1.1 christos }
2351 1.1 christos }
2352 1.1 christos
2353 1.1 christos /* clear domain_parsed */
2354 1.1 christos if(rr->owner == tempzone->apex) {
2355 1.1 christos tempzone->apex->rrsets = NULL;
2356 1.1 christos tempzone->soa_rrset = NULL;
2357 1.1 christos tempzone->soa_nx_rrset = NULL;
2358 1.1 christos tempzone->ns_rrset = NULL;
2359 1.1 christos } else {
2360 1.1 christos rr->owner->rrsets = NULL;
2361 1.1 christos if(rr->owner->usage == 0) {
2362 1.1 christos ixfr_temp_deldomain(temptable, rr->owner);
2363 1.1 christos }
2364 1.1 christos }
2365 1.1 christos }
2366 1.1 christos
2367 1.1 christos /* read ixfr data new SOA */
2368 1.1 christos static int ixfr_data_readnewsoa(struct ixfr_data* data, struct zone* zone,
2369 1.1 christos FILE* in, const char* ixfrfile, struct region* tempregion,
2370 1.1 christos struct domain_table* temptable, struct zone* tempzone,
2371 1.1 christos uint32_t dest_serial)
2372 1.1 christos {
2373 1.1 christos struct rr* rr;
2374 1.1 christos size_t capacity = 0;
2375 1.1 christos if(!ixfr_data_readrr(zone, in, ixfrfile, tempregion, temptable,
2376 1.1 christos tempzone, &rr))
2377 1.1 christos return 0;
2378 1.1 christos if(rr->type != TYPE_SOA) {
2379 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: IXFR data does not start with SOA",
2380 1.1 christos zone->opts->name, ixfrfile);
2381 1.1 christos return 0;
2382 1.1 christos }
2383 1.1 christos if(rr->klass != CLASS_IN) {
2384 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: IXFR data is not class IN",
2385 1.1 christos zone->opts->name, ixfrfile);
2386 1.1 christos return 0;
2387 1.1 christos }
2388 1.1 christos if(!zone->apex) {
2389 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: zone has no apex, no zone data",
2390 1.1 christos zone->opts->name, ixfrfile);
2391 1.1 christos return 0;
2392 1.1 christos }
2393 1.1 christos if(dname_compare(domain_dname(zone->apex), domain_dname(rr->owner)) != 0) {
2394 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: IXFR data wrong SOA for zone %s",
2395 1.1 christos zone->opts->name, ixfrfile, domain_to_string(rr->owner));
2396 1.1 christos return 0;
2397 1.1 christos }
2398 1.1 christos data->newserial = soa_rr_get_serial(rr);
2399 1.1 christos if(data->newserial != dest_serial) {
2400 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: IXFR data contains the wrong version, serial %u but want destination serial %u",
2401 1.1 christos zone->opts->name, ixfrfile, data->newserial,
2402 1.1 christos dest_serial);
2403 1.1 christos return 0;
2404 1.1 christos }
2405 1.1 christos if(!ixfr_putrr(domain_dname(rr->owner), rr->type, rr->klass, rr->ttl, rr->rdatas, rr->rdata_count, &data->newsoa, &data->newsoa_len, &capacity)) {
2406 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: cannot allocate space",
2407 1.1 christos zone->opts->name, ixfrfile);
2408 1.1 christos return 0;
2409 1.1 christos }
2410 1.1 christos clear_temp_table_of_rr(temptable, tempzone, rr);
2411 1.1 christos region_free_all(tempregion);
2412 1.1 christos ixfr_trim_capacity(&data->newsoa, &data->newsoa_len, &capacity);
2413 1.1 christos return 1;
2414 1.1 christos }
2415 1.1 christos
2416 1.1 christos /* read ixfr data old SOA */
2417 1.1 christos static int ixfr_data_readoldsoa(struct ixfr_data* data, struct zone* zone,
2418 1.1 christos FILE* in, const char* ixfrfile, struct region* tempregion,
2419 1.1 christos struct domain_table* temptable, struct zone* tempzone,
2420 1.1 christos uint32_t* dest_serial)
2421 1.1 christos {
2422 1.1 christos struct rr* rr;
2423 1.1 christos size_t capacity = 0;
2424 1.1 christos if(!ixfr_data_readrr(zone, in, ixfrfile, tempregion, temptable,
2425 1.1 christos tempzone, &rr))
2426 1.1 christos return 0;
2427 1.1 christos if(rr->type != TYPE_SOA) {
2428 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: IXFR data 2nd RR is not SOA",
2429 1.1 christos zone->opts->name, ixfrfile);
2430 1.1 christos return 0;
2431 1.1 christos }
2432 1.1 christos if(rr->klass != CLASS_IN) {
2433 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: IXFR data 2ndSOA is not class IN",
2434 1.1 christos zone->opts->name, ixfrfile);
2435 1.1 christos return 0;
2436 1.1 christos }
2437 1.1 christos if(!zone->apex) {
2438 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: zone has no apex, no zone data",
2439 1.1 christos zone->opts->name, ixfrfile);
2440 1.1 christos return 0;
2441 1.1 christos }
2442 1.1 christos if(dname_compare(domain_dname(zone->apex), domain_dname(rr->owner)) != 0) {
2443 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: IXFR data wrong 2nd SOA for zone %s",
2444 1.1 christos zone->opts->name, ixfrfile, domain_to_string(rr->owner));
2445 1.1 christos return 0;
2446 1.1 christos }
2447 1.1 christos data->oldserial = soa_rr_get_serial(rr);
2448 1.1 christos if(!ixfr_putrr(domain_dname(rr->owner), rr->type, rr->klass, rr->ttl, rr->rdatas, rr->rdata_count, &data->oldsoa, &data->oldsoa_len, &capacity)) {
2449 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: cannot allocate space",
2450 1.1 christos zone->opts->name, ixfrfile);
2451 1.1 christos return 0;
2452 1.1 christos }
2453 1.1 christos clear_temp_table_of_rr(temptable, tempzone, rr);
2454 1.1 christos region_free_all(tempregion);
2455 1.1 christos ixfr_trim_capacity(&data->oldsoa, &data->oldsoa_len, &capacity);
2456 1.1 christos *dest_serial = data->oldserial;
2457 1.1 christos return 1;
2458 1.1 christos }
2459 1.1 christos
2460 1.1 christos /* read ixfr data del section */
2461 1.1 christos static int ixfr_data_readdel(struct ixfr_data* data, struct zone* zone,
2462 1.1 christos FILE* in, const char* ixfrfile, struct region* tempregion,
2463 1.1 christos struct domain_table* temptable, struct zone* tempzone)
2464 1.1 christos {
2465 1.1 christos struct rr* rr;
2466 1.1 christos size_t capacity = 0;
2467 1.1 christos while(1) {
2468 1.1 christos if(!ixfr_data_readrr(zone, in, ixfrfile, tempregion, temptable,
2469 1.1 christos tempzone, &rr))
2470 1.1 christos return 0;
2471 1.1 christos if(!ixfr_putrr(domain_dname(rr->owner), rr->type, rr->klass, rr->ttl, rr->rdatas, rr->rdata_count, &data->del, &data->del_len, &capacity)) {
2472 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: cannot allocate space",
2473 1.1 christos zone->opts->name, ixfrfile);
2474 1.1 christos return 0;
2475 1.1 christos }
2476 1.1 christos /* check SOA and also serial, because there could be other
2477 1.1 christos * add and del sections from older versions collated, we can
2478 1.1 christos * see this del section end when it has the serial */
2479 1.1 christos if(rr->type == TYPE_SOA &&
2480 1.1 christos soa_rr_get_serial(rr) == data->newserial) {
2481 1.1 christos /* end of del section. */
2482 1.1 christos clear_temp_table_of_rr(temptable, tempzone, rr);
2483 1.1 christos region_free_all(tempregion);
2484 1.1 christos break;
2485 1.1 christos }
2486 1.1 christos clear_temp_table_of_rr(temptable, tempzone, rr);
2487 1.1 christos region_free_all(tempregion);
2488 1.1 christos }
2489 1.1 christos ixfr_trim_capacity(&data->del, &data->del_len, &capacity);
2490 1.1 christos return 1;
2491 1.1 christos }
2492 1.1 christos
2493 1.1 christos /* read ixfr data add section */
2494 1.1 christos static int ixfr_data_readadd(struct ixfr_data* data, struct zone* zone,
2495 1.1 christos FILE* in, const char* ixfrfile, struct region* tempregion,
2496 1.1 christos struct domain_table* temptable, struct zone* tempzone)
2497 1.1 christos {
2498 1.1 christos struct rr* rr;
2499 1.1 christos size_t capacity = 0;
2500 1.1 christos while(1) {
2501 1.1 christos if(!ixfr_data_readrr(zone, in, ixfrfile, tempregion, temptable,
2502 1.1 christos tempzone, &rr))
2503 1.1 christos return 0;
2504 1.1 christos if(!ixfr_putrr(domain_dname(rr->owner), rr->type, rr->klass, rr->ttl, rr->rdatas, rr->rdata_count, &data->add, &data->add_len, &capacity)) {
2505 1.1 christos log_msg(LOG_ERR, "zone %s ixfr data %s: cannot allocate space",
2506 1.1 christos zone->opts->name, ixfrfile);
2507 1.1 christos return 0;
2508 1.1 christos }
2509 1.1 christos if(rr->type == TYPE_SOA &&
2510 1.1 christos soa_rr_get_serial(rr) == data->newserial) {
2511 1.1 christos /* end of add section. */
2512 1.1 christos clear_temp_table_of_rr(temptable, tempzone, rr);
2513 1.1 christos region_free_all(tempregion);
2514 1.1 christos break;
2515 1.1 christos }
2516 1.1 christos clear_temp_table_of_rr(temptable, tempzone, rr);
2517 1.1 christos region_free_all(tempregion);
2518 1.1 christos }
2519 1.1 christos ixfr_trim_capacity(&data->add, &data->add_len, &capacity);
2520 1.1 christos return 1;
2521 1.1 christos }
2522 1.1 christos
2523 1.1 christos /* read ixfr data from file */
2524 1.1 christos static int ixfr_data_read(struct nsd* nsd, struct zone* zone, FILE* in,
2525 1.1 christos const char* ixfrfile, uint32_t* dest_serial, int file_num)
2526 1.1 christos {
2527 1.1 christos struct ixfr_data* data = NULL;
2528 1.1 christos struct region* tempregion, *stayregion;
2529 1.1 christos struct domain_table* temptable;
2530 1.1 christos struct zone* tempzone;
2531 1.1 christos
2532 1.1 christos if(zone->ixfr &&
2533 1.1 christos zone->ixfr->data->count == zone->opts->pattern->ixfr_number) {
2534 1.1 christos VERBOSITY(3, (LOG_INFO, "zone %s skip %s IXFR data because only %d ixfr-number configured",
2535 1.1 christos zone->opts->name, ixfrfile, (int)zone->opts->pattern->ixfr_number));
2536 1.1 christos return 0;
2537 1.1 christos }
2538 1.1 christos
2539 1.1 christos /* the file has header comments, new soa, old soa, delsection,
2540 1.1 christos * addsection. The delsection and addsection end in a SOA of oldver
2541 1.1 christos * and newver respectively. */
2542 1.1 christos data = xalloc_zero(sizeof(*data));
2543 1.1 christos data->file_num = file_num;
2544 1.1 christos
2545 1.1 christos /* the temp region is cleared after every RR */
2546 1.1 christos tempregion = region_create(xalloc, free);
2547 1.1 christos /* the stay region holds the temporary data that stays between RRs */
2548 1.1 christos stayregion = region_create(xalloc, free);
2549 1.1 christos temptable = domain_table_create(stayregion);
2550 1.1 christos tempzone = region_alloc_zero(stayregion, sizeof(zone_type));
2551 1.1 christos if(!zone->apex) {
2552 1.1 christos ixfr_data_free(data);
2553 1.1 christos region_destroy(tempregion);
2554 1.1 christos region_destroy(stayregion);
2555 1.1 christos return 0;
2556 1.1 christos }
2557 1.1 christos tempzone->apex = domain_table_insert(temptable,
2558 1.1 christos domain_dname(zone->apex));
2559 1.1 christos temptable->root->usage++;
2560 1.1 christos tempzone->apex->usage++;
2561 1.1 christos tempzone->opts = zone->opts;
2562 1.1 christos /* switch to per RR region for new allocations in temp domain table */
2563 1.1 christos temptable->region = tempregion;
2564 1.1 christos
2565 1.1 christos if(!ixfr_data_readnewsoa(data, zone, in, ixfrfile, tempregion,
2566 1.1 christos temptable, tempzone, *dest_serial)) {
2567 1.1 christos ixfr_data_free(data);
2568 1.1 christos region_destroy(tempregion);
2569 1.1 christos region_destroy(stayregion);
2570 1.1 christos return 0;
2571 1.1 christos }
2572 1.1 christos if(!ixfr_data_readoldsoa(data, zone, in, ixfrfile, tempregion,
2573 1.1 christos temptable, tempzone, dest_serial)) {
2574 1.1 christos ixfr_data_free(data);
2575 1.1 christos region_destroy(tempregion);
2576 1.1 christos region_destroy(stayregion);
2577 1.1 christos return 0;
2578 1.1 christos }
2579 1.1 christos if(!ixfr_data_readdel(data, zone, in, ixfrfile, tempregion, temptable,
2580 1.1 christos tempzone)) {
2581 1.1 christos ixfr_data_free(data);
2582 1.1 christos region_destroy(tempregion);
2583 1.1 christos region_destroy(stayregion);
2584 1.1 christos return 0;
2585 1.1 christos }
2586 1.1 christos if(!ixfr_data_readadd(data, zone, in, ixfrfile, tempregion, temptable,
2587 1.1 christos tempzone)) {
2588 1.1 christos ixfr_data_free(data);
2589 1.1 christos region_destroy(tempregion);
2590 1.1 christos region_destroy(stayregion);
2591 1.1 christos return 0;
2592 1.1 christos }
2593 1.1 christos
2594 1.1 christos region_destroy(tempregion);
2595 1.1 christos region_destroy(stayregion);
2596 1.1 christos
2597 1.1 christos if(!zone->ixfr)
2598 1.1 christos zone->ixfr = zone_ixfr_create(nsd);
2599 1.1 christos if(zone->opts->pattern->ixfr_size != 0 &&
2600 1.1 christos zone->ixfr->total_size + ixfr_data_size(data) >
2601 1.1 christos zone->opts->pattern->ixfr_size) {
2602 1.1 christos VERBOSITY(3, (LOG_INFO, "zone %s skip %s IXFR data because only ixfr-size: %u configured, and it is %u size",
2603 1.1 christos zone->opts->name, ixfrfile, (unsigned)zone->opts->pattern->ixfr_size, (unsigned)ixfr_data_size(data)));
2604 1.1 christos ixfr_data_free(data);
2605 1.1 christos return 0;
2606 1.1 christos }
2607 1.1 christos zone_ixfr_add(zone->ixfr, data, 0);
2608 1.1 christos VERBOSITY(3, (LOG_INFO, "zone %s read %s IXFR data of %u bytes",
2609 1.1 christos zone->opts->name, ixfrfile, (unsigned)ixfr_data_size(data)));
2610 1.1 christos return 1;
2611 1.1 christos }
2612 1.1 christos
2613 1.1 christos /* try to read the next ixfr file. returns false if it fails or if it
2614 1.1 christos * does not fit in the configured sizes */
2615 1.1 christos static int ixfr_read_one_more_file(struct nsd* nsd, struct zone* zone,
2616 1.1 christos const char* zfile, int num_files, uint32_t *dest_serial)
2617 1.1 christos {
2618 1.1 christos char ixfrfile[1024+24];
2619 1.1 christos FILE* in;
2620 1.1 christos int file_num = num_files+1;
2621 1.1 christos make_ixfr_name(ixfrfile, sizeof(ixfrfile), zfile, file_num);
2622 1.1 christos in = fopen(ixfrfile, "r");
2623 1.1 christos if(!in) {
2624 1.1 christos if(errno == ENOENT) {
2625 1.1 christos /* the file does not exist, we reached the end
2626 1.1 christos * of the list of IXFR files */
2627 1.1 christos return 0;
2628 1.1 christos }
2629 1.1 christos log_msg(LOG_ERR, "could not read zone %s IXFR file %s: %s",
2630 1.1 christos zone->opts->name, ixfrfile, strerror(errno));
2631 1.1 christos return 0;
2632 1.1 christos }
2633 1.1 christos warn_if_directory("IXFR data", in, ixfrfile);
2634 1.1 christos if(!ixfr_data_read(nsd, zone, in, ixfrfile, dest_serial, file_num)) {
2635 1.1 christos fclose(in);
2636 1.1 christos return 0;
2637 1.1 christos }
2638 1.1 christos fclose(in);
2639 1.1 christos return 1;
2640 1.1 christos }
2641 1.1 christos
2642 1.1 christos void ixfr_read_from_file(struct nsd* nsd, struct zone* zone, const char* zfile)
2643 1.1 christos {
2644 1.1 christos uint32_t serial;
2645 1.1 christos int num_files = 0;
2646 1.1 christos /* delete the existing data, the zone data in memory has likely
2647 1.1 christos * changed, eg. due to reading a new zonefile. So that needs new
2648 1.1 christos * IXFRs */
2649 1.1 christos zone_ixfr_clear(zone->ixfr);
2650 1.1 christos
2651 1.1 christos /* track the serial number that we need to end up with, and check
2652 1.1 christos * that the IXFRs match up and result in the required version */
2653 1.1 christos serial = zone_get_current_serial(zone);
2654 1.1 christos
2655 1.1 christos while(ixfr_read_one_more_file(nsd, zone, zfile, num_files, &serial)) {
2656 1.1 christos num_files++;
2657 1.1 christos }
2658 1.1 christos if(num_files > 0) {
2659 1.1 christos VERBOSITY(1, (LOG_INFO, "zone %s read %d IXFR transfers with success",
2660 1.1 christos zone->opts->name, num_files));
2661 1.1 christos }
2662 1.1 christos }
2663