OpenDNSSEC-signer  1.4.1
addns.c
Go to the documentation of this file.
1 /*
2  * $Id: addns.c 5237 2011-06-20 13:05:39Z 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 "adapter/adapi.h"
36 #include "adapter/adapter.h"
37 #include "adapter/addns.h"
38 #include "adapter/adutil.h"
39 #include "parser/addnsparser.h"
40 #include "parser/confparser.h"
41 #include "shared/duration.h"
42 #include "shared/file.h"
43 #include "shared/log.h"
44 #include "shared/status.h"
45 #include "shared/util.h"
46 #include "signer/zone.h"
47 #include "wire/notify.h"
48 #include "wire/xfrd.h"
49 
50 #include <ldns/ldns.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 
54 static const char* adapter_str = "adapter";
55 static ods_status addns_read_pkt(FILE* fd, zone_type* zone);
56 static ods_status addns_read_file(FILE* fd, zone_type* zone);
57 
58 
63 ldns_rr*
64 addns_read_rr(FILE* fd, char* line, ldns_rdf** orig, ldns_rdf** prev,
65  uint32_t* ttl, ldns_status* status, unsigned int* l)
66 {
67  ldns_rr* rr = NULL;
68  int len = 0;
69  uint32_t new_ttl = 0;
70 
71 addns_read_line:
72  if (ttl) {
73  new_ttl = *ttl;
74  }
75  len = adutil_readline_frm_file(fd, line, l, 1);
76  adutil_rtrim_line(line, &len);
77  if (len >= 0) {
78  switch (line[0]) {
79  /* no directives */
80 
81  /* comments, empty lines */
82  case ';':
83  case '\n':
84  if (ods_strcmp(";;ENDPACKET", line) == 0) {
85  /* end of pkt */
86  *status = LDNS_STATUS_OK;
87  return NULL;
88  }
89  if (ods_strcmp(";;BEGINPACKET", line) == 0) {
90  /* begin packet but previous not ended, rollback */
91  *status = LDNS_STATUS_OK;
92  return NULL;
93  }
94  goto addns_read_line; /* perhaps next line is rr */
95  break;
96  /* let's hope its a RR */
97  default:
98  if (adutil_whitespace_line(line, len)) {
99  goto addns_read_line; /* perhaps next line is rr */
100  break;
101  }
102  *status = ldns_rr_new_frm_str(&rr, line, new_ttl, *orig, prev);
103  if (*status == LDNS_STATUS_OK) {
104  return rr;
105  } else if (*status == LDNS_STATUS_SYNTAX_EMPTY) {
106  if (rr) {
107  ldns_rr_free(rr);
108  rr = NULL;
109  }
110  *status = LDNS_STATUS_OK;
111  goto addns_read_line; /* perhaps next line is rr */
112  break;
113  } else {
114  ods_log_error("[%s] error parsing RR at line %i (%s): %s",
115  adapter_str, l&&*l?*l:0,
116  ldns_get_errorstr_by_id(*status), line);
117  while (len >= 0) {
118  len = adutil_readline_frm_file(fd, line, l, 0);
119  }
120  if (rr) {
121  ldns_rr_free(rr);
122  rr = NULL;
123  }
124  return NULL;
125  }
126  break;
127  }
128  }
129  /* -1, unexpected EOF */
130  *status = LDNS_STATUS_ERR;
131  return NULL;
132 }
133 
134 
139 static ods_status
140 addns_read_pkt(FILE* fd, zone_type* zone)
141 {
142  ldns_rr* rr = NULL;
143  int len = 0;
144  uint32_t new_serial = 0;
145  uint32_t old_serial = 0;
146  uint32_t tmp_serial = 0;
147  ldns_rdf* prev = NULL;
148  ldns_rdf* orig = NULL;
149  ldns_rdf* dname = NULL;
150  uint32_t ttl = 0;
151  size_t rr_count = 0;
152  ods_status result = ODS_STATUS_OK;
153  ldns_status status = LDNS_STATUS_OK;
154  char line[SE_ADFILE_MAXLINE];
155  unsigned is_axfr = 0;
156  unsigned del_mode = 0;
157  unsigned soa_seen = 0;
158  unsigned line_update_interval = 100000;
159  unsigned line_update = line_update_interval;
160  unsigned l = 0;
161 
162  ods_log_assert(fd);
163  ods_log_assert(zone);
164  ods_log_assert(zone->name);
165 
166  len = adutil_readline_frm_file(fd, line, &l, 1);
167  if (len < 0) {
168  /* -1 EOF */
169  return ODS_STATUS_EOF;
170  }
171  adutil_rtrim_line(line, &len);
172  if (ods_strcmp(";;BEGINPACKET", line) != 0) {
173  ods_log_error("[%s] bogus xfrd file zone %s, missing ;;BEGINPACKET (was %s)",
174  adapter_str, zone->name, line);
175  return ODS_STATUS_ERR;
176  }
177 
178 begin_pkt:
179  rr_count = 0;
180  is_axfr = 0;
181  del_mode = 0;
182  soa_seen = 0;
183  /* $ORIGIN <zone name> */
184  dname = adapi_get_origin(zone);
185  if (!dname) {
186  ods_log_error("[%s] error getting default value for $ORIGIN",
187  adapter_str);
188  return ODS_STATUS_ERR;
189  }
190  orig = ldns_rdf_clone(dname);
191  if (!orig) {
192  ods_log_error("[%s] error setting default value for $ORIGIN",
193  adapter_str);
194  return ODS_STATUS_ERR;
195  }
196  /* $TTL <default ttl> */
197  ttl = adapi_get_ttl(zone);
198 
199  /* read RRs */
200  while ((rr = addns_read_rr(fd, line, &orig, &prev, &ttl, &status, &l))
201  != NULL) {
202  /* check status */
203  if (status != LDNS_STATUS_OK) {
204  ods_log_error("[%s] error reading RR at line %i (%s): %s",
205  adapter_str, l, ldns_get_errorstr_by_id(status), line);
206  result = ODS_STATUS_ERR;
207  break;
208  }
209  /* debug update */
210  if (l > line_update) {
211  ods_log_debug("[%s] ...at line %i: %s", adapter_str, l, line);
212  line_update += line_update_interval;
213  }
214  /* first RR: check if SOA and correct zone & serialno */
215  if (rr_count == 0) {
216  rr_count++;
217  if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_SOA) {
218  ods_log_error("[%s] bad xfr, first rr is not soa",
219  adapter_str);
220  ldns_rr_free(rr);
221  rr = NULL;
222  result = ODS_STATUS_ERR;
223  break;
224  }
225  soa_seen++;
226  if (ldns_dname_compare(ldns_rr_owner(rr), zone->apex)) {
227  ods_log_error("[%s] bad xfr, soa dname not equal to zone "
228  "dname %s", adapter_str, zone->name);
229  ldns_rr_free(rr);
230  rr = NULL;
231  result = ODS_STATUS_ERR;
232  break;
233  }
234  tmp_serial =
235  ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
236  old_serial = adapi_get_serial(zone);
237  if (!util_serial_gt(tmp_serial, old_serial)) {
238  ods_log_info("[%s] zone %s is already up to date, have "
239  "serial %u, got serial %u", adapter_str, zone->name,
240  old_serial, tmp_serial);
241  new_serial = tmp_serial;
242  ldns_rr_free(rr);
243  rr = NULL;
244  result = ODS_STATUS_UPTODATE;
245  while (len >= 0) {
246  len = adutil_readline_frm_file(fd, line, &l, 1);
247  if (len && ods_strcmp(";;ENDPACKET", line) == 0) {
248  /* end of pkt */
249  break;
250  }
251  }
252  break;
253  }
254  ldns_rr_free(rr);
255  rr = NULL;
256  result = ODS_STATUS_OK;
257  continue;
258  }
259  /* second RR: if not soa, this is an AXFR */
260  if (rr_count == 1) {
261  if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_SOA) {
262  ods_log_verbose("[%s] detected axfr serial=%u for zone %s",
263  adapter_str, tmp_serial, zone->name);
264  new_serial = tmp_serial;
265  is_axfr = 1;
266  del_mode = 0;
267  } else {
268  ods_log_verbose("[%s] detected ixfr serial=%u for zone %s",
269  adapter_str, tmp_serial, zone->name);
270  new_serial = tmp_serial;
271  tmp_serial =
272  ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
273  ldns_rr_free(rr);
274  rr = NULL;
275  rr_count++;
276  if (tmp_serial < new_serial) {
277  del_mode = 1;
278  result = ODS_STATUS_OK;
279  continue;
280  } else {
281  ods_log_error("[%s] bad xfr for zone %s, bad soa serial",
282  adapter_str, zone->name);
283  result = ODS_STATUS_ERR;
284  break;
285  }
286  }
287  }
288  /* soa means swap */
289  rr_count++;
290  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
291  if (!is_axfr) {
292  tmp_serial =
293  ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
294  if (tmp_serial <= new_serial) {
295  if (tmp_serial == new_serial) {
296  soa_seen++;
297  }
298  del_mode = !del_mode;
299  ldns_rr_free(rr);
300  rr = NULL;
301  result = ODS_STATUS_OK;
302  continue;
303  } else {
304  ods_log_assert(tmp_serial > new_serial);
305  ods_log_error("[%s] bad xfr for zone %s, bad soa serial",
306  adapter_str, zone->name);
307  ldns_rr_free(rr);
308  rr = NULL;
309  result = ODS_STATUS_ERR;
310  break;
311  }
312  } else {
313  /* for axfr */
314  soa_seen++;
315  }
316  }
317  /* [add to/remove from] the zone */
318  if (!is_axfr && del_mode) {
319  ods_log_deeebug("[%s] delete RR #%i at line %i: %s",
320  adapter_str, rr_count, l, line);
321  result = adapi_del_rr(zone, rr, 0);
322  ldns_rr_free(rr);
323  rr = NULL;
324  } else {
325  ods_log_deeebug("[%s] add RR #%i at line %i: %s",
326  adapter_str, rr_count, l, line);
327  result = adapi_add_rr(zone, rr, 0);
328  }
329  if (result == ODS_STATUS_UNCHANGED) {
330  ods_log_debug("[%s] skipping RR at line %i (%s): %s",
331  adapter_str, l, del_mode?"not found":"duplicate", line);
332  ldns_rr_free(rr);
333  rr = NULL;
334  result = ODS_STATUS_OK;
335  continue;
336  } else if (result != ODS_STATUS_OK) {
337  ods_log_error("[%s] error %s RR at line %i: %s",
338  adapter_str, del_mode?"deleting":"adding", l, line);
339  ldns_rr_free(rr);
340  rr = NULL;
341  break;
342  }
343  }
344  /* and done */
345  if (orig) {
346  ldns_rdf_deep_free(orig);
347  orig = NULL;
348  }
349  if (prev) {
350  ldns_rdf_deep_free(prev);
351  prev = NULL;
352  }
353  /* check again */
354  if (ods_strcmp(";;BEGINPACKET", line) == 0) {
355  ods_log_warning("[%s] xfr zone %s on disk incomplete, rollback",
356  adapter_str, zone->name);
357  namedb_rollback(zone->db, 1);
358  result = ODS_STATUS_OK;
359  goto begin_pkt;
360  } else {
361  ods_log_verbose("[%s] xfr zone %s on disk complete, commit to db",
362  adapter_str, zone->name);
363  }
364  /* otherwise ENDPACKET or EOF */
365  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
366  ods_log_error("[%s] error reading RR at line %i (%s): %s",
367  adapter_str, l, ldns_get_errorstr_by_id(status), line);
368  result = ODS_STATUS_ERR;
369  }
370  /* check the number of SOAs seen */
371  if (result == ODS_STATUS_OK) {
372  if ((is_axfr && soa_seen != 2) || (!is_axfr && soa_seen != 3)) {
373  ods_log_error("[%s] bad %s, wrong number of SOAs (%u)",
374  adapter_str, is_axfr?"axfr":"ixfr", soa_seen);
375  result = ODS_STATUS_ERR;
376  }
377  }
378  /* input zone ok, set inbound serial and apply differences */
379  if (result == ODS_STATUS_OK) {
380  adapi_set_serial(zone, new_serial);
381  if (is_axfr) {
382  adapi_trans_full(zone, 1);
383  } else {
384  adapi_trans_diff(zone, 1);
385  }
386  }
387  if (result == ODS_STATUS_UPTODATE) {
388  /* do a transaction for DNSKEY and NSEC3PARAM */
389  adapi_trans_diff(zone, 1);
390  result = ODS_STATUS_OK;
391  }
392  return result;
393 }
394 
395 
400 static ods_status
401 addns_read_file(FILE* fd, zone_type* zone)
402 {
403  ods_status status = ODS_STATUS_OK;
404 
405  while (status == ODS_STATUS_OK) {
406  status = addns_read_pkt(fd, zone);
407  }
408  if (status == ODS_STATUS_EOF) {
409  status = ODS_STATUS_OK;
410  }
411  return status;
412 }
413 
414 
419 dnsin_type*
421 {
422  dnsin_type* addns = NULL;
423  allocator_type* allocator = allocator_create(malloc, free);
424  if (!allocator) {
425  ods_log_error("[%s] unable to create dnsin: allocator_create() "
426  " failed", adapter_str);
427  return NULL;
428  }
429  addns = (dnsin_type*) allocator_alloc(allocator, sizeof(dnsin_type));
430  if (!addns) {
431  ods_log_error("[%s] unable to create dnsin: allocator_alloc() "
432  " failed", adapter_str);
433  allocator_cleanup(allocator);
434  return NULL;
435  }
436  addns->allocator = allocator;
437  addns->request_xfr = NULL;
438  addns->allow_notify = NULL;
439  addns->tsig = NULL;
440  return addns;
441 }
442 
443 
450 {
451  dnsout_type* addns = NULL;
452  allocator_type* allocator = allocator_create(malloc, free);
453  if (!allocator) {
454  ods_log_error("[%s] unable to create dnsout: allocator_create() "
455  " failed", adapter_str);
456  return NULL;
457  }
458  addns = (dnsout_type*) allocator_alloc(allocator, sizeof(dnsout_type));
459  if (!addns) {
460  ods_log_error("[%s] unable to create dnsout: allocator_alloc() "
461  " failed", adapter_str);
462  allocator_cleanup(allocator);
463  return NULL;
464  }
465  addns->allocator = allocator;
466  addns->provide_xfr = NULL;
467  addns->do_notify = NULL;
468  addns->tsig = NULL;
469  return addns;
470 }
471 
472 
477 static ods_status
478 dnsin_read(dnsin_type* addns, const char* filename)
479 {
480  const char* rngfile = ODS_SE_RNGDIR "/addns.rng";
481  ods_status status = ODS_STATUS_OK;
482  FILE* fd = NULL;
483  if (!filename || !addns) {
484  return ODS_STATUS_ASSERT_ERR;
485  }
486  ods_log_debug("[%s] read dnsin file %s", adapter_str, filename);
487  status = parse_file_check(filename, rngfile);
488  if (status != ODS_STATUS_OK) {
489  ods_log_error("[%s] unable to read dnsin: parse error in "
490  "file %s (%s)", adapter_str, filename, ods_status2str(status));
491  return status;
492  }
493  fd = ods_fopen(filename, NULL, "r");
494  if (fd) {
495  addns->tsig = parse_addns_tsig(addns->allocator, filename);
497  filename, addns->tsig);
499  filename, addns->tsig);
500  ods_fclose(fd);
501  return ODS_STATUS_OK;
502  }
503  ods_log_error("[%s] unable to read dnsout: failed to open file %s",
504  adapter_str, filename);
505  return ODS_STATUS_ERR;
506 }
507 
508 
514 dnsin_update(dnsin_type** addns, const char* filename, time_t* last_mod)
515 {
516  dnsin_type* new_addns = NULL;
517  time_t st_mtime = 0;
518  ods_status status = ODS_STATUS_OK;
519 
520  if (!filename || !addns || !last_mod) {
521  return ODS_STATUS_UNCHANGED;
522  }
523  /* read the new signer configuration */
524  new_addns = dnsin_create();
525  if (!new_addns) {
526  ods_log_error("[%s] unable to update dnsin: dnsin_create() "
527  "failed", adapter_str);
528  return ODS_STATUS_ERR;
529  }
530  status = dnsin_read(new_addns, filename);
531  if (status == ODS_STATUS_OK) {
532  *addns = new_addns;
533  *last_mod = st_mtime;
534  } else {
535  ods_log_error("[%s] unable to update dnsin: dnsin_read(%s) "
536  "failed (%s)", adapter_str, filename, ods_status2str(status));
537  dnsin_cleanup(new_addns);
538  }
539  return status;
540 }
541 
546 static ods_status
547 dnsout_read(dnsout_type* addns, const char* filename)
548 {
549  const char* rngfile = ODS_SE_RNGDIR "/addns.rng";
550  ods_status status = ODS_STATUS_OK;
551  FILE* fd = NULL;
552  if (!filename || !addns) {
553  return ODS_STATUS_ASSERT_ERR;
554  }
555  ods_log_debug("[%s] read dnsout file %s", adapter_str, filename);
556  status = parse_file_check(filename, rngfile);
557  if (status != ODS_STATUS_OK) {
558  ods_log_error("[%s] unable to read dnsout: parse error in "
559  "file %s (%s)", adapter_str, filename, ods_status2str(status));
560  return status;
561  }
562  fd = ods_fopen(filename, NULL, "r");
563  if (fd) {
564  addns->tsig = parse_addns_tsig(addns->allocator, filename);
566  filename, addns->tsig);
567  addns->do_notify = parse_addns_do_notify(addns->allocator, filename,
568  addns->tsig);
569  ods_fclose(fd);
570  return ODS_STATUS_OK;
571  }
572  ods_log_error("[%s] unable to read dnsout: failed to open file %s",
573  adapter_str, filename);
574  return ODS_STATUS_ERR;
575 }
576 
577 
583 dnsout_update(dnsout_type** addns, const char* filename, time_t* last_mod)
584 {
585  dnsout_type* new_addns = NULL;
586  time_t st_mtime = 0;
587  ods_status status = ODS_STATUS_OK;
588 
589  if (!filename || !addns || !last_mod) {
590  return ODS_STATUS_UNCHANGED;
591  }
592  /* read the new signer configuration */
593  new_addns = dnsout_create();
594  if (!new_addns) {
595  ods_log_error("[%s] unable to update dnsout: dnsout_create() "
596  "failed", adapter_str);
597  return ODS_STATUS_ERR;
598  }
599  status = dnsout_read(new_addns, filename);
600  if (status == ODS_STATUS_OK) {
601  *addns = new_addns;
602  *last_mod = st_mtime;
603  } else {
604  ods_log_error("[%s] unable to update dnsout: dnsout_read(%s) "
605  "failed (%s)", adapter_str, filename, ods_status2str(status));
606  dnsout_cleanup(new_addns);
607  }
608  return status;
609 }
610 
611 
616 static void
617 dnsout_send_notify(void* zone)
618 {
619  zone_type* z = (zone_type*) zone;
620  rrset_type* rrset = NULL;
621  ldns_rr* soa = NULL;
622  if (!z->notify) {
623  ods_log_error("[%s] unable to send notify for zone %s: no notify "
624  "handler", adapter_str, z->name);
625  return;
626  }
630  ods_log_assert(z->db);
631  ods_log_assert(z->name);
632  ods_log_debug("[%s] enable notify for zone %s serial %u", adapter_str,
633  z->name, z->db->intserial);
634  rrset = zone_lookup_rrset(z, z->apex, LDNS_RR_TYPE_SOA);
635  ods_log_assert(rrset);
636  soa = ldns_rr_clone(rrset->rrs[0].rr);
637  notify_enable(z->notify, soa);
638  return;
639 }
640 
641 
647 addns_read(void* zone)
648 {
649  zone_type* z = (zone_type*) zone;
650  ods_status status = ODS_STATUS_OK;
651  char* xfrfile = NULL;
652  char* file = NULL;
653  FILE* fd = NULL;
654  ods_log_assert(z);
655  ods_log_assert(z->name);
656  ods_log_assert(z->xfrd);
657  ods_log_assert(z->db);
660 
663  /* did we already store a new zone transfer on disk? */
664  if (!z->xfrd->serial_disk_acquired ||
668  if (!z->xfrd->serial_disk_acquired) {
670  }
671  /* do a transaction for DNSKEY and NSEC3PARAM */
672  adapi_trans_diff(z, 0);
673  return ODS_STATUS_UNCHANGED;
674  }
675  /* copy zone transfers */
676  xfrfile = ods_build_path(z->name, ".xfrd", 0, 1);
677  file = ods_build_path(z->name, ".xfrd.tmp", 0, 1);
678  if (!xfrfile || !file) {
679  ods_log_error("[%s] unable to build paths to xfrd files", adapter_str);
680  return ODS_STATUS_MALLOC_ERR;
681  }
682  if (rename(xfrfile, file) != 0) {
685  ods_log_error("[%s] unable to rename file %s to %s: %s", adapter_str,
686  xfrfile, file, strerror(errno));
687  free((void*) xfrfile);
688  free((void*) file);
689  return ODS_STATUS_RENAME_ERR;
690  }
692  /* open copy of zone transfers to read */
693  fd = ods_fopen(file, NULL, "r");
694  free((void*) xfrfile);
695  if (!fd) {
697  free((void*) file);
698  return ODS_STATUS_FOPEN_ERR;
699  }
700 
701  status = addns_read_file(fd, z);
702  if (status == ODS_STATUS_OK) {
707  /* clean up copy of zone transfer */
708  if (unlink((const char*) file) != 0) {
709  ods_log_error("[%s] unable to unlink zone transfer copy file %s: "
710  " %s", adapter_str, strerror(errno));
711  /* should be no issue */
712  }
713  }
714  free((void*) file);
715  ods_fclose(fd);
717  return status;
718 }
719 
720 
726 addns_write(void* zone)
727 {
728  FILE* fd = NULL;
729  char* atmpfile = NULL;
730  char* axfrfile = NULL;
731  char* itmpfile = NULL;
732  char* ixfrfile = NULL;
733  zone_type* z = (zone_type*) zone;
734  int ret = 0;
735  ods_status status = ODS_STATUS_OK;
736  ods_log_assert(z);
737  ods_log_assert(z->name);
740 
741  atmpfile = ods_build_path(z->name, ".axfr.tmp", 0, 1);
742  if (!atmpfile) {
743  return ODS_STATUS_MALLOC_ERR;
744  }
745  fd = ods_fopen(atmpfile, NULL, "w");
746  if (!fd) {
747  free((void*) atmpfile);
748  return ODS_STATUS_FOPEN_ERR;
749  }
750  status = adapi_printaxfr(fd, z);
751  ods_fclose(fd);
752  if (status != ODS_STATUS_OK) {
753  free((void*) atmpfile);
754  return status;
755  }
756 
757  if (z->db->is_initialized) {
758  itmpfile = ods_build_path(z->name, ".ixfr.tmp", 0, 1);
759  if (!itmpfile) {
760  free((void*) atmpfile);
761  return ODS_STATUS_MALLOC_ERR;
762  }
763  fd = ods_fopen(itmpfile, NULL, "w");
764  if (!fd) {
765  free((void*) atmpfile);
766  free((void*) itmpfile);
767  return ODS_STATUS_FOPEN_ERR;
768  }
769  status = adapi_printixfr(fd, z);
770  ods_fclose(fd);
771  if (status != ODS_STATUS_OK) {
772  free((void*) atmpfile);
773  free((void*) itmpfile);
774  return status;
775  }
776  }
777 
778  if (status == ODS_STATUS_OK) {
779  if (z->adoutbound->error) {
780  ods_log_error("[%s] unable to write zone %s axfr: one or "
781  "more RR print failed", adapter_str, z->name);
782  /* clear error */
783  z->adoutbound->error = 0;
784  free((void*) atmpfile);
785  free((void*) itmpfile);
786  return ODS_STATUS_FWRITE_ERR;
787  }
788  }
789 
790  /* lock and move */
791  axfrfile = ods_build_path(z->name, ".axfr", 0, 1);
792  if (!axfrfile) {
793  free((void*) atmpfile);
794  free((void*) itmpfile);
795  return ODS_STATUS_MALLOC_ERR;
796  }
797 
799  ret = rename(atmpfile, axfrfile);
800  if (ret != 0) {
801  ods_log_error("[%s] unable to rename file %s to %s: %s", adapter_str,
802  atmpfile, axfrfile, strerror(errno));
804  free((void*) atmpfile);
805  free((void*) axfrfile);
806  free((void*) itmpfile);
807  return ODS_STATUS_RENAME_ERR;
808  }
809  free((void*) axfrfile);
810  free((void*) atmpfile);
811 
812  if (z->db->is_initialized) {
813  ixfrfile = ods_build_path(z->name, ".ixfr", 0, 1);
814  if (!ixfrfile) {
815  free((void*) axfrfile);
816  free((void*) atmpfile);
817  free((void*) itmpfile);
818  return ODS_STATUS_MALLOC_ERR;
819  }
820  ret = rename(itmpfile, ixfrfile);
821  if (ret != 0) {
822  ods_log_error("[%s] unable to rename file %s to %s: %s",
823  adapter_str, itmpfile, ixfrfile, strerror(errno));
825  free((void*) itmpfile);
826  free((void*) ixfrfile);
827  return ODS_STATUS_RENAME_ERR;
828  }
829  free((void*) ixfrfile);
830  }
831  free((void*) itmpfile);
833 
834  dnsout_send_notify(zone);
835  return ODS_STATUS_OK;
836 }
837 
838 
843 void
845 {
846  allocator_type* allocator = NULL;
847  if (!addns) {
848  return;
849  }
850  allocator = addns->allocator;
851  acl_cleanup(addns->request_xfr, allocator);
852  acl_cleanup(addns->allow_notify, allocator);
853  tsig_cleanup(addns->tsig, allocator);
854  allocator_deallocate(allocator, (void*) addns);
855  allocator_cleanup(allocator);
856  return;
857 }
858 
859 
864 void
866 {
867  allocator_type* allocator = NULL;
868  if (!addns) {
869  return;
870  }
871  allocator = addns->allocator;
872  acl_cleanup(addns->provide_xfr, allocator);
873  acl_cleanup(addns->do_notify, allocator);
874  tsig_cleanup(addns->tsig, allocator);
875  allocator_deallocate(allocator, (void*) addns);
876  allocator_cleanup(allocator);
877  return;
878 }