static int find_same_master_notify(xfrd_zone_t* zone, int acl_num_nfy) { acl_options_t* nfy_acl = acl_find_num( zone->zone_options->allow_notify, acl_num_nfy); int num = 0; acl_options_t* master = zone->zone_options->request_xfr; if(!nfy_acl) return -1; while(master) { if(acl_same_host(nfy_acl, master)) return num; master = master->next; num++; } return -1; }
void xfrd_read_state(struct xfrd_state* xfrd) { const char* statefile = xfrd->nsd->options->xfrdfile; FILE *in; uint32_t filetime = 0; uint32_t numzones, i; region_type *tempregion; tempregion = region_create(xalloc, free); if(!tempregion) return; in = fopen(statefile, "r"); if(!in) { if(errno != ENOENT) { log_msg(LOG_ERR, "xfrd: Could not open file %s for reading: %s", statefile, strerror(errno)); } else { DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: no file %s. refreshing all zones.", statefile)); } region_destroy(tempregion); return; } if(!xfrd_read_check_str(in, XFRD_FILE_MAGIC) || !xfrd_read_check_str(in, "filetime:") || !xfrd_read_i32(in, &filetime) || (time_t)filetime > xfrd_time()+15 || !xfrd_read_check_str(in, "numzones:") || !xfrd_read_i32(in, &numzones)) { log_msg(LOG_ERR, "xfrd: corrupt state file %s dated %d (now=%lld)", statefile, (int)filetime, (long long)xfrd_time()); fclose(in); region_destroy(tempregion); return; } for(i=0; i<numzones; i++) { char *p; xfrd_zone_t* zone; const dname_type* dname; uint32_t state, masnum, nextmas, round_num, timeout; xfrd_soa_t soa_nsd_read, soa_disk_read, soa_notified_read; time_t soa_nsd_acquired_read, soa_disk_acquired_read, soa_notified_acquired_read; xfrd_soa_t incoming_soa; time_t incoming_acquired; memset(&soa_nsd_read, 0, sizeof(soa_nsd_read)); memset(&soa_disk_read, 0, sizeof(soa_disk_read)); memset(&soa_notified_read, 0, sizeof(soa_notified_read)); if(!xfrd_read_check_str(in, "zone:") || !xfrd_read_check_str(in, "name:") || !(p=xfrd_read_token(in)) || !(dname = dname_parse(tempregion, p)) || !xfrd_read_check_str(in, "state:") || !xfrd_read_i32(in, &state) || (state>2) || !xfrd_read_check_str(in, "master:") || !xfrd_read_i32(in, &masnum) || !xfrd_read_check_str(in, "next_master:") || !xfrd_read_i32(in, &nextmas) || !xfrd_read_check_str(in, "round_num:") || !xfrd_read_i32(in, &round_num) || !xfrd_read_check_str(in, "next_timeout:") || !xfrd_read_i32(in, &timeout) || !xfrd_read_state_soa(in, "soa_nsd_acquired:", "soa_nsd:", &soa_nsd_read, &soa_nsd_acquired_read) || !xfrd_read_state_soa(in, "soa_disk_acquired:", "soa_disk:", &soa_disk_read, &soa_disk_acquired_read) || !xfrd_read_state_soa(in, "soa_notify_acquired:", "soa_notify:", &soa_notified_read, &soa_notified_acquired_read)) { log_msg(LOG_ERR, "xfrd: corrupt state file %s dated %d (now=%lld)", statefile, (int)filetime, (long long)xfrd_time()); fclose(in); region_destroy(tempregion); return; } zone = (xfrd_zone_t*)rbtree_search(xfrd->zones, dname); if(!zone) { DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: state file has info for not configured zone %s", p)); continue; } if(soa_nsd_acquired_read>xfrd_time()+15 || soa_disk_acquired_read>xfrd_time()+15 || soa_notified_acquired_read>xfrd_time()+15) { log_msg(LOG_ERR, "xfrd: statefile %s contains" " times in the future for zone %s. Ignoring.", statefile, zone->apex_str); continue; } zone->state = state; zone->master_num = masnum; zone->next_master = nextmas; zone->round_num = round_num; zone->timeout.tv_sec = timeout; zone->timeout.tv_usec = 0; /* read the zone OK, now set the master properly */ zone->master = acl_find_num(zone->zone_options->pattern-> request_xfr, zone->master_num); if(!zone->master) { DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: masters changed for zone %s", zone->apex_str)); zone->master = zone->zone_options->pattern->request_xfr; zone->master_num = 0; zone->round_num = 0; } /* * There is no timeout, * or there is a notification, * or there is a soa && current time is past refresh point */ if(timeout == 0 || soa_notified_acquired_read != 0 || (soa_disk_acquired_read != 0 && (uint32_t)xfrd_time() - soa_disk_acquired_read > ntohl(soa_disk_read.refresh))) { zone->state = xfrd_zone_refreshing; xfrd_set_refresh_now(zone); } /* There is a soa && current time is past expiry point */ if(soa_disk_acquired_read!=0 && (uint32_t)xfrd_time() - soa_disk_acquired_read > ntohl(soa_disk_read.expire)) { zone->state = xfrd_zone_expired; xfrd_set_refresh_now(zone); } /* handle as an incoming SOA. */ incoming_soa = zone->soa_nsd; incoming_acquired = zone->soa_nsd_acquired; zone->soa_nsd = soa_nsd_read; zone->soa_disk = soa_disk_read; zone->soa_notified = soa_notified_read; zone->soa_nsd_acquired = soa_nsd_acquired_read; /* we had better use what we got from starting NSD, not * what we store in this file, because the actual zone * contents trumps the contents of this cache */ /* zone->soa_disk_acquired = soa_disk_acquired_read; */ zone->soa_notified_acquired = soa_notified_acquired_read; xfrd_handle_incoming_soa(zone, &incoming_soa, incoming_acquired); } if(!xfrd_read_check_str(in, XFRD_FILE_MAGIC)) { log_msg(LOG_ERR, "xfrd: corrupt state file %s dated %d (now=%lld)", statefile, (int)filetime, (long long)xfrd_time()); region_destroy(tempregion); fclose(in); return; } DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd: read %d zones from state file", (int)numzones)); fclose(in); region_destroy(tempregion); }
void xfrd_make_request(xfrd_zone_t* zone) { if(zone->next_master != -1) { /* we are told to use this next master */ DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd zone %s use master %i", zone->apex_str, zone->next_master)); zone->master_num = zone->next_master; zone->master = acl_find_num( zone->zone_options->request_xfr, zone->master_num); /* if there is no next master, fallback to use the first one */ if(!zone->master) { zone->master = zone->zone_options->request_xfr; zone->master_num = 0; } /* fallback to cycle master */ zone->next_master = -1; zone->round_num = 0; /* fresh set of retries after notify */ } else { /* cycle master */ if(zone->round_num != -1 && zone->master && zone->master->next) { /* try the next master */ zone->master = zone->master->next; zone->master_num++; } else { /* start a new round */ zone->master = zone->zone_options->request_xfr; zone->master_num = 0; zone->round_num++; } if(zone->round_num >= XFRD_MAX_ROUNDS) { /* tried all servers that many times, wait */ zone->round_num = -1; xfrd_set_timer_retry(zone); DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd zone %s makereq wait_retry, rd %d mr %d nx %d", zone->apex_str, zone->round_num, zone->master_num, zone->next_master)); return; } } /* cache ixfr_disabled only for XFRD_NO_IXFR_CACHE time */ if (zone->master->ixfr_disabled && (zone->master->ixfr_disabled + XFRD_NO_IXFR_CACHE) <= time(NULL)) { DEBUG(DEBUG_XFRD,1, (LOG_INFO, "clear negative caching ixfr " "disabled for master %s num " "%d ", zone->master->ip_address_spec, zone->master_num)); zone->master->ixfr_disabled = 0; } DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd zone %s make request round %d mr %d nx %d", zone->apex_str, zone->round_num, zone->master_num, zone->next_master)); /* perform xfr request */ if (!zone->master->use_axfr_only && zone->soa_disk_acquired > 0 && !zone->master->ixfr_disabled) { if (zone->master->allow_udp) { xfrd_set_timer(zone, xfrd_time() + XFRD_UDP_TIMEOUT); xfrd_udp_obtain(zone); } else { /* doing 3 rounds of IXFR/TCP might not be useful */ xfrd_set_timer(zone, xfrd_time() + xfrd->tcp_set->tcp_timeout); xfrd_tcp_obtain(xfrd->tcp_set, zone); } } else if (zone->master->use_axfr_only || zone->soa_disk_acquired <= 0) { xfrd_set_timer(zone, xfrd_time() + xfrd->tcp_set->tcp_timeout); xfrd_tcp_obtain(xfrd->tcp_set, zone); } else if (zone->master->ixfr_disabled) { if (zone->zone_options->allow_axfr_fallback) { xfrd_set_timer(zone, xfrd_time() + xfrd->tcp_set->tcp_timeout); xfrd_tcp_obtain(xfrd->tcp_set, zone); } else DEBUG(DEBUG_XFRD,1, (LOG_INFO, "xfrd zone %s axfr " "fallback not allowed, skipping master %s.", zone->apex_str, zone->master->ip_address_spec)); } }