📄 zone.c
字号:
REQUIRE(DNS_ZONE_VALID(zone)); ENTER; /* * Configuring the view of this zone may have * failed, for example because the config file * had a syntax error. In that case, the view * adb or resolver, and we had better not try * to do maintenance on it. */ if (zone->view == NULL || zone->view->adb == NULL) return; TIME_NOW(&now); /* * Expire check. */ switch (zone->type) { case dns_zone_slave: case dns_zone_stub: LOCK_ZONE(zone); if (isc_time_compare(&now, &zone->expiretime) >= 0 && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) { zone_expire(zone); zone->refreshtime = now; } UNLOCK_ZONE(zone); break; default: break; } /* * Up to date check. */ switch (zone->type) { case dns_zone_slave: case dns_zone_stub: if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DIALREFRESH) && isc_time_compare(&now, &zone->refreshtime) >= 0) dns_zone_refresh(zone); break; default: break; } /* * Do we need to consolidate the backing store? */ switch (zone->type) { case dns_zone_master: case dns_zone_slave: LOCK_ZONE(zone); if (zone->masterfile != NULL && isc_time_compare(&now, &zone->dumptime) >= 0 && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP)) { dumping = was_dumping(zone); } else dumping = ISC_TRUE; UNLOCK_ZONE(zone); if (!dumping) { result = zone_dump(zone, ISC_TRUE); /* task locked */ if (result != ISC_R_SUCCESS) dns_zone_log(zone, ISC_LOG_WARNING, "dump failed: %s", dns_result_totext(result)); } break; default: break; } /* * Do we need to send out notify messages? */ switch (zone->type) { case dns_zone_master: case dns_zone_slave: if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDNOTIFY)) zone_notify(zone); break; default: break; } zone_settimer(zone, &now);}voiddns_zone_markdirty(dns_zone_t *zone) { LOCK_ZONE(zone); zone_needdump(zone, DNS_DUMP_DELAY); UNLOCK_ZONE(zone);}voiddns_zone_expire(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); LOCK_ZONE(zone); zone_expire(zone); UNLOCK_ZONE(zone);}static voidzone_expire(dns_zone_t *zone) { /* * 'zone' locked by caller. */ REQUIRE(LOCKED_ZONE(zone)); dns_zone_log(zone, ISC_LOG_WARNING, "expired"); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_EXPIRED); zone->refresh = DNS_ZONE_DEFAULTREFRESH; zone->retry = DNS_ZONE_DEFAULTRETRY; DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HAVETIMERS); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP); zone_unload(zone);}voiddns_zone_refresh(dns_zone_t *zone) { isc_interval_t i; isc_uint32_t oldflags; REQUIRE(DNS_ZONE_VALID(zone)); if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) return; /* * Set DNS_ZONEFLG_REFRESH so that there is only one refresh operation * in progress at a time. */ LOCK_ZONE(zone); oldflags = zone->flags; if (zone->masterscnt == 0) { DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOMASTERS); if ((oldflags & DNS_ZONEFLG_NOMASTERS) == 0) dns_zone_log(zone, ISC_LOG_ERROR, "cannot refresh: no masters"); goto unlock; } DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_REFRESH); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NOEDNS); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC); if ((oldflags & (DNS_ZONEFLG_REFRESH|DNS_ZONEFLG_LOADING)) != 0) goto unlock; /* * Set the next refresh time as if refresh check has failed. * Setting this to the retry time will do that. XXXMLG * If we are successful it will be reset using zone->refresh. */ isc_interval_set(&i, isc_random_jitter(zone->retry, zone->retry / 4), 0); isc_time_nowplusinterval(&zone->refreshtime, &i); /* * When lacking user-specified timer values from the SOA, * do exponential backoff of the retry time up to a * maximum of six hours. */ if (! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_HAVETIMERS)) zone->retry = ISC_MIN(zone->retry * 2, 6 * 3600); zone->curmaster = 0; /* initiate soa query */ queue_soa_query(zone); unlock: UNLOCK_ZONE(zone);}isc_result_tdns_zone_flush(dns_zone_t *zone) { isc_result_t result = ISC_R_SUCCESS; isc_boolean_t dumping; REQUIRE(DNS_ZONE_VALID(zone)); LOCK_ZONE(zone); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_FLUSH); if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) && zone->masterfile != NULL) { result = ISC_R_ALREADYRUNNING; dumping = was_dumping(zone); } else dumping = ISC_TRUE; UNLOCK_ZONE(zone); if (!dumping) result = zone_dump(zone, ISC_FALSE); /* Unknown task. */ return (result);}isc_result_tdns_zone_dump(dns_zone_t *zone) { isc_result_t result = ISC_R_ALREADYRUNNING; isc_boolean_t dumping; REQUIRE(DNS_ZONE_VALID(zone)); LOCK_ZONE(zone); dumping = was_dumping(zone); UNLOCK_ZONE(zone); if (!dumping) result = zone_dump(zone, ISC_FALSE); /* Unknown task. */ return (result);}static voidzone_needdump(dns_zone_t *zone, unsigned int delay) { isc_time_t dumptime; isc_time_t now; /* * 'zone' locked by caller */ REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(LOCKED_ZONE(zone)); /* * Do we have a place to dump to and are we loaded? */ if (zone->masterfile == NULL || DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED) == 0) return; TIME_NOW(&now); /* add some noise */ DNS_ZONE_JITTER_ADD(&now, delay, &dumptime); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NEEDDUMP); if (isc_time_isepoch(&zone->dumptime) || isc_time_compare(&zone->dumptime, &dumptime) > 0) zone->dumptime = dumptime; if (zone->task != NULL) zone_settimer(zone, &now);}static voiddump_done(void *arg, isc_result_t result) { const char me[] = "dump_done"; dns_zone_t *zone = arg; dns_db_t *db; dns_dbversion_t *version; isc_boolean_t again = ISC_FALSE; REQUIRE(DNS_ZONE_VALID(zone)); ENTER; if (result == ISC_R_SUCCESS && zone->journal != NULL && zone->journalsize != -1) { isc_uint32_t serial; isc_result_t tresult; /* * We don't own these, zone->dctx must stay valid. */ db = dns_dumpctx_db(zone->dctx); version = dns_dumpctx_version(zone->dctx); tresult = dns_db_getsoaserial(db, version, &serial); if (tresult == ISC_R_SUCCESS) { tresult = dns_journal_compact(zone->mctx, zone->journal, serial, zone->journalsize); switch (tresult) { case ISC_R_SUCCESS: case ISC_R_NOSPACE: case ISC_R_NOTFOUND: dns_zone_log(zone, ISC_LOG_DEBUG(3), "dns_journal_compact: %s", dns_result_totext(tresult)); break; default: dns_zone_log(zone, ISC_LOG_ERROR, "dns_journal_compact failed: %s", dns_result_totext(tresult)); break; } } } LOCK_ZONE(zone); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING); if (result != ISC_R_SUCCESS && result != ISC_R_CANCELED) { /* * Try again in a short while. */ zone_needdump(zone, DNS_DUMP_DELAY); } else if (result == ISC_R_SUCCESS && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) { DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING); isc_time_settoepoch(&zone->dumptime); again = ISC_TRUE; } else if (result == ISC_R_SUCCESS) DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH); if (zone->dctx != NULL) dns_dumpctx_detach(&zone->dctx); zonemgr_putio(&zone->writeio); UNLOCK_ZONE(zone); if (again) (void)zone_dump(zone, ISC_FALSE); dns_zone_idetach(&zone);}static isc_result_tzone_dump(dns_zone_t *zone, isc_boolean_t compact) { const char me[] = "zone_dump"; isc_result_t result; dns_dbversion_t *version = NULL; isc_boolean_t again; dns_db_t *db = NULL; char *masterfile = NULL;/* * 'compact' MUST only be set if we are task locked. */ REQUIRE(DNS_ZONE_VALID(zone)); ENTER; redo: LOCK_ZONE(zone); if (zone->db != NULL) dns_db_attach(zone->db, &db); if (zone->masterfile != NULL) masterfile = isc_mem_strdup(zone->mctx, zone->masterfile); UNLOCK_ZONE(zone); if (db == NULL) { result = DNS_R_NOTLOADED; goto fail; } if (masterfile == NULL) { result = DNS_R_NOMASTERFILE; goto fail; } if (compact) { dns_zone_t *dummy = NULL; LOCK_ZONE(zone); zone_iattach(zone, &dummy); result = zonemgr_getio(zone->zmgr, ISC_FALSE, zone->task, zone_gotwritehandle, zone, &zone->writeio); if (result != ISC_R_SUCCESS) zone_idetach(&dummy); else result = DNS_R_CONTINUE; UNLOCK_ZONE(zone); } else { dns_db_currentversion(db, &version); result = dns_master_dump(zone->mctx, db, version, &dns_master_style_default, masterfile); dns_db_closeversion(db, &version, ISC_FALSE); } fail: if (db != NULL) dns_db_detach(&db); if (masterfile != NULL) isc_mem_free(zone->mctx, masterfile); masterfile = NULL; if (result == DNS_R_CONTINUE) return (ISC_R_SUCCESS); /* XXXMPA */ again = ISC_FALSE; LOCK_ZONE(zone); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_DUMPING); if (result != ISC_R_SUCCESS) { /* * Try again in a short while. */ zone_needdump(zone, DNS_DUMP_DELAY); } else if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NEEDDUMP) && DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) { DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_NEEDDUMP); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_DUMPING); isc_time_settoepoch(&zone->dumptime); again = ISC_TRUE; } else DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_FLUSH); UNLOCK_ZONE(zone); if (again) goto redo; return (result);}static isc_result_tdumptostream(dns_zone_t *zone, FILE *fd, const dns_master_style_t *style) { isc_result_t result; dns_dbversion_t *version = NULL; dns_db_t *db = NULL; REQUIRE(DNS_ZONE_VALID(zone)); LOCK_ZONE(zone); if (zone->db != NULL) dns_db_attach(zone->db, &db); UNLOCK_ZONE(zone); if (db == NULL) return (DNS_R_NOTLOADED); dns_db_currentversion(db, &version); result = dns_master_dumptostream(zone->mctx, db, version, style, fd); dns_db_closeversion(db, &version, ISC_FALSE); dns_db_detach(&db); return (result);}isc_result_tdns_zone_dumptostream(dns_zone_t *zone, FILE *fd) { return dumptostream(zone, fd, &dns_master_style_default);}isc_result_tdns_zone_fulldumptostream(dns_zone_t *zone, FILE *fd) { return dumptostream(zone, fd, &dns_master_style_full);}voiddns_zone_unload(dns_zone_t *zone) { REQUIRE(DNS_ZONE_VALID(zone)); LOCK_ZONE(zone); zone_unload(zone); UNLOCK_ZONE(zone);}static voidnotify_cancel(dns_zone_t *zone) { dns_notify_t *notify; /* * 'zone' locked by caller. */ REQUIRE(LOCKED_ZONE(zone)); for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL; notify = ISC_LIST_NEXT(notify, link)) { if (notify->find != NULL) dns_adb_cancelfind(notify->find); if (notify->request != NULL) dns_request_cancel(notify->request); }}static voidzone_unload(dns_zone_t *zone) { /* * 'zone' locked by caller. */ REQUIRE(LOCKED_ZONE(zone)); dns_db_detach(&zone->db); DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_LOADED);}voiddns_zone_setminrefreshtime(dns_zone_t *zone, isc_uint32_t val) { REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(val > 0); zone->minrefresh = val;}voiddns_zone_setmaxrefreshtime(dns_zone_t *zone, isc_uint32_t val) { REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(val > 0); zone->maxrefresh = val;}voiddns_zone_setminretrytime(dns_zone_t *zone, isc_uint32_t val) { REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(val > 0); zone->minretry = val;}voiddns_zone_setmaxretrytime(dns_zone_t *zone, isc_uint32_t val) { REQUIRE(DNS_ZONE_VALID(zone)); REQUIRE(val > 0); zone->maxretry = val;}static isc_boolean_tnotify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) { dns_notify_t *notify; for (notify = ISC_LIST_HEAD(zone->notifies); notify != NULL; notify
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -