OpenDNSSEC-signer  2.0.3
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 "duration.h"
40 #include "file.h"
41 #include "log.h"
42 #include "status.h"
43 #include "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 
244  tmp_serial =
245  ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
246  old_serial = adapi_get_serial(zone);
247 
275  ldns_rr_free(rr);
276  rr = NULL;
277  result = ODS_STATUS_OK;
278  continue;
279  }
280  /* second RR: if not soa, this is an AXFR */
281  if (rr_count == 1) {
282  if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_SOA) {
283  ods_log_verbose("[%s] detected axfr serial=%u for zone %s",
284  adapter_str, tmp_serial, zone->name);
285  new_serial = tmp_serial;
286  is_axfr = 1;
287  del_mode = 0;
288  } else {
289  ods_log_verbose("[%s] detected ixfr serial=%u for zone %s",
290  adapter_str, tmp_serial, zone->name);
291 
292  if (!util_serial_gt(tmp_serial, old_serial) &&
293  zone->db->is_initialized) {
294  ods_log_error("[%s] bad ixfr for zone %s, bad start serial %lu",
295  adapter_str, zone->name, (unsigned long)tmp_serial);
296  result = ODS_STATUS_ERR;
297  }
298 
299  new_serial = tmp_serial;
300  tmp_serial =
301  ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
302  ldns_rr_free(rr);
303  rr = NULL;
304  rr_count++;
305  if (tmp_serial < new_serial) {
306  del_mode = 1;
307  result = ODS_STATUS_OK;
308  continue;
309  } else {
310  ods_log_error("[%s] bad ixfr for zone %s, bad soa serial %lu",
311  adapter_str, zone->name, (unsigned long) tmp_serial);
312  result = ODS_STATUS_ERR;
313  break;
314  }
315  }
316  }
317  /* soa means swap */
318  rr_count++;
319  if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
320  if (!is_axfr) {
321  tmp_serial =
322  ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
323  if (tmp_serial <= new_serial) {
324  if (tmp_serial == new_serial) {
325  soa_seen++;
326  }
327  del_mode = !del_mode;
328  ldns_rr_free(rr);
329  rr = NULL;
330  result = ODS_STATUS_OK;
331  continue;
332  } else {
333  ods_log_assert(tmp_serial > new_serial);
334  ods_log_error("[%s] bad xfr for zone %s, bad soa serial",
335  adapter_str, zone->name);
336  ldns_rr_free(rr);
337  rr = NULL;
338  result = ODS_STATUS_ERR;
339  break;
340  }
341  } else {
342  /* for axfr */
343  soa_seen++;
344  }
345  }
346  /* [add to/remove from] the zone */
347  if (!is_axfr && del_mode) {
348  ods_log_deeebug("[%s] delete RR #%lu at line %i: %s",
349  adapter_str, (unsigned long)rr_count, l, line);
350  result = adapi_del_rr(zone, rr, 0);
351  ldns_rr_free(rr);
352  rr = NULL;
353  } else {
354  ods_log_deeebug("[%s] add RR #%lu at line %i: %s",
355  adapter_str, (unsigned long)rr_count, l, line);
356  result = adapi_add_rr(zone, rr, 0);
357  }
358  if (result == ODS_STATUS_UNCHANGED) {
359  ods_log_debug("[%s] skipping RR at line %i (%s): %s",
360  adapter_str, l, del_mode?"not found":"duplicate", line);
361  ldns_rr_free(rr);
362  rr = NULL;
363  result = ODS_STATUS_OK;
364  continue;
365  } else if (result != ODS_STATUS_OK) {
366  ods_log_error("[%s] error %s RR at line %i: %s",
367  adapter_str, del_mode?"deleting":"adding", l, line);
368  ldns_rr_free(rr);
369  rr = NULL;
370  break;
371  }
372  }
373  /* and done */
374  if (orig) {
375  ldns_rdf_deep_free(orig);
376  orig = NULL;
377  }
378  if (prev) {
379  ldns_rdf_deep_free(prev);
380  prev = NULL;
381  }
382  /* check again */
383  if (ods_strcmp(";;ENDPACKET", line) == 0) {
384  ods_log_verbose("[%s] xfr zone %s on disk complete, commit to db",
385  adapter_str, zone->name);
386  startpos = 0;
387  } else {
388  ods_log_warning("[%s] xfr zone %s on disk incomplete, rollback",
389  adapter_str, zone->name);
390  namedb_rollback(zone->db, 1);
391  if (ods_strcmp(";;BEGINPACKET", line) == 0) {
392  result = ODS_STATUS_OK;
393  startpos = fpos;
394  goto begin_pkt;
395  } else {
396  result = ODS_STATUS_XFRINCOMPLETE;
397  }
398  }
399  /* otherwise EOF */
400  if (result == ODS_STATUS_OK && status != LDNS_STATUS_OK) {
401  ods_log_error("[%s] error reading RR at line %i (%s): %s",
402  adapter_str, l, ldns_get_errorstr_by_id(status), line);
403  result = ODS_STATUS_ERR;
404  }
405  /* check the number of SOAs seen */
406  if (result == ODS_STATUS_OK) {
407  if ((is_axfr && soa_seen != 2) || (!is_axfr && soa_seen != 3)) {
408  ods_log_error("[%s] bad %s, wrong number of SOAs (%u)",
409  adapter_str, is_axfr?"axfr":"ixfr", soa_seen);
410  result = ODS_STATUS_ERR;
411  }
412  }
413  /* input zone ok, set inbound serial and apply differences */
414  if (result == ODS_STATUS_OK) {
415  adapi_set_serial(zone, new_serial);
416  if (is_axfr) {
417  adapi_trans_full(zone, 1);
418  } else {
419  adapi_trans_diff(zone, 1);
420  }
421  }
422  if (result == ODS_STATUS_UPTODATE) {
423  /* do a transaction for DNSKEY and NSEC3PARAM */
424  adapi_trans_diff(zone, 1);
425  result = ODS_STATUS_OK;
426  }
427  if (result == ODS_STATUS_XFRINCOMPLETE) {
431  xfrd = ods_build_path(zone->name, ".xfrd", 0, 1);
432  fin = ods_build_path(zone->name, ".xfrd.tmp", 0, 1);
433  fout = ods_build_path(zone->name, ".xfrd.bak", 0, 1);
434  if (!xfrd || !fin || !fout) {
435  return ODS_STATUS_MALLOC_ERR;
436  }
437  ods_log_debug("[%s] restore xfrd zone %s xfrd %s fin %s fout %s",
438  adapter_str, zone->name, xfrd, fin, fout);
439  result = ods_file_copy(fin, fout, startpos, 0);
440  if (result != ODS_STATUS_OK) {
441  ods_log_crit("[%s] unable to restore incomple xfr zone %s: %s",
442  adapter_str, zone->name, ods_status2str(result));
443  } else {
444  lock_basic_lock(&zone->xfrd->rw_lock);
445  if (ods_file_lastmodified(xfrd)) {
446  result = ods_file_copy(xfrd, fout, 0, 1);
447  if (result != ODS_STATUS_OK) {
448  ods_log_crit("[%s] unable to restore xfrd zone %s: %s",
449  adapter_str, zone->name, ods_status2str(result));
450  } else if (rename(fout, xfrd) != 0) {
451  result = ODS_STATUS_RENAME_ERR;
452  ods_log_crit("[%s] unable to restore xfrd zone %s: %s",
453  adapter_str, zone->name, ods_status2str(result));
454  }
455  } else if (rename(fout, xfrd) != 0) {
456  result = ODS_STATUS_RENAME_ERR;
457  ods_log_crit("[%s] unable to restore xfrd zone %s: %s",
458  adapter_str, zone->name, ods_status2str(result));
459 
460  }
461  lock_basic_unlock(&zone->xfrd->rw_lock);
462  }
463  free((void*) xfrd);
464  free((void*) fin);
465  free((void*) fout);
466  result = ODS_STATUS_XFRINCOMPLETE;
467  }
468  return result;
469 }
470 
471 
476 static ods_status
477 addns_read_file(FILE* fd, zone_type* zone)
478 {
479  ods_status status = ODS_STATUS_OK;
480 
481  while (status == ODS_STATUS_OK) {
482  status = addns_read_pkt(fd, zone);
483  if (status == ODS_STATUS_OK) {
484  lock_basic_lock(&zone->xfrd->serial_lock);
485  zone->xfrd->serial_xfr = adapi_get_serial(zone);
487  lock_basic_unlock(&zone->xfrd->serial_lock);
488  }
489  }
490  if (status == ODS_STATUS_EOF) {
491  status = ODS_STATUS_OK;
492  }
493  return status;
494 }
495 
496 
501 dnsin_type*
503 {
504  dnsin_type* addns = NULL;
505  CHECKALLOC(addns = (dnsin_type*) malloc(sizeof(dnsin_type)));
506  addns->request_xfr = NULL;
507  addns->allow_notify = NULL;
508  addns->tsig = NULL;
509  return addns;
510 }
511 
512 
519 {
520  dnsout_type* addns = NULL;
521  CHECKALLOC(addns = (dnsout_type*) malloc(sizeof(dnsout_type)));
522  addns->provide_xfr = NULL;
523  addns->do_notify = NULL;
524  addns->tsig = NULL;
525  return addns;
526 }
527 
528 
533 static ods_status
534 dnsin_read(dnsin_type* addns, const char* filename)
535 {
536  const char* rngfile = ODS_SE_RNGDIR "/addns.rng";
537  ods_status status = ODS_STATUS_OK;
538  FILE* fd = NULL;
539  if (!filename || !addns) {
540  return ODS_STATUS_ASSERT_ERR;
541  }
542  ods_log_debug("[%s] read dnsin file %s", adapter_str, filename);
543  status = parse_file_check(filename, rngfile);
544  if (status != ODS_STATUS_OK) {
545  ods_log_error("[%s] unable to read dnsin: parse error in "
546  "file %s (%s)", adapter_str, filename, ods_status2str(status));
547  return status;
548  }
549  fd = ods_fopen(filename, NULL, "r");
550  if (fd) {
551  addns->tsig = parse_addns_tsig(filename);
552  addns->request_xfr = parse_addns_request_xfr(filename, addns->tsig);
553  addns->allow_notify = parse_addns_allow_notify(filename, addns->tsig);
554  ods_fclose(fd);
555  return ODS_STATUS_OK;
556  }
557  ods_log_error("[%s] unable to read dnsout: failed to open file %s",
558  adapter_str, filename);
559  return ODS_STATUS_ERR;
560 }
561 
562 
567 ods_status
568 dnsin_update(dnsin_type** addns, const char* filename, time_t* last_mod)
569 {
570  dnsin_type* new_addns = NULL;
571  time_t st_mtime = 0;
572  ods_status status = ODS_STATUS_OK;
573 
574  if (!filename || !addns || !last_mod) {
575  return ODS_STATUS_UNCHANGED;
576  }
577  /* read the new signer configuration */
578  status = dnsin_read(*addns, filename);
579  if (status == ODS_STATUS_OK) {
580  *last_mod = st_mtime;
581  } else {
582  ods_log_error("[%s] unable to update dnsin: dnsin_read(%s) "
583  "failed (%s)", adapter_str, filename, ods_status2str(status));
584  }
585  return status;
586 }
587 
592 static ods_status
593 dnsout_read(dnsout_type* addns, const char* filename)
594 {
595  const char* rngfile = ODS_SE_RNGDIR "/addns.rng";
596  ods_status status = ODS_STATUS_OK;
597  FILE* fd = NULL;
598  if (!filename || !addns) {
599  return ODS_STATUS_ASSERT_ERR;
600  }
601  ods_log_debug("[%s] read dnsout file %s", adapter_str, filename);
602  status = parse_file_check(filename, rngfile);
603  if (status != ODS_STATUS_OK) {
604  ods_log_error("[%s] unable to read dnsout: parse error in "
605  "file %s (%s)", adapter_str, filename, ods_status2str(status));
606  return status;
607  }
608  fd = ods_fopen(filename, NULL, "r");
609  if (fd) {
610  addns->tsig = parse_addns_tsig(filename);
611  addns->provide_xfr = parse_addns_provide_xfr(filename, addns->tsig);
612  addns->do_notify = parse_addns_do_notify(filename, addns->tsig);
613  ods_fclose(fd);
614  return ODS_STATUS_OK;
615  }
616  ods_log_error("[%s] unable to read dnsout: failed to open file %s",
617  adapter_str, filename);
618  return ODS_STATUS_ERR;
619 }
620 
621 
626 ods_status
627 dnsout_update(dnsout_type** addns, const char* filename, time_t* last_mod)
628 {
629  time_t st_mtime = 0;
630  ods_status status = ODS_STATUS_OK;
631 
632  if (!filename || !addns || !last_mod) {
633  return ODS_STATUS_UNCHANGED;
634  }
635  /* read the new signer configuration */
636  status = dnsout_read(*addns, filename);
637  if (status == ODS_STATUS_OK) {
638  *last_mod = st_mtime;
639  } else {
640  ods_log_error("[%s] unable to update dnsout: dnsout_read(%s) "
641  "failed (%s)", adapter_str, filename, ods_status2str(status));
642  /* Don't do this cleanup. Signer will crash on exit and will
643  * access the wrong memory runtime. Leak is only once per badly
644  * configured adapter. */
645  /* dnsout_cleanup(*addns); */
646  }
647  return status;
648 }
649 
650 
655 static void
656 dnsout_send_notify(void* zone)
657 {
658  zone_type* z = (zone_type*) zone;
659  rrset_type* rrset = NULL;
660  ldns_rr* soa = NULL;
661  if (!z->notify) {
662  ods_log_error("[%s] unable to send notify for zone %s: no notify "
663  "handler", adapter_str, z->name);
664  return;
665  }
666  ods_log_assert(z->adoutbound);
667  ods_log_assert(z->adoutbound->config);
668  ods_log_assert(z->adoutbound->type == ADAPTER_DNS);
669  ods_log_assert(z->db);
670  ods_log_assert(z->name);
671  ods_log_debug("[%s] enable notify for zone %s serial %u", adapter_str,
672  z->name, z->db->intserial);
673  rrset = zone_lookup_rrset(z, z->apex, LDNS_RR_TYPE_SOA);
674  ods_log_assert(rrset);
675  soa = ldns_rr_clone(rrset->rrs[0].rr);
676  notify_enable(z->notify, soa);
677 }
678 
679 
684 ods_status
685 addns_read(void* zone)
686 {
687  zone_type* z = (zone_type*) zone;
688  ods_status status = ODS_STATUS_OK;
689  char* xfrfile = NULL;
690  char* file = NULL;
691  FILE* fd = NULL;
692  ods_log_assert(z);
693  ods_log_assert(z->name);
694  ods_log_assert(z->xfrd);
695  ods_log_assert(z->db);
696  ods_log_assert(z->adinbound);
697  ods_log_assert(z->adinbound->type == ADAPTER_DNS);
698 
699  lock_basic_lock(&z->xfrd->rw_lock);
700  lock_basic_lock(&z->xfrd->serial_lock);
701  /* did we already store a new zone transfer on disk? */
702  if (!z->xfrd->serial_disk_acquired ||
704  if (!z->xfrd->serial_disk_acquired) {
705  lock_basic_unlock(&z->xfrd->serial_lock);
706  lock_basic_unlock(&z->xfrd->rw_lock);
707  return ODS_STATUS_XFR_NOT_READY;
708  }
709  lock_basic_unlock(&z->xfrd->serial_lock);
710  lock_basic_unlock(&z->xfrd->rw_lock);
711  /* do a transaction for DNSKEY and NSEC3PARAM */
712  adapi_trans_diff(z, 0);
713  ods_log_verbose("[%s] no new xfr ready for zone %s", adapter_str,
714  z->name);
715  return ODS_STATUS_UNCHANGED;
716  }
717  /* copy zone transfers */
718  xfrfile = ods_build_path(z->name, ".xfrd", 0, 1);
719  file = ods_build_path(z->name, ".xfrd.tmp", 0, 1);
720  if (!xfrfile || !file) {
721  free(xfrfile);
722  free(file);
723  lock_basic_unlock(&z->xfrd->serial_lock);
724  lock_basic_unlock(&z->xfrd->rw_lock);
725  ods_log_error("[%s] unable to build paths to xfrd files", adapter_str);
726  return ODS_STATUS_MALLOC_ERR;
727  }
728  if (rename(xfrfile, file) != 0) {
729  lock_basic_unlock(&z->xfrd->serial_lock);
730  lock_basic_unlock(&z->xfrd->rw_lock);
731  ods_log_error("[%s] unable to rename file %s to %s: %s", adapter_str,
732  xfrfile, file, strerror(errno));
733  free((void*) xfrfile);
734  free((void*) file);
735  return ODS_STATUS_RENAME_ERR;
736  }
737  lock_basic_unlock(&z->xfrd->serial_lock);
738  /* open copy of zone transfers to read */
739  fd = ods_fopen(file, NULL, "r");
740  free((void*) xfrfile);
741  if (!fd) {
742  lock_basic_unlock(&z->xfrd->rw_lock);
743  free((void*) file);
744  return ODS_STATUS_FOPEN_ERR;
745  }
746  lock_basic_unlock(&z->xfrd->rw_lock);
747 
748  status = addns_read_file(fd, z);
749  if (status == ODS_STATUS_OK) {
750  /* clean up copy of zone transfer */
751  if (unlink((const char*) file) != 0) {
752  ods_log_error("[%s] unable to unlink zone transfer copy file %s: "
753  " %s", adapter_str, file, strerror(errno));
754  /* should be no issue */
755  }
756  }
757  free((void*) file);
758  ods_fclose(fd);
759  return status;
760 }
761 
762 
767 ods_status
768 addns_write(void* zone)
769 {
770  FILE* fd = NULL;
771  char* atmpfile = NULL;
772  char* axfrfile = NULL;
773  char* itmpfile = NULL;
774  char* ixfrfile = NULL;
775  zone_type* z = (zone_type*) zone;
776  int ret = 0;
777  ods_status status = ODS_STATUS_OK;
778  ods_log_assert(z);
779  ods_log_assert(z->name);
780  ods_log_assert(z->adoutbound);
781  ods_log_assert(z->adoutbound->type == ADAPTER_DNS);
782 
783  atmpfile = ods_build_path(z->name, ".axfr.tmp", 0, 1);
784  if (!atmpfile) {
785  return ODS_STATUS_MALLOC_ERR;
786  }
787  fd = ods_fopen(atmpfile, NULL, "w");
788  if (!fd) {
789  free((void*) atmpfile);
790  return ODS_STATUS_FOPEN_ERR;
791  }
792  status = adapi_printaxfr(fd, z);
793  ods_fclose(fd);
794  if (status != ODS_STATUS_OK) {
795  free((void*) atmpfile);
796  return status;
797  }
798 
799  if (z->db->is_initialized && z->ixfr->part[0] &&
800  z->ixfr->part[0]->soamin && z->ixfr->part[0]->soaplus)
801  {
802  itmpfile = ods_build_path(z->name, ".ixfr.tmp", 0, 1);
803  if (!itmpfile) {
804  free((void*) atmpfile);
805  return ODS_STATUS_MALLOC_ERR;
806  }
807  fd = ods_fopen(itmpfile, NULL, "w");
808  if (!fd) {
809  free((void*) atmpfile);
810  free((void*) itmpfile);
811  return ODS_STATUS_FOPEN_ERR;
812  }
813  status = adapi_printixfr(fd, z);
814  ods_fclose(fd);
815  if (status != ODS_STATUS_OK) {
816  free((void*) atmpfile);
817  free((void*) itmpfile);
818  return status;
819  }
820  }
821 
822  if (status == ODS_STATUS_OK) {
823  if (z->adoutbound->error) {
824  ods_log_error("[%s] unable to write zone %s axfr: one or "
825  "more RR print failed", adapter_str, z->name);
826  /* clear error */
827  z->adoutbound->error = 0;
828  free((void*) atmpfile);
829  free((void*) itmpfile);
830  return ODS_STATUS_FWRITE_ERR;
831  }
832  }
833 
834  /* lock and move */
835  axfrfile = ods_build_path(z->name, ".axfr", 0, 1);
836  if (!axfrfile) {
837  free((void*) atmpfile);
838  free((void*) itmpfile);
839  return ODS_STATUS_MALLOC_ERR;
840  }
841 
842  lock_basic_lock(&z->xfr_lock);
843  ret = rename(atmpfile, axfrfile);
844  if (ret != 0) {
845  ods_log_error("[%s] unable to rename file %s to %s: %s", adapter_str,
846  atmpfile, axfrfile, strerror(errno));
847  lock_basic_unlock(&z->xfr_lock);
848  free((void*) atmpfile);
849  free((void*) axfrfile);
850  free((void*) itmpfile);
851  return ODS_STATUS_RENAME_ERR;
852  }
853  free((void*) axfrfile);
854  free((void*) atmpfile);
855  axfrfile = NULL;
856  atmpfile = NULL;
857 
858  if (z->db->is_initialized && z->ixfr->part[0] &&
859  z->ixfr->part[0]->soamin && z->ixfr->part[0]->soaplus)
860  {
861  ixfrfile = ods_build_path(z->name, ".ixfr", 0, 1);
862  if (!ixfrfile) {
863  lock_basic_unlock(&z->xfr_lock);
864  free((void*) axfrfile);
865  free((void*) atmpfile);
866  free((void*) itmpfile);
867  return ODS_STATUS_MALLOC_ERR;
868  }
869  ret = rename(itmpfile, ixfrfile);
870  if (ret != 0) {
871  ods_log_error("[%s] unable to rename file %s to %s: %s",
872  adapter_str, itmpfile, ixfrfile, strerror(errno));
873  lock_basic_unlock(&z->xfr_lock);
874  free((void*) itmpfile);
875  free((void*) ixfrfile);
876  return ODS_STATUS_RENAME_ERR;
877  }
878  free((void*) ixfrfile);
879  }
880  free((void*) itmpfile);
881  lock_basic_unlock(&z->xfr_lock);
882 
883  dnsout_send_notify(zone);
884  return ODS_STATUS_OK;
885 }
886 
887 
892 void
894 {
895  if (!addns) {
896  return;
897  }
898  acl_cleanup(addns->request_xfr);
899  acl_cleanup(addns->allow_notify);
900  tsig_cleanup(addns->tsig);
901  free(addns);
902 }
903 
904 
909 void
911 {
912  if (!addns) {
913  return;
914  }
915  acl_cleanup(addns->provide_xfr);
916  acl_cleanup(addns->do_notify);
917  tsig_cleanup(addns->tsig);
918  free(addns);
919 }
acl_type * parse_addns_request_xfr(const char *filename, tsig_type *tsig)
Definition: addnsparser.c:327
void tsig_cleanup(tsig_type *tsig)
Definition: tsig.c:845
uint32_t intserial
Definition: namedb.h:54
uint32_t adapi_get_serial(zone_type *zone)
Definition: adapi.c:50
void notify_enable(notify_type *notify, ldns_rr *soa)
Definition: notify.c:516
void dnsout_cleanup(dnsout_type *addns)
Definition: addns.c:910
void * config
Definition: adapter.h:61
void acl_cleanup(acl_type *acl)
Definition: acl.c:456
time_t serial_xfr_acquired
Definition: xfrd.h:114
unsigned error
Definition: adapter.h:63
part_type * part[IXFR_MAX_PARTS]
Definition: ixfr.h:63
ods_status parse_file_check(const char *cfgfile, const char *rngfile)
Definition: confparser.c:55
acl_type * parse_addns_allow_notify(const char *filename, tsig_type *tsig)
Definition: addnsparser.c:340
adapter_mode type
Definition: adapter.h:58
lock_basic_type serial_lock
Definition: xfrd.h:97
adapter_type * adoutbound
Definition: zone.h:73
ldns_rr * addns_read_rr(FILE *fd, char *line, ldns_rdf **orig, ldns_rdf **prev, uint32_t *ttl, ldns_status *status, unsigned int *l)
Definition: addns.c:62
ldns_rr * soamin
Definition: ixfr.h:51
void adapi_set_serial(zone_type *zone, uint32_t serial)
Definition: adapi.c:64
namedb_type * db
Definition: zone.h:77
void dnsin_cleanup(dnsin_type *addns)
Definition: addns.c:893
ixfr_type * ixfr
Definition: zone.h:78
ldns_rr * soaplus
Definition: ixfr.h:53
acl_type * provide_xfr
Definition: addns.h:62
unsigned is_initialized
Definition: namedb.h:57
tsig_type * tsig
Definition: addns.h:64
tsig_type * parse_addns_tsig(const char *filename)
Definition: addnsparser.c:379
ldns_rdf * adapi_get_origin(zone_type *zone)
Definition: adapi.c:78
int adutil_whitespace_line(char *line, int line_len)
Definition: adutil.c:183
adapter_type * adinbound
Definition: zone.h:72
void namedb_rollback(namedb_type *db, unsigned keepsc)
Definition: namedb.c:848
acl_type * allow_notify
Definition: addns.h:51
void adutil_rtrim_line(char *line, int *line_len)
Definition: adutil.c:154
ods_status addns_read(void *zone)
Definition: addns.c:685
tsig_type * tsig
Definition: addns.h:52
acl_type * request_xfr
Definition: addns.h:50
ods_status adapi_del_rr(zone_type *zone, ldns_rr *rr, int backup)
Definition: adapi.c:371
ods_status dnsout_update(dnsout_type **addns, const char *filename, time_t *last_mod)
Definition: addns.c:627
ldns_rr * rr
Definition: rrset.h:52
acl_type * do_notify
Definition: addns.h:63
rrset_type * zone_lookup_rrset(zone_type *zone, ldns_rdf *owner, ldns_rr_type type)
Definition: zone.c:557
void adapi_trans_full(zone_type *zone, unsigned more_coming)
Definition: adapi.c:106
ods_status adapi_printixfr(FILE *fd, zone_type *zone)
Definition: adapi.c:424
ods_status adapi_add_rr(zone_type *zone, ldns_rr *rr, int backup)
Definition: adapi.c:360
const char * name
Definition: zone.h:67
#define SE_ADFILE_MAXLINE
Definition: adutil.h:40
int adutil_readline_frm_file(FILE *fd, char *line, unsigned int *l, int keep_comments)
Definition: adutil.c:47
uint32_t serial_xfr
Definition: xfrd.h:108
uint32_t adapi_get_ttl(zone_type *zone)
Definition: adapi.c:92
lock_basic_type rw_lock
Definition: xfrd.h:98
ods_status addns_write(void *zone)
Definition: addns.c:768
acl_type * parse_addns_do_notify(const char *filename, tsig_type *tsig)
Definition: addnsparser.c:366
notify_type * notify
Definition: zone.h:81
dnsin_type * dnsin_create(void)
Definition: addns.c:502
ods_status dnsin_update(dnsin_type **addns, const char *filename, time_t *last_mod)
Definition: addns.c:568
ods_status adapi_printaxfr(FILE *fd, zone_type *zone)
Definition: adapi.c:400
xfrd_type * xfrd
Definition: zone.h:80
dnsout_type * dnsout_create(void)
Definition: addns.c:518
ldns_rdf * apex
Definition: zone.h:59
time_t serial_disk_acquired
Definition: xfrd.h:118
rr_type * rrs
Definition: rrset.h:64
acl_type * parse_addns_provide_xfr(const char *filename, tsig_type *tsig)
Definition: addnsparser.c:353
lock_basic_type xfr_lock
Definition: zone.h:87
void adapi_trans_diff(zone_type *zone, unsigned more_coming)
Definition: adapi.c:143