OpenDNSSEC-signer  1.4.5
addns.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2009 NLNet Labs. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
19  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
21  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
23  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
32 #include "config.h"
33 #include "adapter/adapi.h"
34 #include "adapter/adapter.h"
35 #include "adapter/addns.h"
36 #include "adapter/adutil.h"
37 #include "parser/addnsparser.h"
38 #include "parser/confparser.h"
39 #include "shared/duration.h"
40 #include "shared/file.h"
41 #include "shared/log.h"
42 #include "shared/status.h"
43 #include "shared/util.h"
44 #include "signer/zone.h"
45 #include "wire/notify.h"
46 #include "wire/xfrd.h"
47 
48 #include <ldns/ldns.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 
52 static const char* adapter_str = "adapter";
53 static ods_status addns_read_pkt(FILE* fd, zone_type* zone);
54 static ods_status addns_read_file(FILE* fd, zone_type* zone);
55 
56 
61 ldns_rr*
62 addns_read_rr(FILE* fd, char* line, ldns_rdf** orig, ldns_rdf** prev,
63  uint32_t* ttl, ldns_status* status, unsigned int* l)
64 {
65  ldns_rr* rr = NULL;
66  int len = 0;
67  uint32_t new_ttl = 0;
68 
69 addns_read_line:
70  if (ttl) {
71  new_ttl = *ttl;
72  }
73  len = adutil_readline_frm_file(fd, line, l, 1);
74  adutil_rtrim_line(line, &len);
75  if (len >= 0) {
76  switch (line[0]) {
77  /* no directives */
78 
79  /* comments, empty lines */
80  case ';':
81  case '\n':
82  if (ods_strcmp(";;ENDPACKET", line) == 0) {
83  /* end of pkt */
84  *status = LDNS_STATUS_OK;
85  return NULL;
86  }
87  if (ods_strcmp(";;BEGINPACKET", line) == 0) {
88  /* begin packet but previous not ended, rollback */
89  *status = LDNS_STATUS_OK;
90  return NULL;
91  }
92  goto addns_read_line; /* perhaps next line is rr */
93  break;
94  /* let's hope its a RR */
95  default:
96  if (adutil_whitespace_line(line, len)) {
97  goto addns_read_line; /* perhaps next line is rr */
98  break;
99  }
100  *status = ldns_rr_new_frm_str(&rr, line, new_ttl, *orig, prev);
101  if (*status == LDNS_STATUS_OK) {
102  return rr;
103  } else if (*status == LDNS_STATUS_SYNTAX_EMPTY) {
104  if (rr) {
105  ldns_rr_free(rr);
106  rr = NULL;
107  }
108  *status = LDNS_STATUS_OK;
109  goto addns_read_line; /* perhaps next line is rr */
110  break;
111  } else {
112  ods_log_error("[%s] error parsing RR at line %i (%s): %s",
113  adapter_str, l&&*l?*l:0,
114  ldns_get_errorstr_by_id(*status), line);
115  while (len >= 0) {
116  len = adutil_readline_frm_file(fd, line, l, 0);
117  }
118  if (rr) {
119  ldns_rr_free(rr);
120  rr = NULL;
121  }
122  return NULL;
123  }
124  break;
125  }
126  }
127  /* -1, EOF */
128  *status = LDNS_STATUS_OK;
129  return NULL;
130 }
131 
132 
137 static ods_status
138 addns_read_pkt(FILE* fd, zone_type* zone)
139 {
140  ldns_rr* rr = NULL;
141  long startpos = 0;
142  long fpos = 0;
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  char* xfrd;
162  char* fin;
163  char* fout;
164 
165  ods_log_assert(fd);
166  ods_log_assert(zone);
167  ods_log_assert(zone->name);
168 
169 
170  fpos = ftell(fd);
171  len = adutil_readline_frm_file(fd, line, &l, 1);
172  if (len < 0) {
173  /* -1 EOF */
174  return ODS_STATUS_EOF;
175  }
176  adutil_rtrim_line(line, &len);
177  if (ods_strcmp(";;BEGINPACKET", line) != 0) {
178  ods_log_error("[%s] bogus xfrd file zone %s, missing ;;BEGINPACKET (was %s)",
179  adapter_str, zone->name, line);
180  return ODS_STATUS_ERR;
181  }
182  startpos = fpos;
183  fpos = ftell(fd);
184 
185 begin_pkt:
186  rr_count = 0;
187  is_axfr = 0;
188  del_mode = 0;
189  soa_seen = 0;
190  /* $ORIGIN <zone name> */
191  dname = adapi_get_origin(zone);
192  if (!dname) {
193  ods_log_error("[%s] error getting default value for $ORIGIN",
194  adapter_str);
195  return ODS_STATUS_ERR;
196  }
197  orig = ldns_rdf_clone(dname);
198  if (!orig) {
199  ods_log_error("[%s] error setting default value for $ORIGIN",
200  adapter_str);
201  return ODS_STATUS_ERR;
202  }
203  /* $TTL <default ttl> */
204  ttl = adapi_get_ttl(zone);
205 
206  /* read RRs */
207  while ((rr = addns_read_rr(fd, line, &orig, &prev, &ttl, &status, &l))
208  != NULL) {
209  /* update file position */
210  fpos = ftell(fd);
211  /* check status */
212  if (status != LDNS_STATUS_OK) {
213  ods_log_error("[%s] error reading RR at line %i (%s): %s",
214  adapter_str, l, ldns_get_errorstr_by_id(status), line);
215  result = ODS_STATUS_ERR;
216  break;
217  }
218  /* debug update */
219  if (l > line_update) {
220  ods_log_debug("[%s] ...at line %i: %s", adapter_str, l, line);
221  line_update += line_update_interval;
222  }
223  /* first RR: check if SOA and correct zone & serialno */
224  if (rr_count == 0) {
225  rr_count++;
226  if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_SOA) {
227  ods_log_error("[%s] bad xfr, first rr is not soa",
228  adapter_str);
229  ldns_rr_free(rr);
230  rr = NULL;
231  result = ODS_STATUS_ERR;
232  break;
233  }
234  soa_seen++;
235  if (ldns_dname_compare(ldns_rr_owner(rr), zone->apex)) {
236  ods_log_error("[%s] bad xfr, soa dname not equal to zone "
237  "dname %s", adapter_str, zone->name);
238  ldns_rr_free(rr);
239  rr = NULL;
240  result = ODS_STATUS_ERR;
241  break;
242  }
243  tmp_serial =
244  ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
245  old_serial = adapi_get_serial(zone);
246  if (!util_serial_gt(tmp_serial, old_serial)) {
247  ods_log_info("[%s] zone %s is already up to date, have "
248  "serial %u, got serial %u", adapter_str, zone->name,
249  old_serial, tmp_serial);
250  new_serial = tmp_serial;
251  ldns_rr_free(rr);
252  rr = NULL;
253  result = ODS_STATUS_UPTODATE;
254  while (len >= 0) {
255  len = adutil_readline_frm_file(fd, line, &l, 1);
256  if (len && ods_strcmp(";;ENDPACKET", line) == 0) {
257  /* end of pkt */
258  startpos = 0;
259  break;
260  }
261  }
262  break;
263  }
264  ldns_rr_free(rr);
265  rr = NULL;
266  result = ODS_STATUS_OK;
267  continue;
268  }
269  /* second RR: if not soa, this is an AXFR */
270  if (rr_count == 1) {
271  if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_SOA) {
272  ods_log_verbose("[%s] detected axfr serial=%u for zone %s",
273  adapter_str, tmp_serial, zone->name);
274  new_serial = tmp_serial;
275  is_axfr = 1;
276  del_mode = 0;
277  } else {
278  ods_log_verbose("[%s] detected ixfr serial=%u for zone %s",
279  adapter_str, tmp_serial, zone->name);
280  new_serial = tmp_serial;
281  tmp_serial =
282  ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
283  ldns_rr_free(rr);
284  rr = NULL;
285  rr_count++;
286  if (tmp_serial < new_serial) {
287  del_mode = 1;
288  result = ODS_STATUS_OK;
289  continue;
290  } else {
291  ods_log_error("[%s] bad xfr for zone %s, bad soa serial",
292  adapter_str, zone->name);
293  result = ODS_STATUS_ERR;
294  break;
295  }
296  }
297  }
298  /* soa means swap */
299  rr_count++;
300  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
301  if (!is_axfr) {
302  tmp_serial =
303  ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
304  if (tmp_serial <= new_serial) {
305  if (tmp_serial == new_serial) {
306  soa_seen++;
307  }
308  del_mode = !del_mode;
309  ldns_rr_free(rr);
310  rr = NULL;
311  result = ODS_STATUS_OK;
312  continue;
313  } else {
314  ods_log_assert(tmp_serial > new_serial);
315  ods_log_error("[%s] bad xfr for zone %s, bad soa serial",
316  adapter_str, zone->name);
317  ldns_rr_free(rr);
318  rr = NULL;
319  result = ODS_STATUS_ERR;
320  break;
321  }
322  } else {
323  /* for axfr */
324  soa_seen++;
325  }
326  }
327  /* [add to/remove from] the zone */
328  if (!is_axfr && del_mode) {
329  ods_log_deeebug("[%s] delete RR #%i at line %i: %s",
330  adapter_str, rr_count, l, line);
331  result = adapi_del_rr(zone, rr, 0);
332  ldns_rr_free(rr);
333  rr = NULL;
334  } else {
335  ods_log_deeebug("[%s] add RR #%i at line %i: %s",
336  adapter_str, rr_count, l, line);
337  result = adapi_add_rr(zone, rr, 0);
338  }
339  if (result == ODS_STATUS_UNCHANGED) {
340  ods_log_debug("[%s] skipping RR at line %i (%s): %s",
341  adapter_str, l, del_mode?"not found":"duplicate", line);
342  ldns_rr_free(rr);
343  rr = NULL;
344  result = ODS_STATUS_OK;
345  continue;
346  } else if (result != ODS_STATUS_OK) {
347  ods_log_error("[%s] error %s RR at line %i: %s",
348  adapter_str, del_mode?"deleting":"adding", l, line);
349  ldns_rr_free(rr);
350  rr = NULL;
351  break;
352  }
353  }
354  /* and done */
355  if (orig) {
356  ldns_rdf_deep_free(orig);
357  orig = NULL;
358  }
359  if (prev) {
360  ldns_rdf_deep_free(prev);
361  prev = NULL;
362  }
363  /* check again */
364  if (ods_strcmp(";;ENDPACKET", line) == 0) {
365  ods_log_verbose("[%s] xfr zone %s on disk complete, commit to db",
366  adapter_str, zone->name);
367  startpos = 0;
368  } else {
369  ods_log_warning("[%s] xfr zone %s on disk incomplete, rollback",
370  adapter_str, zone->name);
371  namedb_rollback(zone->db, 1);
372  if (ods_strcmp(";;BEGINPACKET", line) == 0) {
373  result = ODS_STATUS_OK;
374  startpos = fpos;
375  goto begin_pkt;
376  } else {
377  result = ODS_STATUS_XFRINCOMPLETE;
378  }
379  }
380  /* otherwise EOF */
381  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
382  ods_log_error("[%s] error reading RR at line %i (%s): %s",
383  adapter_str, l, ldns_get_errorstr_by_id(status), line);
384  result = ODS_STATUS_ERR;
385  }
386  /* check the number of SOAs seen */
387  if (result == ODS_STATUS_OK) {
388  if ((is_axfr && soa_seen != 2) || (!is_axfr && soa_seen != 3)) {
389  ods_log_error("[%s] bad %s, wrong number of SOAs (%u)",
390  adapter_str, is_axfr?"axfr":"ixfr", soa_seen);
391  result = ODS_STATUS_ERR;
392  }
393  }
394  /* input zone ok, set inbound serial and apply differences */
395  if (result == ODS_STATUS_OK) {
396  adapi_set_serial(zone, new_serial);
397  if (is_axfr) {
398  adapi_trans_full(zone, 1);
399  } else {
400  adapi_trans_diff(zone, 1);
401  }
402  }
403  if (result == ODS_STATUS_UPTODATE) {
404  /* do a transaction for DNSKEY and NSEC3PARAM */
405  adapi_trans_diff(zone, 1);
406  result = ODS_STATUS_OK;
407  }
408  if (result == ODS_STATUS_XFRINCOMPLETE) {
412  xfrd = ods_build_path(zone->name, ".xfrd", 0, 1);
413  fin = ods_build_path(zone->name, ".xfrd.tmp", 0, 1);
414  fout = ods_build_path(zone->name, ".xfrd.bak", 0, 1);
415  if (!xfrd || !fin || !fout) {
416  return ODS_STATUS_MALLOC_ERR;
417  }
418  ods_log_debug("[%s] restore xfrd zone %s xfrd %s fin %s fout %s",
419  adapter_str, zone->name, xfrd, fin, fout);
420  result = ods_file_copy(fin, fout, startpos, 0);
421  if (result != ODS_STATUS_OK) {
422  ods_log_crit("[%s] unable to restore incomple xfr zone %s: %s",
423  adapter_str, zone->name, ods_status2str(result));
424  } else {
425  lock_basic_lock(&zone->xfrd->rw_lock);
426  if (ods_file_lastmodified(xfrd)) {
427  result = ods_file_copy(xfrd, fout, 0, 1);
428  if (result != ODS_STATUS_OK) {
429  ods_log_crit("[%s] unable to restore xfrd zone %s: %s",
430  adapter_str, zone->name, ods_status2str(result));
431  } else if (rename(fout, xfrd) != 0) {
432  result = ODS_STATUS_RENAME_ERR;
433  ods_log_crit("[%s] unable to restore xfrd zone %s: %s",
434  adapter_str, zone->name, ods_status2str(result));
435  }
436  } else if (rename(fout, xfrd) != 0) {
437  result = ODS_STATUS_RENAME_ERR;
438  ods_log_crit("[%s] unable to restore xfrd zone %s: %s",
439  adapter_str, zone->name, ods_status2str(result));
440 
441  }
442  lock_basic_unlock(&zone->xfrd->rw_lock);
443  }
444  free((void*) xfrd);
445  free((void*) fin);
446  free((void*) fout);
447  result = ODS_STATUS_XFRINCOMPLETE;
448  }
449  return result;
450 }
451 
452 
457 static ods_status
458 addns_read_file(FILE* fd, zone_type* zone)
459 {
460  ods_status status = ODS_STATUS_OK;
461 
462  while (status == ODS_STATUS_OK) {
463  status = addns_read_pkt(fd, zone);
464  if (status == ODS_STATUS_OK) {
466  zone->xfrd->serial_xfr = adapi_get_serial(zone);
469  }
470  }
471  if (status == ODS_STATUS_EOF) {
472  status = ODS_STATUS_OK;
473  }
474  return status;
475 }
476 
477 
482 dnsin_type*
484 {
485  dnsin_type* addns = NULL;
486  allocator_type* allocator = allocator_create(malloc, free);
487  if (!allocator) {
488  ods_log_error("[%s] unable to create dnsin: allocator_create() "
489  " failed", adapter_str);
490  return NULL;
491  }
492  addns = (dnsin_type*) allocator_alloc(allocator, sizeof(dnsin_type));
493  if (!addns) {
494  ods_log_error("[%s] unable to create dnsin: allocator_alloc() "
495  " failed", adapter_str);
496  allocator_cleanup(allocator);
497  return NULL;
498  }
499  addns->allocator = allocator;
500  addns->request_xfr = NULL;
501  addns->allow_notify = NULL;
502  addns->tsig = NULL;
503  return addns;
504 }
505 
506 
513 {
514  dnsout_type* addns = NULL;
515  allocator_type* allocator = allocator_create(malloc, free);
516  if (!allocator) {
517  ods_log_error("[%s] unable to create dnsout: allocator_create() "
518  " failed", adapter_str);
519  return NULL;
520  }
521  addns = (dnsout_type*) allocator_alloc(allocator, sizeof(dnsout_type));
522  if (!addns) {
523  ods_log_error("[%s] unable to create dnsout: allocator_alloc() "
524  " failed", adapter_str);
525  allocator_cleanup(allocator);
526  return NULL;
527  }
528  addns->allocator = allocator;
529  addns->provide_xfr = NULL;
530  addns->do_notify = NULL;
531  addns->tsig = NULL;
532  return addns;
533 }
534 
535 
540 static ods_status
541 dnsin_read(dnsin_type* addns, const char* filename)
542 {
543  const char* rngfile = ODS_SE_RNGDIR "/addns.rng";
544  ods_status status = ODS_STATUS_OK;
545  FILE* fd = NULL;
546  if (!filename || !addns) {
547  return ODS_STATUS_ASSERT_ERR;
548  }
549  ods_log_debug("[%s] read dnsin file %s", adapter_str, filename);
550  status = parse_file_check(filename, rngfile);
551  if (status != ODS_STATUS_OK) {
552  ods_log_error("[%s] unable to read dnsin: parse error in "
553  "file %s (%s)", adapter_str, filename, ods_status2str(status));
554  return status;
555  }
556  fd = ods_fopen(filename, NULL, "r");
557  if (fd) {
558  addns->tsig = parse_addns_tsig(addns->allocator, filename);
560  filename, addns->tsig);
562  filename, addns->tsig);
563  ods_fclose(fd);
564  return ODS_STATUS_OK;
565  }
566  ods_log_error("[%s] unable to read dnsout: failed to open file %s",
567  adapter_str, filename);
568  return ODS_STATUS_ERR;
569 }
570 
571 
577 dnsin_update(dnsin_type** addns, const char* filename, time_t* last_mod)
578 {
579  dnsin_type* new_addns = NULL;
580  time_t st_mtime = 0;
581  ods_status status = ODS_STATUS_OK;
582 
583  if (!filename || !addns || !last_mod) {
584  return ODS_STATUS_UNCHANGED;
585  }
586  /* read the new signer configuration */
587  new_addns = dnsin_create();
588  if (!new_addns) {
589  ods_log_error("[%s] unable to update dnsin: dnsin_create() "
590  "failed", adapter_str);
591  return ODS_STATUS_ERR;
592  }
593  status = dnsin_read(new_addns, filename);
594  if (status == ODS_STATUS_OK) {
595  *addns = new_addns;
596  *last_mod = st_mtime;
597  } else {
598  ods_log_error("[%s] unable to update dnsin: dnsin_read(%s) "
599  "failed (%s)", adapter_str, filename, ods_status2str(status));
600  dnsin_cleanup(new_addns);
601  }
602  return status;
603 }
604 
609 static ods_status
610 dnsout_read(dnsout_type* addns, const char* filename)
611 {
612  const char* rngfile = ODS_SE_RNGDIR "/addns.rng";
613  ods_status status = ODS_STATUS_OK;
614  FILE* fd = NULL;
615  if (!filename || !addns) {
616  return ODS_STATUS_ASSERT_ERR;
617  }
618  ods_log_debug("[%s] read dnsout file %s", adapter_str, filename);
619  status = parse_file_check(filename, rngfile);
620  if (status != ODS_STATUS_OK) {
621  ods_log_error("[%s] unable to read dnsout: parse error in "
622  "file %s (%s)", adapter_str, filename, ods_status2str(status));
623  return status;
624  }
625  fd = ods_fopen(filename, NULL, "r");
626  if (fd) {
627  addns->tsig = parse_addns_tsig(addns->allocator, filename);
629  filename, addns->tsig);
630  addns->do_notify = parse_addns_do_notify(addns->allocator, filename,
631  addns->tsig);
632  ods_fclose(fd);
633  return ODS_STATUS_OK;
634  }
635  ods_log_error("[%s] unable to read dnsout: failed to open file %s",
636  adapter_str, filename);
637  return ODS_STATUS_ERR;
638 }
639 
640 
646 dnsout_update(dnsout_type** addns, const char* filename, time_t* last_mod)
647 {
648  dnsout_type* new_addns = NULL;
649  time_t st_mtime = 0;
650  ods_status status = ODS_STATUS_OK;
651 
652  if (!filename || !addns || !last_mod) {
653  return ODS_STATUS_UNCHANGED;
654  }
655  /* read the new signer configuration */
656  new_addns = dnsout_create();
657  if (!new_addns) {
658  ods_log_error("[%s] unable to update dnsout: dnsout_create() "
659  "failed", adapter_str);
660  return ODS_STATUS_ERR;
661  }
662  status = dnsout_read(new_addns, filename);
663  if (status == ODS_STATUS_OK) {
664  *addns = new_addns;
665  *last_mod = st_mtime;
666  } else {
667  ods_log_error("[%s] unable to update dnsout: dnsout_read(%s) "
668  "failed (%s)", adapter_str, filename, ods_status2str(status));
669  dnsout_cleanup(new_addns);
670  }
671  return status;
672 }
673 
674 
679 static void
680 dnsout_send_notify(void* zone)
681 {
682  zone_type* z = (zone_type*) zone;
683  rrset_type* rrset = NULL;
684  ldns_rr* soa = NULL;
685  if (!z->notify) {
686  ods_log_error("[%s] unable to send notify for zone %s: no notify "
687  "handler", adapter_str, z->name);
688  return;
689  }
693  ods_log_assert(z->db);
694  ods_log_assert(z->name);
695  ods_log_debug("[%s] enable notify for zone %s serial %u", adapter_str,
696  z->name, z->db->intserial);
697  rrset = zone_lookup_rrset(z, z->apex, LDNS_RR_TYPE_SOA);
698  ods_log_assert(rrset);
699  soa = ldns_rr_clone(rrset->rrs[0].rr);
700  notify_enable(z->notify, soa);
701  return;
702 }
703 
704 
710 addns_read(void* zone)
711 {
712  zone_type* z = (zone_type*) zone;
713  ods_status status = ODS_STATUS_OK;
714  char* xfrfile = NULL;
715  char* file = NULL;
716  FILE* fd = NULL;
717  ods_log_assert(z);
718  ods_log_assert(z->name);
719  ods_log_assert(z->xfrd);
720  ods_log_assert(z->db);
723 
726  /* did we already store a new zone transfer on disk? */
727  if (!z->xfrd->serial_disk_acquired ||
731  if (!z->xfrd->serial_disk_acquired) {
733  }
734  /* do a transaction for DNSKEY and NSEC3PARAM */
735  adapi_trans_diff(z, 0);
736  return ODS_STATUS_UNCHANGED;
737  }
738  /* copy zone transfers */
739  xfrfile = ods_build_path(z->name, ".xfrd", 0, 1);
740  file = ods_build_path(z->name, ".xfrd.tmp", 0, 1);
741  if (!xfrfile || !file) {
742  ods_log_error("[%s] unable to build paths to xfrd files", adapter_str);
743  return ODS_STATUS_MALLOC_ERR;
744  }
745  if (rename(xfrfile, file) != 0) {
748  ods_log_error("[%s] unable to rename file %s to %s: %s", adapter_str,
749  xfrfile, file, strerror(errno));
750  free((void*) xfrfile);
751  free((void*) file);
752  return ODS_STATUS_RENAME_ERR;
753  }
755  /* open copy of zone transfers to read */
756  fd = ods_fopen(file, NULL, "r");
757  free((void*) xfrfile);
758  if (!fd) {
760  free((void*) file);
761  return ODS_STATUS_FOPEN_ERR;
762  }
764 
765  status = addns_read_file(fd, z);
766  if (status == ODS_STATUS_OK) {
767  /* clean up copy of zone transfer */
768  if (unlink((const char*) file) != 0) {
769  ods_log_error("[%s] unable to unlink zone transfer copy file %s: "
770  " %s", adapter_str, strerror(errno));
771  /* should be no issue */
772  }
773  }
774  free((void*) file);
775  ods_fclose(fd);
776  return status;
777 }
778 
779 
785 addns_write(void* zone)
786 {
787  FILE* fd = NULL;
788  char* atmpfile = NULL;
789  char* axfrfile = NULL;
790  char* itmpfile = NULL;
791  char* ixfrfile = NULL;
792  zone_type* z = (zone_type*) zone;
793  int ret = 0;
794  ods_status status = ODS_STATUS_OK;
795  ods_log_assert(z);
796  ods_log_assert(z->name);
799 
800  atmpfile = ods_build_path(z->name, ".axfr.tmp", 0, 1);
801  if (!atmpfile) {
802  return ODS_STATUS_MALLOC_ERR;
803  }
804  fd = ods_fopen(atmpfile, NULL, "w");
805  if (!fd) {
806  free((void*) atmpfile);
807  return ODS_STATUS_FOPEN_ERR;
808  }
809  status = adapi_printaxfr(fd, z);
810  ods_fclose(fd);
811  if (status != ODS_STATUS_OK) {
812  free((void*) atmpfile);
813  return status;
814  }
815 
816  if (z->db->is_initialized) {
817  itmpfile = ods_build_path(z->name, ".ixfr.tmp", 0, 1);
818  if (!itmpfile) {
819  free((void*) atmpfile);
820  return ODS_STATUS_MALLOC_ERR;
821  }
822  fd = ods_fopen(itmpfile, NULL, "w");
823  if (!fd) {
824  free((void*) atmpfile);
825  free((void*) itmpfile);
826  return ODS_STATUS_FOPEN_ERR;
827  }
828  status = adapi_printixfr(fd, z);
829  ods_fclose(fd);
830  if (status != ODS_STATUS_OK) {
831  free((void*) atmpfile);
832  free((void*) itmpfile);
833  return status;
834  }
835  }
836 
837  if (status == ODS_STATUS_OK) {
838  if (z->adoutbound->error) {
839  ods_log_error("[%s] unable to write zone %s axfr: one or "
840  "more RR print failed", adapter_str, z->name);
841  /* clear error */
842  z->adoutbound->error = 0;
843  free((void*) atmpfile);
844  free((void*) itmpfile);
845  return ODS_STATUS_FWRITE_ERR;
846  }
847  }
848 
849  /* lock and move */
850  axfrfile = ods_build_path(z->name, ".axfr", 0, 1);
851  if (!axfrfile) {
852  free((void*) atmpfile);
853  free((void*) itmpfile);
854  return ODS_STATUS_MALLOC_ERR;
855  }
856 
858  ret = rename(atmpfile, axfrfile);
859  if (ret != 0) {
860  ods_log_error("[%s] unable to rename file %s to %s: %s", adapter_str,
861  atmpfile, axfrfile, strerror(errno));
863  free((void*) atmpfile);
864  free((void*) axfrfile);
865  free((void*) itmpfile);
866  return ODS_STATUS_RENAME_ERR;
867  }
868  free((void*) axfrfile);
869  free((void*) atmpfile);
870 
871  if (z->db->is_initialized) {
872  ixfrfile = ods_build_path(z->name, ".ixfr", 0, 1);
873  if (!ixfrfile) {
874  free((void*) axfrfile);
875  free((void*) atmpfile);
876  free((void*) itmpfile);
877  return ODS_STATUS_MALLOC_ERR;
878  }
879  ret = rename(itmpfile, ixfrfile);
880  if (ret != 0) {
881  ods_log_error("[%s] unable to rename file %s to %s: %s",
882  adapter_str, itmpfile, ixfrfile, strerror(errno));
884  free((void*) itmpfile);
885  free((void*) ixfrfile);
886  return ODS_STATUS_RENAME_ERR;
887  }
888  free((void*) ixfrfile);
889  }
890  free((void*) itmpfile);
892 
893  dnsout_send_notify(zone);
894  return ODS_STATUS_OK;
895 }
896 
897 
902 void
904 {
905  allocator_type* allocator = NULL;
906  if (!addns) {
907  return;
908  }
909  allocator = addns->allocator;
910  acl_cleanup(addns->request_xfr, allocator);
911  acl_cleanup(addns->allow_notify, allocator);
912  tsig_cleanup(addns->tsig, allocator);
913  allocator_deallocate(allocator, (void*) addns);
914  allocator_cleanup(allocator);
915  return;
916 }
917 
918 
923 void
925 {
926  allocator_type* allocator = NULL;
927  if (!addns) {
928  return;
929  }
930  allocator = addns->allocator;
931  acl_cleanup(addns->provide_xfr, allocator);
932  acl_cleanup(addns->do_notify, allocator);
933  tsig_cleanup(addns->tsig, allocator);
934  allocator_deallocate(allocator, (void*) addns);
935  allocator_cleanup(allocator);
936  return;
937 }