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);
63 uint32_t* ttl, ldns_status* status,
unsigned int* l)
82 if (ods_strcmp(
";;ENDPACKET", line) == 0) {
84 *status = LDNS_STATUS_OK;
87 if (ods_strcmp(
";;BEGINPACKET", line) == 0) {
89 *status = LDNS_STATUS_OK;
100 *status = ldns_rr_new_frm_str(&rr, line, new_ttl, *orig, prev);
101 if (*status == LDNS_STATUS_OK) {
103 }
else if (*status == LDNS_STATUS_SYNTAX_EMPTY) {
108 *status = LDNS_STATUS_OK;
109 goto addns_read_line;
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);
128 *status = LDNS_STATUS_OK;
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;
152 ods_status result = ODS_STATUS_OK;
153 ldns_status status = LDNS_STATUS_OK;
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;
166 ods_log_assert(zone);
167 ods_log_assert(zone->
name);
174 return ODS_STATUS_EOF;
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;
193 ods_log_error(
"[%s] error getting default value for $ORIGIN",
195 return ODS_STATUS_ERR;
197 orig = ldns_rdf_clone(dname);
199 ods_log_error(
"[%s] error setting default value for $ORIGIN",
201 return ODS_STATUS_ERR;
207 while ((rr =
addns_read_rr(fd, line, &orig, &prev, &ttl, &status, &l))
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;
219 if (l > line_update) {
220 ods_log_debug(
"[%s] ...at line %i: %s", adapter_str, l, line);
221 line_update += line_update_interval;
226 if (ldns_rr_get_type(rr) != LDNS_RR_TYPE_SOA) {
227 ods_log_error(
"[%s] bad xfr, first rr is not soa",
231 result = ODS_STATUS_ERR;
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);
240 result = ODS_STATUS_ERR;
245 ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
277 result = ODS_STATUS_OK;
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;
289 ods_log_verbose(
"[%s] detected ixfr serial=%u for zone %s",
290 adapter_str, tmp_serial, zone->
name);
292 if (!util_serial_gt(tmp_serial, old_serial) &&
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;
299 new_serial = tmp_serial;
301 ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
305 if (tmp_serial < new_serial) {
307 result = ODS_STATUS_OK;
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;
319 if (ldns_rr_get_type(rr) == LDNS_RR_TYPE_SOA) {
322 ldns_rdf2native_int32(ldns_rr_rdf(rr, SE_SOA_RDATA_SERIAL));
323 if (tmp_serial <= new_serial) {
324 if (tmp_serial == new_serial) {
327 del_mode = !del_mode;
330 result = ODS_STATUS_OK;
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);
338 result = ODS_STATUS_ERR;
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);
354 ods_log_deeebug(
"[%s] add RR #%lu at line %i: %s",
355 adapter_str, (
unsigned long)rr_count, l, line);
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);
363 result = ODS_STATUS_OK;
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);
375 ldns_rdf_deep_free(orig);
379 ldns_rdf_deep_free(prev);
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);
388 ods_log_warning(
"[%s] xfr zone %s on disk incomplete, rollback",
389 adapter_str, zone->
name);
391 if (ods_strcmp(
";;BEGINPACKET", line) == 0) {
392 result = ODS_STATUS_OK;
396 result = ODS_STATUS_XFRINCOMPLETE;
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;
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;
414 if (result == ODS_STATUS_OK) {
422 if (result == ODS_STATUS_UPTODATE) {
425 result = ODS_STATUS_OK;
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;
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));
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));
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));
466 result = ODS_STATUS_XFRINCOMPLETE;
477addns_read_file(FILE* fd,
zone_type* zone)
479 ods_status status = ODS_STATUS_OK;
481 while (status == ODS_STATUS_OK) {
482 status = addns_read_pkt(fd, zone);
483 if (status == ODS_STATUS_OK) {
490 if (status == ODS_STATUS_EOF) {
491 status = ODS_STATUS_OK;
534dnsin_read(
dnsin_type* addns,
const char* filename)
536 const char* rngfile = ODS_SE_RNGDIR
"/addns.rng";
537 ods_status status = ODS_STATUS_OK;
539 if (!filename || !addns) {
540 return ODS_STATUS_ASSERT_ERR;
542 ods_log_debug(
"[%s] read dnsin file %s", adapter_str, filename);
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));
549 fd = ods_fopen(filename, NULL,
"r");
555 return ODS_STATUS_OK;
557 ods_log_error(
"[%s] unable to read dnsout: failed to open file %s",
558 adapter_str, filename);
559 return ODS_STATUS_ERR;
572 ods_status status = ODS_STATUS_OK;
574 if (!filename || !addns || !last_mod) {
575 return ODS_STATUS_UNCHANGED;
578 status = dnsin_read(*addns, filename);
579 if (status == ODS_STATUS_OK) {
580 *last_mod = st_mtime;
582 ods_log_error(
"[%s] unable to update dnsin: dnsin_read(%s) "
583 "failed (%s)", adapter_str, filename, ods_status2str(status));
593dnsout_read(
dnsout_type* addns,
const char* filename)
595 const char* rngfile = ODS_SE_RNGDIR
"/addns.rng";
596 ods_status status = ODS_STATUS_OK;
598 if (!filename || !addns) {
599 return ODS_STATUS_ASSERT_ERR;
601 ods_log_debug(
"[%s] read dnsout file %s", adapter_str, filename);
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));
608 fd = ods_fopen(filename, NULL,
"r");
614 return ODS_STATUS_OK;
616 ods_log_error(
"[%s] unable to read dnsout: failed to open file %s",
617 adapter_str, filename);
618 return ODS_STATUS_ERR;
630 ods_status status = ODS_STATUS_OK;
632 if (!filename || !addns || !last_mod) {
633 return ODS_STATUS_UNCHANGED;
636 status = dnsout_read(*addns, filename);
637 if (status == ODS_STATUS_OK) {
638 *last_mod = st_mtime;
640 ods_log_error(
"[%s] unable to update dnsout: dnsout_read(%s) "
641 "failed (%s)", adapter_str, filename, ods_status2str(status));
656dnsout_send_notify(
void* zone)
662 ods_log_error(
"[%s] unable to send notify for zone %s: no notify "
663 "handler", adapter_str, z->
name);
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,
674 ods_log_assert(rrset);
675 soa = ldns_rr_clone(rrset->
rrs[0].
rr);
688 ods_status status = ODS_STATUS_OK;
689 char* xfrfile = NULL;
693 ods_log_assert(z->
name);
694 ods_log_assert(z->
xfrd);
695 ods_log_assert(z->
db);
707 return ODS_STATUS_XFR_NOT_READY;
713 ods_log_verbose(
"[%s] no new xfr ready for zone %s", adapter_str,
715 return ODS_STATUS_UNCHANGED;
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) {
725 ods_log_error(
"[%s] unable to build paths to xfrd files", adapter_str);
726 return ODS_STATUS_MALLOC_ERR;
728 if (rename(xfrfile, file) != 0) {
731 ods_log_error(
"[%s] unable to rename file %s to %s: %s", adapter_str,
732 xfrfile, file, strerror(errno));
733 free((
void*) xfrfile);
735 return ODS_STATUS_RENAME_ERR;
739 fd = ods_fopen(file, NULL,
"r");
740 free((
void*) xfrfile);
744 return ODS_STATUS_FOPEN_ERR;
748 status = addns_read_file(fd, z);
749 if (status == ODS_STATUS_OK) {
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));
771 char* atmpfile = NULL;
772 char* axfrfile = NULL;
773 char* itmpfile = NULL;
774 char* ixfrfile = NULL;
777 ods_status status = ODS_STATUS_OK;
779 ods_log_assert(z->
name);
783 atmpfile = ods_build_path(z->
name,
".axfr.tmp", 0, 1);
785 return ODS_STATUS_MALLOC_ERR;
787 fd = ods_fopen(atmpfile, NULL,
"w");
789 free((
void*) atmpfile);
790 return ODS_STATUS_FOPEN_ERR;
794 if (status != ODS_STATUS_OK) {
795 free((
void*) atmpfile);
802 itmpfile = ods_build_path(z->
name,
".ixfr.tmp", 0, 1);
804 free((
void*) atmpfile);
805 return ODS_STATUS_MALLOC_ERR;
807 fd = ods_fopen(itmpfile, NULL,
"w");
809 free((
void*) atmpfile);
810 free((
void*) itmpfile);
811 return ODS_STATUS_FOPEN_ERR;
815 if (status != ODS_STATUS_OK) {
816 free((
void*) atmpfile);
817 free((
void*) itmpfile);
822 if (status == ODS_STATUS_OK) {
824 ods_log_error(
"[%s] unable to write zone %s axfr: one or "
825 "more RR print failed", adapter_str, z->
name);
828 free((
void*) atmpfile);
829 free((
void*) itmpfile);
830 return ODS_STATUS_FWRITE_ERR;
835 axfrfile = ods_build_path(z->
name,
".axfr", 0, 1);
837 free((
void*) atmpfile);
838 free((
void*) itmpfile);
839 return ODS_STATUS_MALLOC_ERR;
843 ret = rename(atmpfile, axfrfile);
845 ods_log_error(
"[%s] unable to rename file %s to %s: %s", adapter_str,
846 atmpfile, axfrfile, strerror(errno));
848 free((
void*) atmpfile);
849 free((
void*) axfrfile);
850 free((
void*) itmpfile);
851 return ODS_STATUS_RENAME_ERR;
853 free((
void*) axfrfile);
854 free((
void*) atmpfile);
861 ixfrfile = ods_build_path(z->
name,
".ixfr", 0, 1);
864 free((
void*) axfrfile);
865 free((
void*) atmpfile);
866 free((
void*) itmpfile);
867 return ODS_STATUS_MALLOC_ERR;
869 ret = rename(itmpfile, ixfrfile);
871 ods_log_error(
"[%s] unable to rename file %s to %s: %s",
872 adapter_str, itmpfile, ixfrfile, strerror(errno));
874 free((
void*) itmpfile);
875 free((
void*) ixfrfile);
876 return ODS_STATUS_RENAME_ERR;
878 free((
void*) ixfrfile);
880 free((
void*) itmpfile);
883 dnsout_send_notify(zone);
884 return ODS_STATUS_OK;
void acl_cleanup(acl_type *acl)
void adapi_set_serial(zone_type *zone, uint32_t serial)
ods_status adapi_add_rr(zone_type *zone, ldns_rr *rr, int backup)
void adapi_trans_full(zone_type *zone, unsigned more_coming)
ods_status adapi_printixfr(FILE *fd, zone_type *zone)
ods_status adapi_del_rr(zone_type *zone, ldns_rr *rr, int backup)
ods_status adapi_printaxfr(FILE *fd, zone_type *zone)
uint32_t adapi_get_serial(zone_type *zone)
uint32_t adapi_get_ttl(zone_type *zone)
ldns_rdf * adapi_get_origin(zone_type *zone)
void adapi_trans_diff(zone_type *zone, unsigned more_coming)
void dnsout_cleanup(dnsout_type *addns)
ods_status addns_read(void *zone)
ods_status dnsout_update(dnsout_type **addns, const char *filename, time_t *last_mod)
void dnsin_cleanup(dnsin_type *addns)
dnsout_type * dnsout_create(void)
ods_status addns_write(void *zone)
ods_status dnsin_update(dnsin_type **addns, const char *filename, time_t *last_mod)
dnsin_type * dnsin_create(void)
ldns_rr * addns_read_rr(FILE *fd, char *line, ldns_rdf **orig, ldns_rdf **prev, uint32_t *ttl, ldns_status *status, unsigned int *l)
tsig_type * parse_addns_tsig(const char *filename)
acl_type * parse_addns_request_xfr(const char *filename, tsig_type *tsig)
acl_type * parse_addns_do_notify(const char *filename, tsig_type *tsig)
acl_type * parse_addns_provide_xfr(const char *filename, tsig_type *tsig)
acl_type * parse_addns_allow_notify(const char *filename, tsig_type *tsig)
void adutil_rtrim_line(char *line, int *line_len)
int adutil_readline_frm_file(FILE *fd, char *line, unsigned int *l, int keep_comments)
int adutil_whitespace_line(char *line, int line_len)
#define SE_ADFILE_MAXLINE
ods_status parse_file_check(const char *cfgfile, const char *rngfile)
void namedb_rollback(namedb_type *db, unsigned keepsc)
void notify_enable(notify_type *notify, ldns_rr *soa)
part_type * part[IXFR_MAX_PARTS]
time_t serial_disk_acquired
pthread_mutex_t serial_lock
time_t serial_xfr_acquired
adapter_type * adoutbound
void tsig_cleanup(tsig_type *tsig)
rrset_type * zone_lookup_rrset(zone_type *zone, ldns_rdf *owner, ldns_rr_type type)