📄 zone.c
字号:
/* * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. *//* $Id: zone.c,v 1.333.2.23.2.50 2004/08/28 05:53:37 marka Exp $ */#include <config.h>#include <isc/file.h>#include <isc/mutex.h>#include <isc/print.h>#include <isc/random.h>#include <isc/ratelimiter.h>#include <isc/refcount.h>#include <isc/serial.h>#include <isc/string.h>#include <isc/taskpool.h>#include <isc/timer.h>#include <isc/util.h>#include <dns/acl.h>#include <dns/adb.h>#include <dns/callbacks.h>#include <dns/db.h>#include <dns/events.h>#include <dns/journal.h>#include <dns/log.h>#include <dns/master.h>#include <dns/masterdump.h>#include <dns/message.h>#include <dns/name.h>#include <dns/peer.h>#include <dns/rcode.h>#include <dns/rdataclass.h>#include <dns/rdatalist.h>#include <dns/rdataset.h>#include <dns/rdatastruct.h>#include <dns/rdatatype.h>#include <dns/request.h>#include <dns/resolver.h>#include <dns/result.h>#include <dns/stats.h>#include <dns/ssu.h>#include <dns/tsig.h>#include <dns/xfrin.h>#include <dns/zone.h>#define ZONE_MAGIC ISC_MAGIC('Z', 'O', 'N', 'E')#define DNS_ZONE_VALID(zone) ISC_MAGIC_VALID(zone, ZONE_MAGIC)#define NOTIFY_MAGIC ISC_MAGIC('N', 't', 'f', 'y')#define DNS_NOTIFY_VALID(notify) ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)#define STUB_MAGIC ISC_MAGIC('S', 't', 'u', 'b')#define DNS_STUB_VALID(stub) ISC_MAGIC_VALID(stub, STUB_MAGIC)#define ZONEMGR_MAGIC ISC_MAGIC('Z', 'm', 'g', 'r')#define DNS_ZONEMGR_VALID(stub) ISC_MAGIC_VALID(stub, ZONEMGR_MAGIC)#define LOAD_MAGIC ISC_MAGIC('L', 'o', 'a', 'd')#define DNS_LOAD_VALID(load) ISC_MAGIC_VALID(load, LOAD_MAGIC)#define FORWARD_MAGIC ISC_MAGIC('F', 'o', 'r', 'w')#define DNS_FORWARD_VALID(load) ISC_MAGIC_VALID(load, FORWARD_MAGIC)#define IO_MAGIC ISC_MAGIC('Z', 'm', 'I', 'O')#define DNS_IO_VALID(load) ISC_MAGIC_VALID(load, IO_MAGIC)/* * Ensure 'a' is at least 'min' but not more than 'max'. */#define RANGE(a, min, max) \ (((a) < (min)) ? (min) : ((a) < (max) ? (a) : (max)))/* * Default values. */#define DNS_DEFAULT_IDLEIN 3600 /* 1 hour */#define DNS_DEFAULT_IDLEOUT 3600 /* 1 hour */#define MAX_XFER_TIME (2*3600) /* Documented default is 2 hours */#ifndef DNS_MAX_EXPIRE#define DNS_MAX_EXPIRE 14515200 /* 24 weeks */#endif#ifndef DNS_DUMP_DELAY#define DNS_DUMP_DELAY 900 /* 15 minutes */#endiftypedef struct dns_notify dns_notify_t;typedef struct dns_stub dns_stub_t;typedef struct dns_load dns_load_t;typedef struct dns_forward dns_forward_t;typedef struct dns_io dns_io_t;typedef ISC_LIST(dns_io_t) dns_iolist_t;#define DNS_ZONE_CHECKLOCK#ifdef DNS_ZONE_CHECKLOCK#define LOCK_ZONE(z) \ do { LOCK(&(z)->lock); \ INSIST((z)->locked == ISC_FALSE); \ (z)->locked = ISC_TRUE; \ } while (0)#define UNLOCK_ZONE(z) \ do { (z)->locked = ISC_FALSE; UNLOCK(&(z)->lock); } while (0)#define LOCKED_ZONE(z) ((z)->locked)#else#define LOCK_ZONE(z) LOCK(&(z)->lock)#define UNLOCK_ZONE(z) UNLOCK(&(z)->lock)#define LOCKED_ZONE(z) ISC_TRUE#endifstruct dns_zone { /* Unlocked */ unsigned int magic; isc_mutex_t lock;#ifdef DNS_ZONE_CHECKLOCK isc_boolean_t locked;#endif isc_mem_t *mctx; isc_refcount_t erefs; /* Locked */ dns_db_t *db; dns_zonemgr_t *zmgr; ISC_LINK(dns_zone_t) link; /* Used by zmgr. */ isc_timer_t *timer; unsigned int irefs; dns_name_t origin; char *masterfile; char *journal; isc_int32_t journalsize; dns_rdataclass_t rdclass; dns_zonetype_t type; unsigned int flags; unsigned int options; unsigned int db_argc; char **db_argv; isc_time_t expiretime; isc_time_t refreshtime; isc_time_t dumptime; isc_time_t loadtime; isc_uint32_t serial; isc_uint32_t refresh; isc_uint32_t retry; isc_uint32_t expire; isc_uint32_t minimum; char *keydirectory; isc_uint32_t maxrefresh; isc_uint32_t minrefresh; isc_uint32_t maxretry; isc_uint32_t minretry; isc_sockaddr_t *masters; dns_name_t **masterkeynames; unsigned int masterscnt; unsigned int curmaster; isc_sockaddr_t masteraddr; dns_notifytype_t notifytype; isc_sockaddr_t *notify; unsigned int notifycnt; isc_sockaddr_t notifyfrom; isc_task_t *task; isc_sockaddr_t notifysrc4; isc_sockaddr_t notifysrc6; isc_sockaddr_t xfrsource4; isc_sockaddr_t xfrsource6; isc_sockaddr_t altxfrsource4; isc_sockaddr_t altxfrsource6; isc_sockaddr_t sourceaddr; dns_xfrin_ctx_t *xfr; /* task locked */ dns_tsigkey_t *tsigkey; /* key used for xfr */ /* Access Control Lists */ dns_acl_t *update_acl; dns_acl_t *forward_acl; dns_acl_t *notify_acl; dns_acl_t *query_acl; dns_acl_t *xfr_acl; isc_boolean_t update_disabled; dns_severity_t check_names; ISC_LIST(dns_notify_t) notifies; dns_request_t *request; dns_loadctx_t *lctx; dns_io_t *readio; dns_dumpctx_t *dctx; dns_io_t *writeio; isc_uint32_t maxxfrin; isc_uint32_t maxxfrout; isc_uint32_t idlein; isc_uint32_t idleout; isc_event_t ctlevent; dns_ssutable_t *ssutable; isc_uint32_t sigvalidityinterval; dns_view_t *view; /* * Zones in certain states such as "waiting for zone transfer" * or "zone transfer in progress" are kept on per-state linked lists * in the zone manager using the 'statelink' field. The 'statelist' * field points at the list the zone is currently on. It the zone * is not on any such list, statelist is NULL. */ ISC_LINK(dns_zone_t) statelink; dns_zonelist_t *statelist; /* * Optional per-zone statistics counters (NULL if not present). */ isc_uint64_t *counters;};#define DNS_ZONE_FLAG(z,f) (ISC_TF(((z)->flags & (f)) != 0))#define DNS_ZONE_SETFLAG(z,f) do { \ INSIST(LOCKED_ZONE(z)); \ (z)->flags |= (f); \ } while (0)#define DNS_ZONE_CLRFLAG(z,f) do { \ INSIST(LOCKED_ZONE(z)); \ (z)->flags &= ~(f); \ } while (0) /* XXX MPA these may need to go back into zone.h */#define DNS_ZONEFLG_REFRESH 0x00000001U /* refresh check in progress */#define DNS_ZONEFLG_NEEDDUMP 0x00000002U /* zone need consolidation */#define DNS_ZONEFLG_USEVC 0x00000004U /* use tcp for refresh query */#define DNS_ZONEFLG_DUMPING 0x00000008U /* a dump is in progress */#define DNS_ZONEFLG_HASINCLUDE 0x00000010U /* $INCLUDE in zone file */#define DNS_ZONEFLG_LOADED 0x00000020U /* database has loaded */#define DNS_ZONEFLG_EXITING 0x00000040U /* zone is being destroyed */#define DNS_ZONEFLG_EXPIRED 0x00000080U /* zone has expired */#define DNS_ZONEFLG_NEEDREFRESH 0x00000100U /* refresh check needed */#define DNS_ZONEFLG_UPTODATE 0x00000200U /* zone contents are * uptodate */#define DNS_ZONEFLG_NEEDNOTIFY 0x00000400U /* need to send out notify * messages */#define DNS_ZONEFLG_DIFFONRELOAD 0x00000800U /* generate a journal diff on * reload */#define DNS_ZONEFLG_NOMASTERS 0x00001000U /* an attempt to refresh a * zone with no masters * occured */#define DNS_ZONEFLG_LOADING 0x00002000U /* load from disk in progress*/#define DNS_ZONEFLG_HAVETIMERS 0x00004000U /* timer values have been set * from SOA (if not set, we * are still using * default timer values) */#define DNS_ZONEFLG_FORCEXFER 0x00008000U /* Force a zone xfer */#define DNS_ZONEFLG_NOREFRESH 0x00010000U#define DNS_ZONEFLG_DIALNOTIFY 0x00020000U#define DNS_ZONEFLG_DIALREFRESH 0x00040000U#define DNS_ZONEFLG_SHUTDOWN 0x00080000U#define DNS_ZONEFLAG_NOIXFR 0x00100000U /* IXFR failed, force AXFR */#define DNS_ZONEFLG_FLUSH 0x00200000U#define DNS_ZONEFLG_NOEDNS 0x00400000U#define DNS_ZONEFLG_USEALTXFRSRC 0x00800000U#define DNS_ZONE_OPTION(z,o) (((z)->options & (o)) != 0)/* Flags for zone_load() */#define DNS_ZONELOADFLAG_NOSTAT 0x00000001U /* Do not stat() master files */struct dns_zonemgr { unsigned int magic; isc_mem_t * mctx; int refs; /* Locked by rwlock */ isc_taskmgr_t * taskmgr; isc_timermgr_t * timermgr; isc_socketmgr_t * socketmgr; isc_taskpool_t * zonetasks; isc_task_t * task; isc_ratelimiter_t * rl; isc_rwlock_t rwlock; isc_mutex_t iolock; /* Locked by rwlock. */ dns_zonelist_t zones; dns_zonelist_t waiting_for_xfrin; dns_zonelist_t xfrin_in_progress; /* Configuration data. */ isc_uint32_t transfersin; isc_uint32_t transfersperns; unsigned int serialqueryrate; /* Locked by iolock */ isc_uint32_t iolimit; isc_uint32_t ioactive; dns_iolist_t high; dns_iolist_t low;};/* * Hold notify state. */struct dns_notify { unsigned int magic; unsigned int flags; isc_mem_t *mctx; dns_zone_t *zone; dns_adbfind_t *find; dns_request_t *request; dns_name_t ns; isc_sockaddr_t dst; ISC_LINK(dns_notify_t) link;};#define DNS_NOTIFY_NOSOA 0x0001U/* * dns_stub holds state while performing a 'stub' transfer. * 'db' is the zone's 'db' or a new one if this is the initial * transfer. */struct dns_stub { unsigned int magic; isc_mem_t *mctx; dns_zone_t *zone; dns_db_t *db; dns_dbversion_t *version;};/* * Hold load state. */struct dns_load { unsigned int magic; isc_mem_t *mctx; dns_zone_t *zone; dns_db_t *db; isc_time_t loadtime; dns_rdatacallbacks_t callbacks;};/* * Hold forward state. */struct dns_forward { unsigned int magic; isc_mem_t *mctx; dns_zone_t *zone; isc_buffer_t *msgbuf; dns_request_t *request; isc_uint32_t which; isc_sockaddr_t addr; dns_updatecallback_t callback; void *callback_arg;};/* * Hold IO request state. */struct dns_io { unsigned int magic; dns_zonemgr_t *zmgr; isc_boolean_t high; isc_task_t *task; ISC_LINK(dns_io_t) link; isc_event_t *event;};#define SEND_BUFFER_SIZE 2048static void zone_settimer(dns_zone_t *, isc_time_t *);static void cancel_refresh(dns_zone_t *);static void zone_debuglog(dns_zone_t *zone, const char *, int debuglevel, const char *msg, ...) ISC_FORMAT_PRINTF(4, 5);static void notify_log(dns_zone_t *zone, int level, const char *fmt, ...) ISC_FORMAT_PRINTF(3, 4);static void queue_xfrin(dns_zone_t *zone);static void zone_unload(dns_zone_t *zone);static void zone_expire(dns_zone_t *zone);static void zone_iattach(dns_zone_t *source, dns_zone_t **target);static void zone_idetach(dns_zone_t **zonep);static isc_result_t zone_replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump);static isc_result_t default_journal(dns_zone_t *zone);static void zone_xfrdone(dns_zone_t *zone, isc_result_t result);static isc_result_t zone_postload(dns_zone_t *zone, dns_db_t *db, isc_time_t loadtime, isc_result_t result);static void zone_needdump(dns_zone_t *zone, unsigned int delay);static void zone_shutdown(isc_task_t *, isc_event_t *);static void zone_loaddone(void *arg, isc_result_t result);static isc_result_t zone_startload(dns_db_t *db, dns_zone_t *zone, isc_time_t loadtime);#if 0/* ondestroy example */static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);#endifstatic void refresh_callback(isc_task_t *, isc_event_t *);static void stub_callback(isc_task_t *, isc_event_t *);static void queue_soa_query(dns_zone_t *zone);static void soa_query(isc_task_t *, isc_event_t *);static void ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub);static int message_count(dns_message_t *msg, dns_section_t section, dns_rdatatype_t type);static void notify_cancel(dns_zone_t *zone);static void notify_find_address(dns_notify_t *notify);static void notify_send(dns_notify_t *notify);static isc_result_t notify_createmessage(dns_zone_t *zone, unsigned int flags, dns_message_t **messagep);static void notify_done(isc_task_t *task, isc_event_t *event);static void notify_send_toaddr(isc_task_t *task, isc_event_t *event);static isc_result_t zone_dump(dns_zone_t *, isc_boolean_t);static void got_transfer_quota(isc_task_t *task, isc_event_t *event);static isc_result_t zmgr_start_xfrin_ifquota(dns_zonemgr_t *zmgr, dns_zone_t *zone);static void zmgr_resume_xfrs(dns_zonemgr_t *zmgr, isc_boolean_t multi);static void zonemgr_free(dns_zonemgr_t *zmgr);static isc_result_t zonemgr_getio(dns_zonemgr_t *zmgr, isc_boolean_t high, isc_task_t *task, isc_taskaction_t action, void *arg, dns_io_t **iop);static void zonemgr_putio(dns_io_t **iop);static void zonemgr_cancelio(dns_io_t *io);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);static void zone_freedbargs(dns_zone_t *zone);static void forward_callback(isc_task_t *task, isc_event_t *event);static void zone_saveunique(dns_zone_t *zone, const char *path, const char *templat);static void zone_maintenance(dns_zone_t *zone);static void zone_notify(dns_zone_t *zone);static void dump_done(void *arg, isc_result_t result);#define ENTER zone_debuglog(zone, me, 1, "enter")static const unsigned int dbargc_default = 1;static const char *dbargv_default[] = { "rbt" };#define DNS_ZONE_JITTER_ADD(a, b, c) \ do { \ isc_interval_t _i; \ isc_uint32_t _j; \ _j = isc_random_jitter((b), (b)/4); \ isc_interval_set(&_i, _j, 0); \ if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \ dns_zone_log(zone, ISC_LOG_WARNING, \ "epoch approaching: upgrade required: " \ "now + %s failed", #b); \ isc_interval_set(&_i, _j/2, 0); \ (void)isc_time_add((a), &_i, (c)); \ } \ } while (0)#define DNS_ZONE_TIME_ADD(a, b, c) \ do { \ isc_interval_t _i; \ isc_interval_set(&_i, (b), 0); \ if (isc_time_add((a), &_i, (c)) != ISC_R_SUCCESS) { \ dns_zone_log(zone, ISC_LOG_WARNING, \ "epoch approaching: upgrade required: " \ "now + %s failed", #b); \ isc_interval_set(&_i, (b)/2, 0); \ (void)isc_time_add((a), &_i, (c)); \ } \ } while (0)/*** *** Public functions. ***/isc_result_tdns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { isc_result_t result; dns_zone_t *zone; REQUIRE(zonep != NULL && *zonep == NULL); REQUIRE(mctx != NULL); zone = isc_mem_get(mctx, sizeof(*zone)); if (zone == NULL) return (ISC_R_NOMEMORY); result = isc_mutex_init(&zone->lock); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, zone, sizeof(*zone)); UNEXPECTED_ERROR(__FILE__, __LINE__, "isc_mutex_init() failed: %s", isc_result_totext(result)); return (ISC_R_UNEXPECTED); } /* XXX MPA check that all elements are initialised */ zone->mctx = NULL;#ifdef DNS_ZONE_CHECKLOCK zone->locked = ISC_FALSE;#endif isc_mem_attach(mctx, &zone->mctx); zone->db = NULL; zone->zmgr = NULL; ISC_LINK_INIT(zone, link); isc_refcount_init(&zone->erefs, 1); /* Implicit attach. */ zone->irefs = 0; dns_name_init(&zone->origin, NULL); zone->masterfile = NULL; zone->keydirectory = NULL; zone->journalsize = -1; zone->journal = NULL; zone->rdclass = dns_rdataclass_none; zone->type = dns_zone_none; zone->flags = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -