* PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: zone.c,v 1.437 2005/06/07 00:27:33 marka Exp $ */
+/* $Id: zone.c,v 1.438 2005/06/07 01:21:32 marka Exp $ */
/*! \file */
isc_sockaddr_t *masters;
dns_name_t **masterkeynames;
+ isc_boolean_t *mastersok;
unsigned int masterscnt;
unsigned int curmaster;
isc_sockaddr_t masteraddr;
zone->minretry = DNS_ZONE_MINRETRY;
zone->masters = NULL;
zone->masterkeynames = NULL;
+ zone->mastersok = NULL;
zone->masterscnt = 0;
zone->curmaster = 0;
zone->notify = NULL;
isc_sockaddr_t *new;
isc_result_t result = ISC_R_SUCCESS;
dns_name_t **newname;
+ isc_boolean_t *newok;
unsigned int i;
REQUIRE(DNS_ZONE_VALID(zone));
zone->masterscnt * sizeof(dns_name_t *));
zone->masterkeynames = NULL;
}
+ if (zone->mastersok != NULL) {
+ isc_mem_put(zone->mctx, zone->mastersok,
+ zone->masterscnt * sizeof(isc_boolean_t));
+ zone->mastersok = NULL;
+ }
zone->masterscnt = 0;
/*
- * If count == 0, don't allocate any space for masters or keynames
- * so internally, those pointers are NULL if count == 0
+ * If count == 0, don't allocate any space for masters, mastersok or
+ * keynames so internally, those pointers are NULL if count == 0
*/
if (count == 0)
goto unlock;
/*
* masters must countain count elements!
*/
- new = isc_mem_get(zone->mctx,
- count * sizeof(isc_sockaddr_t));
+ new = isc_mem_get(zone->mctx, count * sizeof(*new));
if (new == NULL) {
result = ISC_R_NOMEMORY;
goto unlock;
}
memcpy(new, masters, count * sizeof(*new));
- zone->masters = new;
- zone->masterscnt = count;
- DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
+
+ /*
+ * Similarly for mastersok.
+ */
+ newok = isc_mem_get(zone->mctx, count * sizeof(newok));
+ if (newok == NULL) {
+ result = ISC_R_NOMEMORY;
+ isc_mem_put(zone->mctx, new, count * sizeof(*new));
+ goto unlock;
+ };
+ for (i = 0; i < count; i++)
+ newok[i] = ISC_FALSE;
/*
* if keynames is non-NULL, it must contain count elements!
*/
+ newname = NULL;
if (keynames != NULL) {
- newname = isc_mem_get(zone->mctx,
- count * sizeof(dns_name_t *));
+ newname = isc_mem_get(zone->mctx, count * sizeof(*newname));
if (newname == NULL) {
result = ISC_R_NOMEMORY;
- isc_mem_put(zone->mctx, zone->masters,
- count * sizeof(*new));
+ isc_mem_put(zone->mctx, new, count * sizeof(*new));
+ isc_mem_put(zone->mctx, newok, count * sizeof(*newok));
goto unlock;
}
for (i = 0; i < count; i++)
dns_name_free(
newname[i],
zone->mctx);
- isc_mem_put(zone->mctx, zone->masters,
+ isc_mem_put(zone->mctx, new,
count * sizeof(*new));
+ isc_mem_put(zone->mctx, newok,
+ count * sizeof(*newok));
isc_mem_put(zone->mctx, newname,
count * sizeof(*newname));
goto unlock;
}
}
}
- zone->masterkeynames = newname;
}
+
+ /*
+ * Everything is ok so attach to the zone.
+ */
+ zone->masters = new;
+ zone->mastersok = newok;
+ zone->masterkeynames = newname;
+ zone->masterscnt = count;
+ DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOMASTERS);
+
unlock:
UNLOCK_ZONE(zone);
return (result);
dns_zone_refresh(dns_zone_t *zone) {
isc_interval_t i;
isc_uint32_t oldflags;
+ unsigned int j;
REQUIRE(DNS_ZONE_VALID(zone));
zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600);
zone->curmaster = 0;
+ for (j = 0; j < zone->masterscnt; j++)
+ zone->mastersok[j] = ISC_FALSE;
/* initiate soa query */
queue_soa_query(zone);
unlock:
isc_time_t now;
isc_boolean_t exiting = ISC_FALSE;
isc_interval_t i;
+ unsigned int j;
stub = revent->ev_arg;
INSIST(DNS_STUB_VALID(stub));
isc_event_free(&event);
LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
- zone->curmaster++;
+ /*
+ * Skip to next failed / untried master.
+ */
+ do {
+ zone->curmaster++;
+ } while (zone->curmaster < zone->masterscnt &&
+ zone->mastersok[zone->curmaster]);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
if (exiting || zone->curmaster >= zone->masterscnt) {
+ isc_boolean_t done = ISC_TRUE;
if (!exiting &&
DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
+ /*
+ * Did we get a good answer from all the masters?
+ */
+ for (j = 0; j < zone->masterscnt; j++)
+ if (zone->mastersok[j] == ISC_FALSE) {
+ done = ISC_FALSE;
+ break;
+ }
+ } else
+ done = ISC_TRUE;
+ if (!done) {
zone->curmaster = 0;
+ /*
+ * Find the next failed master.
+ */
+ while (zone->curmaster < zone->masterscnt &&
+ zone->mastersok[zone->curmaster])
+ zone->curmaster++;
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
} else {
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
dns_rdata_soa_t soa;
isc_result_t result;
isc_uint32_t serial;
+ unsigned int j;
zone = revent->ev_arg;
INSIST(DNS_ZONE_VALID(zone));
}
DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);
DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);
+ zone->mastersok[zone->curmaster] = ISC_TRUE;
goto next_master;
} else {
if (!DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MULTIMASTER))
soa.serial, master, zone->serial);
else
zone_debuglog(zone, me, 1, "ahead");
+ zone->mastersok[zone->curmaster] = ISC_TRUE;
goto next_master;
}
if (msg != NULL)
isc_event_free(&event);
LOCK_ZONE(zone);
dns_request_destroy(&zone->request);
- zone->curmaster++;
+ /*
+ * Skip to next failed / untried master.
+ */
+ do {
+ zone->curmaster++;
+ } while (zone->curmaster < zone->masterscnt &&
+ zone->mastersok[zone->curmaster]);
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS);
if (zone->curmaster >= zone->masterscnt) {
+ isc_boolean_t done = ISC_TRUE;
if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_USEALTXFRSRC) &&
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
+ /*
+ * Did we get a good answer from all the masters?
+ */
+ for (j = 0; j < zone->masterscnt; j++)
+ if (zone->mastersok[j] == ISC_FALSE) {
+ done = ISC_FALSE;
+ break;
+ }
+ } else
+ done = ISC_TRUE;
+ if (!done) {
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
zone->curmaster = 0;
+ /*
+ * Find the next failed master.
+ */
+ while (zone->curmaster < zone->masterscnt &&
+ zone->mastersok[zone->curmaster])
+ zone->curmaster++;
goto requeue;
}
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);
skip_master:
if (key != NULL)
dns_tsigkey_detach(&key);
- zone->curmaster++;
+ /*
+ * Skip to next failed / untried master.
+ */
+ do {
+ zone->curmaster++;
+ } while (zone->curmaster < zone->masterscnt &&
+ zone->mastersok[zone->curmaster]);
if (zone->curmaster < zone->masterscnt)
goto again;
zone->curmaster = 0;
default:
next_master:
- zone->curmaster++;
+ /*
+ * Skip to next failed / untried master.
+ */
+ do {
+ zone->curmaster++;
+ } while (zone->curmaster < zone->masterscnt &&
+ zone->mastersok[zone->curmaster]);
+ /* FALLTHROUGH */
same_master:
if (zone->curmaster >= zone->masterscnt) {
zone->curmaster = 0;
!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_USEALTXFRSRC)) {
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH);
DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);
+ while (zone->curmaster < zone->masterscnt &&
+ zone->mastersok[zone->curmaster])
+ zone->curmaster++;
again = ISC_TRUE;
} else
DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);