📄 zone.c
字号:
&db); if (result != ISC_R_SUCCESS) { dns_zone_log(zone, ISC_LOG_ERROR, "loading zone: creating database: %s", isc_result_totext(result)); goto cleanup; } dns_db_settask(db, zone->task); if (! dns_db_ispersistent(db)) { if (zone->masterfile != NULL) { result = zone_startload(db, zone, loadtime); } else { result = DNS_R_NOMASTERFILE; if (zone->type == dns_zone_master) { dns_zone_log(zone, ISC_LOG_ERROR, "loading zone: " "no master file configured"); goto cleanup; } dns_zone_log(zone, ISC_LOG_INFO, "loading zone: " "no master file configured: continuing"); } } if (result == DNS_R_CONTINUE) { DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_LOADING); goto cleanup; } result = zone_postload(zone, db, loadtime, result); cleanup: UNLOCK_ZONE(zone); if (db != NULL) dns_db_detach(&db); return (result);}isc_result_tdns_zone_load(dns_zone_t *zone) { return (zone_load(zone, 0));}isc_result_tdns_zone_loadnew(dns_zone_t *zone) { return (zone_load(zone, DNS_ZONELOADFLAG_NOSTAT));}static voidzone_gotreadhandle(isc_task_t *task, isc_event_t *event) { dns_load_t *load = event->ev_arg; isc_result_t result = ISC_R_SUCCESS; unsigned int options; REQUIRE(DNS_LOAD_VALID(load)); if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) result = ISC_R_CANCELED; isc_event_free(&event); if (result == ISC_R_CANCELED) goto fail; options = DNS_MASTER_ZONE; if (load->zone->type == dns_zone_slave) options |= DNS_MASTER_SLAVE; if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNS)) options |= DNS_MASTER_CHECKNS; if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_FATALNS)) options |= DNS_MASTER_FATALNS; if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNAMES)) options |= DNS_MASTER_CHECKNAMES; if (DNS_ZONE_OPTION(load->zone, DNS_ZONEOPT_CHECKNAMESFAIL)) options |= DNS_MASTER_CHECKNAMESFAIL; 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 voidzone_gotwritehandle(isc_task_t *task, isc_event_t *event) { const char me[] = "zone_gotwritehandle"; dns_zone_t *zone = event->ev_arg; isc_result_t result = ISC_R_SUCCESS; dns_dbversion_t *version = NULL; REQUIRE(DNS_ZONE_VALID(zone)); INSIST(task == zone->task); ENTER; if ((event->ev_attributes & ISC_EVENTATTR_CANCELED) != 0) result = ISC_R_CANCELED; isc_event_free(&event); if (result == ISC_R_CANCELED) goto fail; LOCK_ZONE(zone); dns_db_currentversion(zone->db, &version); result = dns_master_dumpinc(zone->mctx, zone->db, version, &dns_master_style_default, zone->masterfile, zone->task, dump_done, zone, &zone->dctx); dns_db_closeversion(zone->db, &version, ISC_FALSE); UNLOCK_ZONE(zone); if (result != DNS_R_CONTINUE) goto fail; return; fail: dump_done(zone, 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 (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNS)) options |= DNS_MASTER_CHECKNS; if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_FATALNS)) options |= DNS_MASTER_FATALNS; if (zone->type == dns_zone_slave) options |= DNS_MASTER_SLAVE; if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMES)) options |= DNS_MASTER_CHECKNAMES; if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_CHECKNAMESFAIL)) options |= DNS_MASTER_CHECKNAMESFAIL; 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 { 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; } 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; 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, on initial load. */ if (zone->journal != NULL && ! DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOMERGE) && ! DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) { 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_uint32_t 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) DNS_ZONE_TIME_ADD(&t, zone->expire, &zone->expiretime); else DNS_ZONE_TIME_ADD(&now, zone->retry, &zone->expiretime); delay = isc_random_jitter(zone->retry, (zone->retry * 3) / 4); DNS_ZONE_TIME_ADD(&now, delay, &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); if (! dns_db_ispersistent(db)) dns_zone_log(zone, ISC_LOG_INFO, "loaded serial %u%s", zone->serial, dns_db_issecure(db) ? " (signed)" : ""); 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) { result = dns_rdata_tostruct(&rdata, &soa, NULL); RUNTIME_CHECK(result == ISC_R_SUCCESS); } 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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -