OpenDNSSEC-signer 2.1.13
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
52static const char* adapter_str = "adapter";
53static ods_status addns_read_pkt(FILE* fd, zone_type* zone);
54static ods_status addns_read_file(FILE* fd, zone_type* zone);
55
56
61ldns_rr*
62addns_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
69addns_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
137static ods_status
138addns_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
185begin_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 pthread_mutex_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 pthread_mutex_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
476static ods_status
477addns_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 pthread_mutex_lock(&zone->xfrd->serial_lock);
485 zone->xfrd->serial_xfr = adapi_get_serial(zone);
487 pthread_mutex_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
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
533static ods_status
534dnsin_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
567ods_status
568dnsin_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
592static ods_status
593dnsout_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
626ods_status
627dnsout_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
655static void
656dnsout_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
684ods_status
685addns_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 pthread_mutex_lock(&z->xfrd->rw_lock);
700 pthread_mutex_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 pthread_mutex_unlock(&z->xfrd->serial_lock);
706 pthread_mutex_unlock(&z->xfrd->rw_lock);
707 return ODS_STATUS_XFR_NOT_READY;
708 }
709 pthread_mutex_unlock(&z->xfrd->serial_lock);
710 pthread_mutex_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 pthread_mutex_unlock(&z->xfrd->serial_lock);
724 pthread_mutex_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 pthread_mutex_unlock(&z->xfrd->serial_lock);
730 pthread_mutex_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 pthread_mutex_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 pthread_mutex_unlock(&z->xfrd->rw_lock);
743 free((void*) file);
744 return ODS_STATUS_FOPEN_ERR;
745 }
746 pthread_mutex_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
767ods_status
768addns_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 pthread_mutex_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 pthread_mutex_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 pthread_mutex_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 pthread_mutex_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 pthread_mutex_unlock(&z->xfr_lock);
882
883 dnsout_send_notify(zone);
884 return ODS_STATUS_OK;
885}
886
887
892void
894{
895 if (!addns) {
896 return;
897 }
898 acl_cleanup(addns->request_xfr);
900 tsig_cleanup(addns->tsig);
901 free(addns);
902}
903
904
909void
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}
void acl_cleanup(acl_type *acl)
Definition: acl.c:456
void adapi_set_serial(zone_type *zone, uint32_t serial)
Definition: adapi.c:64
ods_status adapi_add_rr(zone_type *zone, ldns_rr *rr, int backup)
Definition: adapi.c:359
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:423
ods_status adapi_del_rr(zone_type *zone, ldns_rr *rr, int backup)
Definition: adapi.c:370
ods_status adapi_printaxfr(FILE *fd, zone_type *zone)
Definition: adapi.c:399
uint32_t adapi_get_serial(zone_type *zone)
Definition: adapi.c:50
uint32_t adapi_get_ttl(zone_type *zone)
Definition: adapi.c:92
ldns_rdf * adapi_get_origin(zone_type *zone)
Definition: adapi.c:78
void adapi_trans_diff(zone_type *zone, unsigned more_coming)
Definition: adapi.c:143
@ ADAPTER_DNS
Definition: adapter.h:42
void dnsout_cleanup(dnsout_type *addns)
Definition: addns.c:910
ods_status addns_read(void *zone)
Definition: addns.c:685
ods_status dnsout_update(dnsout_type **addns, const char *filename, time_t *last_mod)
Definition: addns.c:627
void dnsin_cleanup(dnsin_type *addns)
Definition: addns.c:893
dnsout_type * dnsout_create(void)
Definition: addns.c:518
ods_status addns_write(void *zone)
Definition: addns.c:768
ods_status dnsin_update(dnsin_type **addns, const char *filename, time_t *last_mod)
Definition: addns.c:568
dnsin_type * dnsin_create(void)
Definition: addns.c:502
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
tsig_type * parse_addns_tsig(const char *filename)
Definition: addnsparser.c:379
acl_type * parse_addns_request_xfr(const char *filename, tsig_type *tsig)
Definition: addnsparser.c:327
acl_type * parse_addns_do_notify(const char *filename, tsig_type *tsig)
Definition: addnsparser.c:366
acl_type * parse_addns_provide_xfr(const char *filename, tsig_type *tsig)
Definition: addnsparser.c:353
acl_type * parse_addns_allow_notify(const char *filename, tsig_type *tsig)
Definition: addnsparser.c:340
void adutil_rtrim_line(char *line, int *line_len)
Definition: adutil.c:154
int adutil_readline_frm_file(FILE *fd, char *line, unsigned int *l, int keep_comments)
Definition: adutil.c:47
int adutil_whitespace_line(char *line, int line_len)
Definition: adutil.c:183
#define SE_ADFILE_MAXLINE
Definition: adutil.h:40
ods_status parse_file_check(const char *cfgfile, const char *rngfile)
Definition: confparser.c:55
void namedb_rollback(namedb_type *db, unsigned keepsc)
Definition: namedb.c:847
void notify_enable(notify_type *notify, ldns_rr *soa)
Definition: notify.c:544
void * config
Definition: adapter.h:61
adapter_mode type
Definition: adapter.h:58
unsigned error
Definition: adapter.h:63
acl_type * allow_notify
Definition: addns.h:51
tsig_type * tsig
Definition: addns.h:52
acl_type * request_xfr
Definition: addns.h:50
acl_type * do_notify
Definition: addns.h:63
acl_type * provide_xfr
Definition: addns.h:62
tsig_type * tsig
Definition: addns.h:64
part_type * part[IXFR_MAX_PARTS]
Definition: ixfr.h:63
unsigned is_initialized
Definition: namedb.h:57
uint32_t intserial
Definition: namedb.h:54
ldns_rr * soamin
Definition: ixfr.h:52
ldns_rr * soaplus
Definition: ixfr.h:54
ldns_rr * rr
Definition: rrset.h:52
rr_type * rrs
Definition: rrset.h:64
time_t serial_disk_acquired
Definition: xfrd.h:118
pthread_mutex_t serial_lock
Definition: xfrd.h:97
pthread_mutex_t rw_lock
Definition: xfrd.h:98
uint32_t serial_xfr
Definition: xfrd.h:108
time_t serial_xfr_acquired
Definition: xfrd.h:114
notify_type * notify
Definition: zone.h:83
namedb_type * db
Definition: zone.h:79
pthread_mutex_t xfr_lock
Definition: zone.h:87
adapter_type * adinbound
Definition: zone.h:74
ldns_rdf * apex
Definition: zone.h:61
ixfr_type * ixfr
Definition: zone.h:80
xfrd_type * xfrd
Definition: zone.h:82
const char * name
Definition: zone.h:69
adapter_type * adoutbound
Definition: zone.h:75
void tsig_cleanup(tsig_type *tsig)
Definition: tsig.c:847
rrset_type * zone_lookup_rrset(zone_type *zone, ldns_rdf *owner, ldns_rr_type type)
Definition: zone.c:510