📄 zone.c
字号:
result = dns_master_loadfileinc(load->zone->masterfile, dns_db_origin(load->db), dns_db_origin(load->db), load->zone->rdclass, options, &load->callbacks, task, zone_loaddone, load, &load->zone->lctx, load->zone->mctx); if (result != ISC_R_SUCCESS && result != DNS_R_CONTINUE && result != DNS_R_SEENINCLUDE) goto fail; return; fail: zone_loaddone(load, result);}static isc_result_tzone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime) { dns_load_t *load; isc_result_t result; isc_result_t tresult; unsigned int options; options = DNS_MASTER_ZONE; if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) options |= DNS_MASTER_MANYERRORS; if (zone->type == dns_zone_slave) options |= DNS_MASTER_SLAVE; if (zone->zmgr != NULL && zone->db != NULL && zone->task != NULL) { load = isc_mem_get(zone->mctx, sizeof(*load)); if (load == NULL) return (ISC_R_NOMEMORY); load->mctx = NULL; load->zone = NULL; load->db = NULL; load->loadtime = loadtime; load->magic = LOAD_MAGIC; isc_mem_attach(zone->mctx, &load->mctx); zone_iattach(zone, &load->zone); dns_db_attach(db, &load->db); dns_rdatacallbacks_init(&load->callbacks); result = dns_db_beginload(db, &load->callbacks.add, &load->callbacks.add_private); if (result != ISC_R_SUCCESS) goto cleanup; result = zonemgr_getio(zone->zmgr, ISC_TRUE, zone->task, zone_gotreadhandle, load, &zone->readio); if (result != ISC_R_SUCCESS) { tresult = dns_db_endload(load->db, &load->callbacks.add_private); if (result == ISC_R_SUCCESS) result = tresult; goto cleanup; } else result = DNS_R_CONTINUE; } else if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_MANYERRORS)) { dns_rdatacallbacks_t callbacks; dns_rdatacallbacks_init(&callbacks); result = dns_db_beginload(db, &callbacks.add, &callbacks.add_private); if (result != ISC_R_SUCCESS) return (result); result = dns_master_loadfile(zone->masterfile, &zone->origin, &zone->origin, zone->rdclass, options, &callbacks, zone->mctx); tresult = dns_db_endload(db, &callbacks.add_private); if (result == ISC_R_SUCCESS) result = tresult; } else { result = dns_db_load(db, zone->masterfile); } return (result); cleanup: load->magic = 0; dns_db_detach(&load->db); zone_idetach(&load->zone); isc_mem_detach(&load->mctx); isc_mem_put(zone->mctx, load, sizeof(*load)); return (result);}static isc_result_tzone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, isc_result_t result){ unsigned int soacount = 0; unsigned int nscount = 0; isc_uint32_t serial, refresh, retry, expire, minimum; isc_time_t now; isc_boolean_t needdump = ISC_FALSE; isc_time_now(&now); /* * Initiate zone transfer? We may need a error code that * indicates that the "permanent" form does not exist. * XXX better error feedback to log. */ if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { if (zone->type == dns_zone_slave || zone->type == dns_zone_stub) { if (result == ISC_R_FILENOTFOUND) dns_zone_log(zone, ISC_LOG_DEBUG(1), "no master file"); else if (result != DNS_R_NOMASTERFILE) dns_zone_log(zone, ISC_LOG_ERROR, "loading master file %s: %s", zone->masterfile, dns_result_totext(result)); } else dns_zone_log(zone, ISC_LOG_ERROR, "loading master file %s: %s", zone->masterfile, dns_result_totext(result)); goto cleanup; } dns_zone_log(zone, ISC_LOG_DEBUG(2), "number of nodes in database: %u", dns_db_nodecount(db)); zone->loadtime = loadtime; dns_zone_log(zone, ISC_LOG_DEBUG(1), "loaded"); if (result == DNS_R_SEENINCLUDE) DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HASINCLUDE); else DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_HASINCLUDE); /* * Apply update log, if any. */ if (zone->journal != NULL && ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE)) { result = dns_journal_rollforward(zone->mctx, db, zone->journal); if (result != ISC_R_SUCCESS && result != ISC_R_NOTFOUND && result != DNS_R_UPTODATE && result != DNS_R_NOJOURNAL && result != ISC_R_RANGE) { dns_zone_log(zone, ISC_LOG_ERROR, "journal rollforward failed: %s", dns_result_totext(result)); goto cleanup; } if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) { dns_zone_log(zone, ISC_LOG_ERROR, "journal rollforward failed: " "journal out of sync with zone"); goto cleanup; } dns_zone_log(zone, ISC_LOG_DEBUG(1), "journal rollforward completed " "successfully: %s", dns_result_totext(result)); if (result == ISC_R_SUCCESS) needdump = ISC_TRUE; } /* * Obtain ns and soa counts for top of zone. */ nscount = 0; soacount = 0; INSIST(db != NULL); result = zone_get_from_db(db, &zone->origin, &nscount, &soacount, &serial, &refresh, &retry, &expire, &minimum); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, "could not find NS and/or SOA records"); } /* * Master / Slave / Stub zones require both NS and SOA records at * the top of the zone. */ switch (zone->type) { case dns_zone_master: case dns_zone_slave: case dns_zone_stub: if (soacount != 1) { dns_zone_log(zone, ISC_LOG_ERROR, "has %d SOA records", soacount); result = DNS_R_BADZONE; } if (nscount == 0) { dns_zone_log(zone, ISC_LOG_ERROR, "has no NS records"); result = DNS_R_BADZONE; } if (result != ISC_R_SUCCESS) goto cleanup; if (zone->db != NULL) { if (!isc_serial_ge(serial, zone->serial)) { dns_zone_log(zone, ISC_LOG_ERROR, "zone serial has gone backwards"); } } zone->serial = serial; zone->refresh = RANGE(refresh, zone->minrefresh, zone->maxrefresh); zone->retry = RANGE(retry, zone->minretry, zone->maxretry); zone->expire = RANGE(expire, zone->refresh + zone->retry, DNS_MAX_EXPIRE); zone->minimum = minimum; DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_HAVETIMERS); if (zone->type == dns_zone_slave || zone->type == dns_zone_stub) { isc_time_t t; isc_interval_t i; unsigned int delay; result = isc_file_getmodtime(zone->journal, &t); if (result != ISC_R_SUCCESS) result = isc_file_getmodtime(zone->masterfile, &t); if (result == ISC_R_SUCCESS) { isc_interval_set(&i, zone->expire, 0); isc_time_add(&t, &i, &zone->expiretime); } else { isc_interval_set(&i, zone->retry, 0); isc_time_add(&now, &i, &zone->expiretime); } delay = isc_random_jitter(zone->retry, (zone->retry * 3) / 4); isc_interval_set(&i, delay, 0); isc_time_add(&now, &i, &zone->refreshtime); if (isc_time_compare(&zone->refreshtime, &zone->expiretime) >= 0) zone->refreshtime = now; } break; default: UNEXPECTED_ERROR(__FILE__, __LINE__, "unexpected zone type %d", zone->type); result = ISC_R_UNEXPECTED; goto cleanup; }#if 0 /* destroy notification example. */ { isc_event_t *e = isc_event_allocate(zone->mctx, NULL, DNS_EVENT_DBDESTROYED, dns_zonemgr_dbdestroyed, zone, sizeof(isc_event_t)); dns_db_ondestroy(db, zone->task, &e); }#endif if (zone->db != NULL) { result = zone_replacedb(zone, db, ISC_FALSE); if (result != ISC_R_SUCCESS) goto cleanup; } else { dns_db_attach(db, &zone->db); DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADED|DNS_ZONEFLG_NEEDNOTIFY); } result = ISC_R_SUCCESS; if (needdump) zone_needdump(zone, DNS_DUMP_DELAY); if (zone->task != NULL) zone_settimer(zone, &now); dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u", zone->serial); return (result); cleanup: if (zone->type == dns_zone_slave || zone->type == dns_zone_stub) { if (zone->journal != NULL) zone_saveunique(zone, zone->journal, "jn-XXXXXXXX"); if (zone->masterfile != NULL) zone_saveunique(zone, zone->masterfile, "db-XXXXXXXX"); /* Mark the zone for immediate refresh. */ zone->refreshtime = now; if (zone->task != NULL) zone_settimer(zone, &now); result = ISC_R_SUCCESS; } return (result);}static isc_boolean_texit_check(dns_zone_t *zone) { REQUIRE(LOCKED_ZONE(zone)); if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_SHUTDOWN) && zone->irefs == 0) { /* * DNS_ZONEFLG_SHUTDOWN can only be set if erefs == 0. */ INSIST(isc_refcount_current(&zone->erefs) == 0); return (ISC_TRUE); } return (ISC_FALSE);}static isc_result_tzone_count_ns_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, unsigned int *nscount){ isc_result_t result; unsigned int count; dns_rdataset_t rdataset; REQUIRE(nscount != NULL); dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, version, dns_rdatatype_ns, dns_rdatatype_none, 0, &rdataset, NULL); if (result == ISC_R_NOTFOUND) { *nscount = 0; result = ISC_R_SUCCESS; goto invalidate_rdataset; } else if (result != ISC_R_SUCCESS) goto invalidate_rdataset; count = 0; result = dns_rdataset_first(&rdataset); while (result == ISC_R_SUCCESS) { count++; result = dns_rdataset_next(&rdataset); } dns_rdataset_disassociate(&rdataset); *nscount = count; result = ISC_R_SUCCESS; invalidate_rdataset: dns_rdataset_invalidate(&rdataset); return (result);}static isc_result_tzone_load_soa_rr(dns_db_t *db, dns_dbnode_t *node, dns_dbversion_t *version, unsigned int *soacount, isc_uint32_t *serial, isc_uint32_t *refresh, isc_uint32_t *retry, isc_uint32_t *expire, isc_uint32_t *minimum){ isc_result_t result; unsigned int count; dns_rdataset_t rdataset; dns_rdata_t rdata = DNS_RDATA_INIT; dns_rdata_soa_t soa; dns_rdataset_init(&rdataset); result = dns_db_findrdataset(db, node, version, dns_rdatatype_soa, dns_rdatatype_none, 0, &rdataset, NULL); if (result != ISC_R_SUCCESS) goto invalidate_rdataset; count = 0; result = dns_rdataset_first(&rdataset); while (result == ISC_R_SUCCESS) { dns_rdata_init(&rdata); dns_rdataset_current(&rdataset, &rdata); count++; if (count == 1) dns_rdata_tostruct(&rdata, &soa, NULL); result = dns_rdataset_next(&rdataset); dns_rdata_reset(&rdata); } dns_rdataset_disassociate(&rdataset); if (soacount != NULL) *soacount = count; if (count > 0) { if (serial != NULL) *serial = soa.serial; if (refresh != NULL) *refresh = soa.refresh; if (retry != NULL) *retry = soa.retry; if (expire != NULL) *expire = soa.expire; if (minimum != NULL) *minimum = soa.minimum; } result = ISC_R_SUCCESS; invalidate_rdataset: dns_rdataset_invalidate(&rdataset); return (result);}/* * zone must be locked. */static isc_result_tzone_get_from_db(dns_db_t *db, dns_name_t *origin, unsigned int *nscount, unsigned int *soacount, isc_uint32_t *serial, isc_uint32_t *refresh, isc_uint32_t *retry, isc_uint32_t *expire, isc_uint32_t *minimum){ dns_dbversion_t *version; isc_result_t result; isc_result_t answer = ISC_R_SUCCESS; dns_dbnode_t *node; REQUIRE(db != NULL); REQUIRE(origin != NULL); version = NULL; dns_db_currentversion(db, &version); node = NULL; result = dns_db_findnode(db, origin, ISC_FALSE, &node); if (result != ISC_R_SUCCESS) { answer = result; goto closeversion; } if (nscount != NULL) { result = zone_count_ns_rr(db, node, version, nscount); if (result != ISC_R_SUCCESS) answer = result; } if (soacount != NULL || serial != NULL || refresh != NULL || retry != NULL || expire != NULL || minimum != NULL) { result = zone_load_soa_rr(db, node, version, soacount, serial, refresh, retry, expire, minimum); if (result != ISC_R_SUCCESS) answer = result; } dns_db_detachnode(db, &node); closeversion: dns_db_closeversion(db, &version, ISC_FALSE); return (answer);}voiddns_zone_attach(dns_zone_t *source, dns_zone_t **target) { REQUIRE(DNS_ZONE_VALID(source)); REQUIRE(target != NULL && *target == NULL); isc_refcount_increment(&source->erefs, NULL); *target = source;}voiddns_zone_detach(dns_zone_t **zonep) { dns_zone_t *zone; unsigned int refs; isc_boolean_t free_now = ISC_FALSE; REQUIRE(zonep != NULL && DNS_ZONE_VALID(*zonep)); zone = *zonep; isc_refcount_decrement(&zone->erefs, &refs); if (refs == 0) { LOCK_ZONE(zone); /* * We just detached the last external reference. */ if (zone->task != NULL) { /* * This zone is being managed. Post * its control event and let it clean * up synchronously in the context of * its task. */ isc_event_t *ev = &zone->ctlevent; isc_task_send(zone->task, &ev); } else { /* * This zone is not being managed; it has * no task and can have no outstanding * events. Free it immediately. */ /* * Unmanaged zones should not have non-null views; * we have no way of detaching from the view here * without causing deadlock because this code is called * with the view already locked. */ INSIST(zone->view == NULL); free_now = ISC_TRUE; } UNLOCK_ZONE(zone); } *zonep = NULL; if (free_now) zone_free(zone);}voiddns_zone_iattach(dns_zone_t *source, dns_zone_t **target) { REQUIRE(DNS_ZONE_VALID(source)); REQUIRE(target != NULL && *target == NULL); LOCK_ZONE(source); zone_iattach(source, target); UNLOCK_ZONE(source);}static voidzone_iattach(dns_zone_t *source, dns_zone_t **target) { /* * 'source' locked by caller. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -