OpenDNSSEC-signer  1.4.1
ixfr.c
Go to the documentation of this file.
1 /*
2  * $Id: ixfr.c 5260 2011-06-28 14:13:14Z matthijs $
3  *
4  * Copyright (c) 2009 NLNet Labs. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in the
13  * documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
21  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
23  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
25  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
34 #include "config.h"
35 #include "shared/util.h"
36 #include "signer/ixfr.h"
37 #include "signer/rrset.h"
38 #include "signer/zone.h"
39 
40 static const char* ixfr_str = "journal";
41 
42 
47 static part_type*
48 part_create(allocator_type* allocator)
49 {
50  part_type* part = NULL;
51  ods_log_assert(allocator);
52 
53  part = (part_type*) allocator_alloc(allocator, sizeof(part_type));
54  if (!part) {
55  ods_log_error("[%s] unable to create ixfr part: "
56  "allocator_alloc() failed", ixfr_str);
57  return NULL;
58  }
59  part->soaplus = NULL;
60  part->soamin = NULL;
61  part->plus = ldns_rr_list_new();
62  if (!part->plus) {
63  ods_log_error("[%s] unable to create ixfr part: "
64  "ldns_rr_list_new() failed", ixfr_str);
65  allocator_deallocate(allocator, (void*) part);
66  return NULL;
67  }
68  part->min = ldns_rr_list_new();
69  if (!part->min) {
70  ods_log_error("[%s] unable to create ixfr part: "
71  "ldns_rr_list_new() failed", ixfr_str);
72  ldns_rr_list_free(part->plus);
73  allocator_deallocate(allocator, (void*) part);
74  return NULL;
75  }
76  return part;
77 }
78 
79 
84 static void
85 part_cleanup(allocator_type* allocator, part_type* part)
86 {
87  if (!part || !allocator) {
88  return;
89  }
90  ldns_rr_list_deep_free(part->min);
91  ldns_rr_list_free(part->plus);
92  allocator_deallocate(allocator, (void*) part);
93  return;
94 }
95 
96 
101 ixfr_type*
102 ixfr_create(void* zone)
103 {
104  size_t i = 0;
105  ixfr_type* xfr = NULL;
106  zone_type* z = (zone_type*) zone;
107 
108  ods_log_assert(z);
109  ods_log_assert(z->name);
111 
112  xfr = (ixfr_type*) allocator_alloc(z->allocator, sizeof(ixfr_type));
113  if (!xfr) {
114  ods_log_error("[%s] unable to create ixfr for zone %s: "
115  "allocator_alloc() failed", ixfr_str, z->name);
116  return NULL;
117  }
118  for (i=0; i < IXFR_MAX_PARTS; i++) {
119  xfr->part[i] = NULL;
120  }
121  xfr->zone = zone;
122  lock_basic_init(&xfr->ixfr_lock);
123  return xfr;
124 }
125 
126 
131 void
132 ixfr_add_rr(ixfr_type* ixfr, ldns_rr* rr)
133 {
134  zone_type* zone = NULL;
135  if (!ixfr || !rr) {
136  return;
137  }
138  zone = (zone_type*) ixfr->zone;
139  ods_log_assert(zone);
140  ods_log_assert(zone->db);
141  if (!zone->db->is_initialized) {
142  /* no ixfr yet */
143  return;
144  }
145  ods_log_assert(ixfr->part[0]);
146  ods_log_assert(ixfr->part[0]->plus);
147  if (!ldns_rr_list_push_rr(ixfr->part[0]->plus, rr)) {
148  ods_fatal_exit("[%s] fatal unable to +RR: ldns_rr_list_push_rr() failed",
149  ixfr_str);
150  }
151  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
152  ixfr->part[0]->soaplus = rr;
153  }
154  return;
155 }
156 
157 
162 void
163 ixfr_del_rr(ixfr_type* ixfr, ldns_rr* rr)
164 {
165  zone_type* zone = NULL;
166  if (!ixfr || !rr) {
167  return;
168  }
169  zone = (zone_type*) ixfr->zone;
170  ods_log_assert(zone);
171  ods_log_assert(zone->db);
172  if (!zone->db->is_initialized) {
173  /* no ixfr yet */
174  return;
175  }
176  ods_log_assert(ixfr->part[0]);
177  ods_log_assert(ixfr->part[0]->min);
178  if (!ldns_rr_list_push_rr(ixfr->part[0]->min, rr)) {
179  ods_fatal_exit("[%s] fatal unable to -RR: ldns_rr_list_push_rr() failed",
180  ixfr_str);
181  }
182  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
183  ixfr->part[0]->soamin = rr;
184  }
185  return;
186 }
187 
188 
193 static int
194 part_rr_list_print_nonsoa(FILE* fd, ldns_rr_list* list)
195 {
196  size_t i = 0;
197  int error = 0;
198  if (!list || !fd) {
199  return 1;
200  }
201  for (i = 0; i < ldns_rr_list_rr_count(list); i++) {
202  if (ldns_rr_get_type(ldns_rr_list_rr(list, i)) != LDNS_RR_TYPE_SOA) {
203  if (util_rr_print(fd, ldns_rr_list_rr(list, i)) != ODS_STATUS_OK) {
204  error = 1;
205  }
206  }
207  }
208  return error;
209 }
210 
211 
216 static void
217 part_print(FILE* fd, ixfr_type* ixfr, size_t i)
218 {
219  zone_type* zone = NULL;
220  part_type* part = NULL;
221  int error = 0;
222  if (!ixfr || !fd) {
223  return;
224  }
225  zone = (zone_type*) ixfr->zone;
226  part = ixfr->part[i];
227  if (!part) {
228  return;
229  }
230  ods_log_assert(part->min);
231  ods_log_assert(part->plus);
232  ods_log_assert(part->soamin);
233  ods_log_assert(part->soaplus);
234  if (util_rr_print(fd, part->soamin) != ODS_STATUS_OK) {
235  zone->adoutbound->error = 1;
236  }
237  error = part_rr_list_print_nonsoa(fd, part->min);
238  if (error) {
239  zone->adoutbound->error = 1;
240  }
241  if (util_rr_print(fd, part->soaplus) != ODS_STATUS_OK) {
242  zone->adoutbound->error = 1;
243  }
244  error = part_rr_list_print_nonsoa(fd, part->plus);
245  if (error) {
246  zone->adoutbound->error = 1;
247  }
248  return;
249 }
250 
251 
256 void
257 ixfr_print(FILE* fd, ixfr_type* ixfr)
258 {
259  int i = 0;
260  if (!ixfr || !fd) {
261  return;
262  }
263  ods_log_debug("[%s] print ixfr", ixfr_str);
264  for (i = IXFR_MAX_PARTS - 1; i >= 0; i--) {
265  ods_log_deeebug("[%s] print ixfr part #%d", ixfr_str, i);
266  part_print(fd, ixfr, i);
267  }
268  return;
269 }
270 
271 
276 void
278 {
279  int i = 0;
280  zone_type* zone = NULL;
281  if (!ixfr) {
282  return;
283  }
284  zone = (zone_type*) ixfr->zone;
285  ods_log_assert(zone);
286  ods_log_assert(zone->allocator);
287  ods_log_debug("[%s] purge ixfr for zone %s", ixfr_str, zone->name);
288  for (i = IXFR_MAX_PARTS - 1; i >= 0; i--) {
289  if (i == (IXFR_MAX_PARTS - 1)) {
290  part_cleanup(zone->allocator, ixfr->part[i]);
291  ixfr->part[i] = NULL;
292  } else {
293  ixfr->part[i+1] = ixfr->part[i];
294  ixfr->part[i] = NULL;
295  }
296  }
297  ixfr->part[0] = part_create(zone->allocator);
298  if (!ixfr->part[0]) {
299  ods_fatal_exit("[%s] fatal unable to purge ixfr for zone %s: "
300  "part_create() failed", ixfr_str, zone->name);
301  }
302  return;
303 }
304 
305 
310 void
312 {
313  int i = 0;
314  zone_type* z = NULL;
315  lock_basic_type ixfr_lock;
316  if (!ixfr) {
317  return;
318  }
319  z = (zone_type*) ixfr->zone;
320  ixfr_lock = ixfr->ixfr_lock;
321  for (i = IXFR_MAX_PARTS - 1; i >= 0; i--) {
322  part_cleanup(z->allocator, ixfr->part[i]);
323  }
324  allocator_deallocate(z->allocator, (void*) ixfr);
325  lock_basic_destroy(&ixfr_lock);
326  return;
327 }