mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-31 22:45:39 +00:00
240. [func] databases now come in three flavours: zone, cache
and stub. Add stubs zones support checkpoint. notify_t -> dns_notify_t
This commit is contained in:
524
lib/dns/zone.c
524
lib/dns/zone.c
@@ -15,7 +15,7 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* $Id: zone.c,v 1.142 2000/06/05 21:54:28 gson Exp $ */
|
/* $Id: zone.c,v 1.143 2000/06/07 02:40:42 marka Exp $ */
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
@@ -51,11 +51,14 @@
|
|||||||
|
|
||||||
#define ZONE_MAGIC 0x5a4f4e45U /* ZONE */
|
#define ZONE_MAGIC 0x5a4f4e45U /* ZONE */
|
||||||
#define NOTIFY_MAGIC 0x4e746679U /* Ntfy */
|
#define NOTIFY_MAGIC 0x4e746679U /* Ntfy */
|
||||||
|
#define STUB_MAGIC 0x53747562U /* Stub */
|
||||||
|
|
||||||
#define DNS_ZONE_VALID(zone) \
|
#define DNS_ZONE_VALID(zone) \
|
||||||
ISC_MAGIC_VALID(zone, ZONE_MAGIC)
|
ISC_MAGIC_VALID(zone, ZONE_MAGIC)
|
||||||
#define DNS_NOTIFY_VALID(notify) \
|
#define DNS_NOTIFY_VALID(notify) \
|
||||||
ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
|
ISC_MAGIC_VALID(notify, NOTIFY_MAGIC)
|
||||||
|
#define DNS_STUB_VALID(stub) \
|
||||||
|
ISC_MAGIC_VALID(stub, STUB_MAGIC)
|
||||||
|
|
||||||
#define RANGE(a, b, c) (((a) < (b)) ? (b) : ((a) < (c) ? (a) : (c)))
|
#define RANGE(a, b, c) (((a) < (b)) ? (b) : ((a) < (c) ? (a) : (c)))
|
||||||
|
|
||||||
@@ -78,7 +81,8 @@
|
|||||||
#define MAX_XFER_TIME (2*3600) /* Documented default is 2 hours */
|
#define MAX_XFER_TIME (2*3600) /* Documented default is 2 hours */
|
||||||
|
|
||||||
|
|
||||||
typedef struct notify notify_t;
|
typedef struct dns_notify dns_notify_t;
|
||||||
|
typedef struct dns_stub dns_stub_t;
|
||||||
|
|
||||||
struct dns_zone {
|
struct dns_zone {
|
||||||
/* Unlocked */
|
/* Unlocked */
|
||||||
@@ -129,7 +133,7 @@ struct dns_zone {
|
|||||||
dns_acl_t *query_acl;
|
dns_acl_t *query_acl;
|
||||||
dns_acl_t *xfr_acl;
|
dns_acl_t *xfr_acl;
|
||||||
dns_severity_t check_names;
|
dns_severity_t check_names;
|
||||||
ISC_LIST(notify_t) notifies;
|
ISC_LIST(dns_notify_t) notifies;
|
||||||
dns_request_t *request;
|
dns_request_t *request;
|
||||||
isc_uint32_t maxxfrin;
|
isc_uint32_t maxxfrin;
|
||||||
isc_uint32_t maxxfrout;
|
isc_uint32_t maxxfrout;
|
||||||
@@ -156,7 +160,7 @@ struct dns_zone {
|
|||||||
/* XXX MPA these may need to go back into zone.h */
|
/* XXX MPA these may need to go back into zone.h */
|
||||||
#define DNS_ZONE_F_REFRESH 0x00000001U /* refresh check in progress */
|
#define DNS_ZONE_F_REFRESH 0x00000001U /* refresh check in progress */
|
||||||
#define DNS_ZONE_F_NEEDDUMP 0x00000002U /* zone need consolidation */
|
#define DNS_ZONE_F_NEEDDUMP 0x00000002U /* zone need consolidation */
|
||||||
/* #define DNS_ZONE_F_UNUSED 0x00000004U */ /* unused */
|
#define DNS_ZONE_F_USEVC 0x00000004U /* use tcp for refresh query */
|
||||||
/* #define DNS_ZONE_F_UNUSED 0x00000008U */ /* unused */
|
/* #define DNS_ZONE_F_UNUSED 0x00000008U */ /* unused */
|
||||||
/* #define DNS_ZONE_F_UNUSED 0x00000010U */ /* unused */
|
/* #define DNS_ZONE_F_UNUSED 0x00000010U */ /* unused */
|
||||||
#define DNS_ZONE_F_LOADED 0x00000020U /* database has loaded */
|
#define DNS_ZONE_F_LOADED 0x00000020U /* database has loaded */
|
||||||
@@ -199,7 +203,7 @@ struct dns_zonemgr {
|
|||||||
/*
|
/*
|
||||||
* Hold notify state.
|
* Hold notify state.
|
||||||
*/
|
*/
|
||||||
struct notify {
|
struct dns_notify {
|
||||||
isc_int32_t magic;
|
isc_int32_t magic;
|
||||||
isc_mem_t *mctx;
|
isc_mem_t *mctx;
|
||||||
dns_zone_t *zone;
|
dns_zone_t *zone;
|
||||||
@@ -207,7 +211,21 @@ struct notify {
|
|||||||
dns_request_t *request;
|
dns_request_t *request;
|
||||||
dns_name_t ns;
|
dns_name_t ns;
|
||||||
isc_sockaddr_t dst;
|
isc_sockaddr_t dst;
|
||||||
ISC_LINK(notify_t) link;
|
ISC_LINK(dns_notify_t) link;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 {
|
||||||
|
isc_int32_t magic;
|
||||||
|
isc_mem_t *mctx;
|
||||||
|
dns_zone_t *zone;
|
||||||
|
dns_db_t *db;
|
||||||
|
dns_dbversion_t *version;
|
||||||
};
|
};
|
||||||
|
|
||||||
static isc_result_t zone_settimer(dns_zone_t *, isc_stdtime_t);
|
static isc_result_t zone_settimer(dns_zone_t *, isc_stdtime_t);
|
||||||
@@ -232,12 +250,15 @@ static void dns_zonemgr_dbdestroyed(isc_task_t *task, isc_event_t *event);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void refresh_callback(isc_task_t *, isc_event_t *);
|
static 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 queue_soa_query(dns_zone_t *zone);
|
||||||
static void soa_query(isc_task_t *, isc_event_t *);
|
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,
|
static int message_count(dns_message_t *msg, dns_section_t section,
|
||||||
dns_rdatatype_t type);
|
dns_rdatatype_t type);
|
||||||
static void notify_find_address(notify_t *notify);
|
static void notify_find_address(dns_notify_t *notify);
|
||||||
static void notify_send(notify_t *notify);
|
static void notify_send(dns_notify_t *notify);
|
||||||
static isc_result_t notify_createmessage(dns_zone_t *zone,
|
static isc_result_t notify_createmessage(dns_zone_t *zone,
|
||||||
dns_message_t **messagep);
|
dns_message_t **messagep);
|
||||||
static void notify_done(isc_task_t *task, isc_event_t *event);
|
static void notify_done(isc_task_t *task, isc_event_t *event);
|
||||||
@@ -628,9 +649,10 @@ dns_zone_load(dns_zone_t *zone) {
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
result = dns_db_create(zone->mctx, zone->db_type,
|
result = dns_db_create(zone->mctx, zone->db_type,
|
||||||
&zone->origin,
|
&zone->origin, (zone->type == dns_zone_stub) ?
|
||||||
ISC_FALSE, zone->rdclass,
|
dns_dbtype_stub : dns_dbtype_zone,
|
||||||
zone->db_argc, zone->db_argv, &db);
|
zone->rdclass, zone->db_argc, zone->db_argv,
|
||||||
|
&db);
|
||||||
|
|
||||||
if (result != ISC_R_SUCCESS)
|
if (result != ISC_R_SUCCESS)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@@ -643,7 +665,8 @@ dns_zone_load(dns_zone_t *zone) {
|
|||||||
* XXX better error feedback to log.
|
* XXX better error feedback to log.
|
||||||
*/
|
*/
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
if (zone->type == dns_zone_slave) {
|
if (zone->type == dns_zone_slave ||
|
||||||
|
zone->type == dns_zone_stub) {
|
||||||
zone_log(zone, me, ISC_LOG_INFO,
|
zone_log(zone, me, ISC_LOG_INFO,
|
||||||
"no database file");
|
"no database file");
|
||||||
/* Mark the zone for immediate refresh. */
|
/* Mark the zone for immediate refresh. */
|
||||||
@@ -1539,7 +1562,7 @@ dns_zone_setrefresh(dns_zone_t *zone, isc_uint32_t refresh,
|
|||||||
|
|
||||||
static isc_boolean_t
|
static isc_boolean_t
|
||||||
notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
|
notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
|
||||||
notify_t *notify;
|
dns_notify_t *notify;
|
||||||
|
|
||||||
for (notify = ISC_LIST_HEAD(zone->notifies);
|
for (notify = ISC_LIST_HEAD(zone->notifies);
|
||||||
notify != NULL;
|
notify != NULL;
|
||||||
@@ -1556,7 +1579,7 @@ notify_isqueued(dns_zone_t *zone, dns_name_t *name, isc_sockaddr_t *addr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
notify_destroy(notify_t *notify) {
|
notify_destroy(dns_notify_t *notify) {
|
||||||
isc_mem_t *mctx;
|
isc_mem_t *mctx;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1581,8 +1604,8 @@ notify_destroy(notify_t *notify) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
notify_create(isc_mem_t *mctx, notify_t **notifyp) {
|
notify_create(isc_mem_t *mctx, dns_notify_t **notifyp) {
|
||||||
notify_t *notify;
|
dns_notify_t *notify;
|
||||||
|
|
||||||
REQUIRE(notifyp != NULL && *notifyp == NULL);
|
REQUIRE(notifyp != NULL && *notifyp == NULL);
|
||||||
|
|
||||||
@@ -1608,7 +1631,7 @@ notify_create(isc_mem_t *mctx, notify_t **notifyp) {
|
|||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
process_adb_event(isc_task_t *task, isc_event_t *ev) {
|
process_adb_event(isc_task_t *task, isc_event_t *ev) {
|
||||||
notify_t *notify;
|
dns_notify_t *notify;
|
||||||
isc_eventtype_t result;
|
isc_eventtype_t result;
|
||||||
dns_zone_t *zone = NULL;
|
dns_zone_t *zone = NULL;
|
||||||
|
|
||||||
@@ -1638,7 +1661,7 @@ process_adb_event(isc_task_t *task, isc_event_t *ev) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
notify_find_address(notify_t *notify) {
|
notify_find_address(dns_notify_t *notify) {
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
unsigned int options;
|
unsigned int options;
|
||||||
dns_zone_t *zone = NULL;
|
dns_zone_t *zone = NULL;
|
||||||
@@ -1679,7 +1702,7 @@ notify_find_address(notify_t *notify) {
|
|||||||
|
|
||||||
|
|
||||||
static isc_result_t
|
static isc_result_t
|
||||||
notify_send_queue(notify_t *notify) {
|
notify_send_queue(dns_notify_t *notify) {
|
||||||
isc_event_t *e;
|
isc_event_t *e;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
|
|
||||||
@@ -1700,7 +1723,7 @@ notify_send_queue(notify_t *notify) {
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
|
notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
|
||||||
notify_t *notify;
|
dns_notify_t *notify;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
dns_message_t *message = NULL;
|
dns_message_t *message = NULL;
|
||||||
dns_zone_t *zone = NULL;
|
dns_zone_t *zone = NULL;
|
||||||
@@ -1754,12 +1777,12 @@ notify_send_toaddr(isc_task_t *task, isc_event_t *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
notify_send(notify_t *notify) {
|
notify_send(dns_notify_t *notify) {
|
||||||
dns_adbaddrinfo_t *ai;
|
dns_adbaddrinfo_t *ai;
|
||||||
isc_sockaddr_t dst;
|
isc_sockaddr_t dst;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
dns_message_t *message = NULL;
|
dns_message_t *message = NULL;
|
||||||
notify_t *new = NULL;
|
dns_notify_t *new = NULL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Zone lock held by caller.
|
* Zone lock held by caller.
|
||||||
@@ -1808,7 +1831,7 @@ dns_zone_notify(dns_zone_t *zone) {
|
|||||||
dns_rdataset_t nsrdset;
|
dns_rdataset_t nsrdset;
|
||||||
dns_rdataset_t soardset;
|
dns_rdataset_t soardset;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
notify_t *notify = NULL;
|
dns_notify_t *notify = NULL;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
isc_sockaddr_t dst;
|
isc_sockaddr_t dst;
|
||||||
isc_boolean_t isqueued;
|
isc_boolean_t isqueued;
|
||||||
@@ -1948,6 +1971,256 @@ dns_zone_notify(dns_zone_t *zone) {
|
|||||||
*** Private
|
*** Private
|
||||||
***/
|
***/
|
||||||
|
|
||||||
|
static void
|
||||||
|
stub_callback(isc_task_t *task, isc_event_t *event) {
|
||||||
|
const char me[] = "stub_callback";
|
||||||
|
dns_requestevent_t *revent = (dns_requestevent_t *)event;
|
||||||
|
dns_stub_t *stub = NULL;
|
||||||
|
dns_message_t *msg = NULL;
|
||||||
|
dns_zone_t *zone = NULL;
|
||||||
|
char master[ISC_SOCKADDR_FORMATSIZE];
|
||||||
|
isc_uint32_t nscnt, cnamecnt;
|
||||||
|
isc_result_t result;
|
||||||
|
isc_stdtime_t now;
|
||||||
|
dns_rdata_ns_t ns;
|
||||||
|
dns_rdataset_t *nsrdataset = NULL;
|
||||||
|
dns_rdataset_t *rdataset = NULL;
|
||||||
|
dns_dbnode_t *node = NULL;
|
||||||
|
dns_rdata_t rdata;
|
||||||
|
|
||||||
|
stub = revent->ev_arg;
|
||||||
|
INSIST(DNS_STUB_VALID(stub));
|
||||||
|
|
||||||
|
UNUSED(task);
|
||||||
|
|
||||||
|
/* XXX add test for exiting */
|
||||||
|
|
||||||
|
dns_zone_iattach(stub->zone, &zone);
|
||||||
|
|
||||||
|
DNS_ENTER;
|
||||||
|
|
||||||
|
isc_stdtime_get(&now);
|
||||||
|
|
||||||
|
if (revent->result != ISC_R_SUCCESS) {
|
||||||
|
zone_log(zone, me, ISC_LOG_INFO, "failure for %s: %s",
|
||||||
|
master, dns_result_totext(revent->result));
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTPARSE, &msg);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto next_master;
|
||||||
|
result = dns_request_getresponse(revent->request, msg, ISC_FALSE);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto next_master;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unexpected rcode.
|
||||||
|
*/
|
||||||
|
if (msg->rcode != dns_rcode_noerror) {
|
||||||
|
char rcode[128];
|
||||||
|
isc_buffer_t rb;
|
||||||
|
|
||||||
|
isc_buffer_init(&rb, rcode, sizeof(rcode));
|
||||||
|
dns_rcode_totext(msg->rcode, &rb);
|
||||||
|
|
||||||
|
zone_log(zone, me, ISC_LOG_INFO,
|
||||||
|
"unexpected rcode (%.*s) from %s",
|
||||||
|
rb.used, rcode, master);
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
|
||||||
|
if (dns_request_usedtcp(revent->request)) {
|
||||||
|
/* XXX log failure */
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
LOCK(&zone->lock);
|
||||||
|
zone->flags |= DNS_ZONE_F_USEVC;
|
||||||
|
UNLOCK(&zone->lock);
|
||||||
|
goto same_master;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* if non-auth log and next master;
|
||||||
|
*/
|
||||||
|
if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) {
|
||||||
|
zone_log(zone, me, ISC_LOG_INFO,
|
||||||
|
"non-authorative answer from %s", master);
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnamecnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_cname);
|
||||||
|
nscnt = message_count(msg, DNS_SECTION_ANSWER, dns_rdatatype_ns);
|
||||||
|
|
||||||
|
if (cnamecnt != 0) {
|
||||||
|
zone_log(zone, me, ISC_LOG_INFO,
|
||||||
|
"found unexpected CNAME %s", master);
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nscnt == 0) {
|
||||||
|
zone_log(zone, me, ISC_LOG_INFO,
|
||||||
|
"no NS records from %s", master);
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = dns_message_findname(msg, DNS_SECTION_ANSWER, &zone->origin,
|
||||||
|
dns_rdatatype_ns, dns_rdatatype_none,
|
||||||
|
NULL, &nsrdataset);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
zone_log(zone, me, ISC_LOG_INFO,
|
||||||
|
"unable to get ns records from %s", master);
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE, &node);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
zone_log(zone, me, ISC_LOG_INFO,
|
||||||
|
"dns_db_findnode failed: %s",
|
||||||
|
dns_result_totext(result));
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Add NS rdataset.
|
||||||
|
*/
|
||||||
|
result = dns_db_addrdataset(stub->db, node, stub->version, now,
|
||||||
|
nsrdataset, 0, NULL);
|
||||||
|
dns_db_detachnode(stub->db, &node);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
zone_log(zone, me, ISC_LOG_INFO,
|
||||||
|
"dns_db_addrdataset failed: %s",
|
||||||
|
dns_result_totext(result));
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Add glue rdatasets.
|
||||||
|
*/
|
||||||
|
for (result = dns_rdataset_first(nsrdataset);
|
||||||
|
result == ISC_R_SUCCESS;
|
||||||
|
result = dns_rdataset_next(nsrdataset)) {
|
||||||
|
dns_rdataset_current(nsrdataset, &rdata);
|
||||||
|
result = dns_rdata_tostruct(&rdata, &ns, NULL);
|
||||||
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||||
|
if (!dns_name_issubdomain(&ns.name, &zone->origin)) {
|
||||||
|
result = dns_rdataset_next(nsrdataset);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rdataset = NULL;
|
||||||
|
result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL,
|
||||||
|
&ns.name, dns_rdatatype_a6,
|
||||||
|
dns_rdatatype_none, NULL,
|
||||||
|
&rdataset);
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
result = dns_db_findnode(stub->db, &ns.name,
|
||||||
|
ISC_TRUE, &node);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto next_master;
|
||||||
|
result = dns_db_addrdataset(stub->db, node,
|
||||||
|
stub->version, now,
|
||||||
|
rdataset, 0, NULL);
|
||||||
|
dns_db_detachnode(stub->db, &node);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
rdataset = NULL;
|
||||||
|
result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL,
|
||||||
|
&ns.name, dns_rdatatype_aaaa,
|
||||||
|
dns_rdatatype_none, NULL,
|
||||||
|
&rdataset);
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
result = dns_db_findnode(stub->db, &ns.name,
|
||||||
|
ISC_TRUE, &node);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto next_master;
|
||||||
|
result = dns_db_addrdataset(stub->db, node,
|
||||||
|
stub->version, now,
|
||||||
|
rdataset, 0, NULL);
|
||||||
|
dns_db_detachnode(stub->db, &node);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
rdataset = NULL;
|
||||||
|
result = dns_message_findname(msg, DNS_SECTION_ADDITIONAL,
|
||||||
|
&ns.name, dns_rdatatype_a,
|
||||||
|
dns_rdatatype_none, NULL,
|
||||||
|
&rdataset);
|
||||||
|
if (result == ISC_R_SUCCESS) {
|
||||||
|
result = dns_db_findnode(stub->db, &ns.name,
|
||||||
|
ISC_TRUE, &node);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto next_master;
|
||||||
|
result = dns_db_addrdataset(stub->db, node,
|
||||||
|
stub->version, now,
|
||||||
|
rdataset, 0, NULL);
|
||||||
|
dns_db_detachnode(stub->db, &node);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (result != ISC_R_NOMORE)
|
||||||
|
goto next_master;
|
||||||
|
dns_db_closeversion(stub->db, &stub->version, ISC_TRUE);
|
||||||
|
LOCK(&zone->lock);
|
||||||
|
if (zone->db == NULL)
|
||||||
|
dns_db_attach(stub->db, &zone->db);
|
||||||
|
UNLOCK(&zone->lock);
|
||||||
|
dns_db_detach(&stub->db);
|
||||||
|
|
||||||
|
if (zone->dbname != NULL)
|
||||||
|
dns_zone_dump(zone);
|
||||||
|
|
||||||
|
dns_message_destroy(&msg);
|
||||||
|
isc_event_free(&event);
|
||||||
|
dns_request_destroy(&zone->request);
|
||||||
|
goto free_stub;
|
||||||
|
|
||||||
|
next_master:
|
||||||
|
if (stub->version != NULL)
|
||||||
|
dns_db_closeversion(stub->db, &stub->version, ISC_FALSE);
|
||||||
|
if (node != NULL)
|
||||||
|
dns_db_detachnode(stub->db, &node);
|
||||||
|
if (stub->db != NULL)
|
||||||
|
dns_db_detach(&stub->db);
|
||||||
|
if (msg != NULL)
|
||||||
|
dns_message_destroy(&msg);
|
||||||
|
LOCK(&zone->lock);
|
||||||
|
isc_event_free(&event);
|
||||||
|
dns_request_destroy(&zone->request);
|
||||||
|
zone->curmaster++;
|
||||||
|
if (zone->curmaster >= zone->masterscnt) {
|
||||||
|
zone->flags &= ~DNS_ZONE_F_REFRESH;
|
||||||
|
|
||||||
|
zone_settimer(zone, now);
|
||||||
|
UNLOCK(&zone->lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
UNLOCK(&zone->lock);
|
||||||
|
queue_soa_query(zone);
|
||||||
|
goto free_stub;
|
||||||
|
|
||||||
|
same_master:
|
||||||
|
if (msg != NULL)
|
||||||
|
dns_message_destroy(&msg);
|
||||||
|
isc_event_free(&event);
|
||||||
|
LOCK(&zone->lock);
|
||||||
|
dns_request_destroy(&zone->request);
|
||||||
|
UNLOCK(&zone->lock);
|
||||||
|
ns_query(zone, NULL, stub);
|
||||||
|
goto detach;
|
||||||
|
|
||||||
|
|
||||||
|
free_stub:
|
||||||
|
stub->magic = 0;
|
||||||
|
dns_zone_idetach(&stub->zone);
|
||||||
|
INSIST(stub->db == NULL);
|
||||||
|
INSIST(stub->version == NULL);
|
||||||
|
isc_mem_put(stub->mctx, stub, sizeof(*stub));
|
||||||
|
|
||||||
|
detach:
|
||||||
|
dns_zone_idetach(&zone);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
refresh_callback(isc_task_t *task, isc_event_t *event) {
|
refresh_callback(isc_task_t *task, isc_event_t *event) {
|
||||||
const char me[] = "refresh_callback";
|
const char me[] = "refresh_callback";
|
||||||
@@ -2011,10 +2284,23 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
|
|||||||
* If truncated punt to zone transfer which will query again.
|
* If truncated punt to zone transfer which will query again.
|
||||||
*/
|
*/
|
||||||
if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
|
if ((msg->flags & DNS_MESSAGEFLAG_TC) != 0) {
|
||||||
|
if (zone->type == dns_zone_slave) {
|
||||||
zone_log(zone, me, ISC_LOG_INFO,
|
zone_log(zone, me, ISC_LOG_INFO,
|
||||||
"truncated UDP answer initiating TCP zone xfer %s",
|
"truncated UDP answer initiating "
|
||||||
|
"TCP zone xfer %s",
|
||||||
master);
|
master);
|
||||||
goto tcp_transfer;
|
goto tcp_transfer;
|
||||||
|
} else {
|
||||||
|
INSIST(zone->type == dns_zone_stub);
|
||||||
|
if (dns_request_usedtcp(revent->request)) {
|
||||||
|
/* XXX log failure */
|
||||||
|
goto next_master;
|
||||||
|
}
|
||||||
|
LOCK(&zone->lock);
|
||||||
|
zone->flags |= DNS_ZONE_F_USEVC;
|
||||||
|
UNLOCK(&zone->lock);
|
||||||
|
goto same_master;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2095,7 +2381,6 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
serial = soa.serial;
|
serial = soa.serial;
|
||||||
dns_message_destroy(&msg);
|
|
||||||
|
|
||||||
zone_log(zone, me, ISC_LOG_DEBUG(1), "Serial: new %u, old %u",
|
zone_log(zone, me, ISC_LOG_DEBUG(1), "Serial: new %u, old %u",
|
||||||
serial, zone->serial);
|
serial, zone->serial);
|
||||||
@@ -2104,7 +2389,14 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
|
|||||||
tcp_transfer:
|
tcp_transfer:
|
||||||
isc_event_free(&event);
|
isc_event_free(&event);
|
||||||
dns_request_destroy(&zone->request);
|
dns_request_destroy(&zone->request);
|
||||||
|
if (zone->type == dns_zone_slave) {
|
||||||
queue_xfrin(zone);
|
queue_xfrin(zone);
|
||||||
|
} else {
|
||||||
|
INSIST(zone->type == dns_zone_stub);
|
||||||
|
ns_query(zone, rdataset, NULL);
|
||||||
|
}
|
||||||
|
if (msg != NULL)
|
||||||
|
dns_message_destroy(&msg);
|
||||||
} else if (isc_serial_eq(soa.serial, zone->serial)) {
|
} else if (isc_serial_eq(soa.serial, zone->serial)) {
|
||||||
if (zone->dbname != NULL) {
|
if (zone->dbname != NULL) {
|
||||||
isc_time_t t;
|
isc_time_t t;
|
||||||
@@ -2123,6 +2415,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
|
|||||||
ZONE_LOG(1, "ahead");
|
ZONE_LOG(1, "ahead");
|
||||||
goto next_master;
|
goto next_master;
|
||||||
}
|
}
|
||||||
|
if (msg != NULL)
|
||||||
|
dns_message_destroy(&msg);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
next_master:
|
next_master:
|
||||||
@@ -2145,6 +2439,16 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {
|
|||||||
UNLOCK(&zone->lock);
|
UNLOCK(&zone->lock);
|
||||||
queue_soa_query(zone);
|
queue_soa_query(zone);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
same_master:
|
||||||
|
if (msg != NULL)
|
||||||
|
dns_message_destroy(&msg);
|
||||||
|
LOCK(&zone->lock);
|
||||||
|
isc_event_free(&event);
|
||||||
|
dns_request_destroy(&zone->request);
|
||||||
|
UNLOCK(&zone->lock);
|
||||||
|
queue_soa_query(zone);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -2196,6 +2500,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
|
|||||||
dns_peer_t *peer = NULL;
|
dns_peer_t *peer = NULL;
|
||||||
dns_name_t *keyname = NULL;
|
dns_name_t *keyname = NULL;
|
||||||
dns_tsigkey_t *key = NULL;
|
dns_tsigkey_t *key = NULL;
|
||||||
|
isc_uint32_t options;
|
||||||
|
|
||||||
REQUIRE(DNS_ZONE_VALID(zone));
|
REQUIRE(DNS_ZONE_VALID(zone));
|
||||||
|
|
||||||
@@ -2262,8 +2567,10 @@ soa_query(isc_task_t *task, isc_event_t *event) {
|
|||||||
zone->view->dynamickeys);
|
zone->view->dynamickeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
options = DNS_ZONE_FLAG(zone, DNS_ZONE_F_USEVC) ?
|
||||||
|
DNS_REQUESTOPT_TCP : 0;
|
||||||
result = dns_request_create(zone->view->requestmgr, message,
|
result = dns_request_create(zone->view->requestmgr, message,
|
||||||
&zone->masteraddr, 0, key,
|
&zone->masteraddr, options, key,
|
||||||
15 /* XXX */, zone->task,
|
15 /* XXX */, zone->task,
|
||||||
refresh_callback, zone, &zone->request);
|
refresh_callback, zone, &zone->request);
|
||||||
if (result != ISC_R_SUCCESS) {
|
if (result != ISC_R_SUCCESS) {
|
||||||
@@ -2290,6 +2597,167 @@ soa_query(isc_task_t *task, isc_event_t *event) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {
|
||||||
|
const char me[] = "ns_query";
|
||||||
|
isc_result_t result;
|
||||||
|
dns_message_t *message = NULL;
|
||||||
|
dns_name_t *qname = NULL;
|
||||||
|
dns_rdataset_t *qrdataset = NULL;
|
||||||
|
isc_netaddr_t masterip;
|
||||||
|
dns_peer_t *peer = NULL;
|
||||||
|
dns_name_t *keyname = NULL;
|
||||||
|
dns_tsigkey_t *key = NULL;
|
||||||
|
dns_dbnode_t *node = NULL;
|
||||||
|
isc_uint32_t options;
|
||||||
|
|
||||||
|
REQUIRE(DNS_ZONE_VALID(zone));
|
||||||
|
REQUIRE((soardataset != NULL && stub == NULL) ||
|
||||||
|
(soardataset == NULL && stub != NULL));
|
||||||
|
REQUIRE(stub == NULL || DNS_STUB_VALID(stub));
|
||||||
|
|
||||||
|
DNS_ENTER;
|
||||||
|
|
||||||
|
if (stub == NULL) {
|
||||||
|
stub = isc_mem_get(zone->mctx, sizeof *stub);
|
||||||
|
if (stub == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
stub->magic = STUB_MAGIC;
|
||||||
|
stub->mctx = zone->mctx;
|
||||||
|
stub->zone = NULL;
|
||||||
|
stub->db = NULL;
|
||||||
|
stub->version = NULL;
|
||||||
|
|
||||||
|
/* Attach so that zone won't disappear under us. */
|
||||||
|
dns_zone_iattach(zone, &stub->zone);
|
||||||
|
|
||||||
|
if (zone->db != NULL)
|
||||||
|
dns_db_attach(zone->db, &stub->db);
|
||||||
|
else {
|
||||||
|
result = dns_db_create(zone->mctx, "rbt",
|
||||||
|
&zone->origin, dns_dbtype_stub,
|
||||||
|
zone->rdclass,
|
||||||
|
zone->db_argc, zone->db_argv,
|
||||||
|
&stub->db);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
zone_log(zone, me, ISC_LOG_INFO,
|
||||||
|
"dns_db_create failed: %s",
|
||||||
|
dns_result_totext(result));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_db_newversion(stub->db, &stub->version);
|
||||||
|
|
||||||
|
result = dns_db_findnode(stub->db, &zone->origin, ISC_TRUE,
|
||||||
|
&node);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
zone_log(zone, me, ISC_LOG_INFO,
|
||||||
|
"dns_db_findnode failed: %s",
|
||||||
|
dns_result_totext(result));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = dns_db_addrdataset(stub->db, node, stub->version, 0,
|
||||||
|
soardataset, 0, NULL);
|
||||||
|
dns_db_detachnode(stub->db, &node);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
zone_log(zone, me, ISC_LOG_INFO,
|
||||||
|
"dns_db_addrdataset failed: %s",
|
||||||
|
dns_result_totext(result));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* XXX Optimisation: Create message when zone is setup and reuse.
|
||||||
|
*/
|
||||||
|
result = dns_message_create(zone->mctx, DNS_MESSAGE_INTENTRENDER,
|
||||||
|
&message);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
message->opcode = dns_opcode_query;
|
||||||
|
message->rdclass = zone->rdclass;
|
||||||
|
|
||||||
|
result = dns_message_gettempname(message, &qname);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
result = dns_message_gettemprdataset(message, &qrdataset);
|
||||||
|
if (result != ISC_R_SUCCESS)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make question.
|
||||||
|
*/
|
||||||
|
dns_name_init(qname, NULL);
|
||||||
|
dns_name_clone(&zone->origin, qname);
|
||||||
|
dns_rdataset_init(qrdataset);
|
||||||
|
dns_rdataset_makequestion(qrdataset, zone->rdclass, dns_rdatatype_ns);
|
||||||
|
ISC_LIST_APPEND(qname->list, qrdataset, link);
|
||||||
|
dns_message_addname(message, qname, DNS_SECTION_QUESTION);
|
||||||
|
qname = NULL;
|
||||||
|
qrdataset = NULL;
|
||||||
|
|
||||||
|
LOCK(&zone->lock);
|
||||||
|
INSIST(zone->masterscnt > 0);
|
||||||
|
INSIST(zone->curmaster < zone->masterscnt);
|
||||||
|
zone->masteraddr = zone->masters[zone->curmaster];
|
||||||
|
UNLOCK(&zone->lock);
|
||||||
|
|
||||||
|
if (isc_sockaddr_getport(&zone->masteraddr) == 0)
|
||||||
|
isc_sockaddr_setport(&zone->masteraddr, 53); /* XXX */
|
||||||
|
|
||||||
|
isc_netaddr_fromsockaddr(&masterip, &zone->masteraddr);
|
||||||
|
result = dns_peerlist_peerbyaddr(zone->view->peers,
|
||||||
|
&masterip, &peer);
|
||||||
|
if (result == ISC_R_SUCCESS &&
|
||||||
|
dns_peer_getkey(peer, &keyname) == ISC_R_SUCCESS)
|
||||||
|
{
|
||||||
|
result = dns_tsigkey_find(&key, keyname, NULL,
|
||||||
|
zone->view->statickeys);
|
||||||
|
if (result == ISC_R_NOTFOUND)
|
||||||
|
(void) dns_tsigkey_find(&key, keyname, NULL,
|
||||||
|
zone->view->dynamickeys);
|
||||||
|
}
|
||||||
|
|
||||||
|
options = DNS_ZONE_FLAG(zone, DNS_ZONE_F_USEVC) ?
|
||||||
|
DNS_REQUESTOPT_TCP : 0;
|
||||||
|
result = dns_request_create(zone->view->requestmgr, message,
|
||||||
|
&zone->masteraddr, options, key,
|
||||||
|
15 /* XXX */, zone->task,
|
||||||
|
stub_callback, stub, &zone->request);
|
||||||
|
if (result != ISC_R_SUCCESS) {
|
||||||
|
zone_log(zone, me, ISC_LOG_DEBUG(1),
|
||||||
|
"dns_request_create failed: %s",
|
||||||
|
dns_result_totext(result));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
dns_message_destroy(&message);
|
||||||
|
return;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (stub != NULL) {
|
||||||
|
stub->magic = 0;
|
||||||
|
if (stub->version != NULL)
|
||||||
|
dns_db_closeversion(stub->db, &stub->version,
|
||||||
|
ISC_FALSE);
|
||||||
|
if (stub->db != NULL)
|
||||||
|
dns_db_detach(&stub->db);
|
||||||
|
isc_mem_put(stub->mctx, stub, sizeof(*stub));
|
||||||
|
}
|
||||||
|
if (qname != NULL)
|
||||||
|
dns_message_puttempname(message, &qname);
|
||||||
|
if (qrdataset != NULL)
|
||||||
|
dns_message_puttemprdataset(message, &qrdataset);
|
||||||
|
if (message != NULL)
|
||||||
|
dns_message_destroy(&message);
|
||||||
|
cancel_refresh(zone);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle the control event. Note that although this event causes the zone
|
* Handle the control event. Note that although this event causes the zone
|
||||||
* to shut down, it is not a shutdown event in the sense of the task library.
|
* to shut down, it is not a shutdown event in the sense of the task library.
|
||||||
@@ -2297,7 +2765,7 @@ soa_query(isc_task_t *task, isc_event_t *event) {
|
|||||||
static void
|
static void
|
||||||
zone_shutdown(isc_task_t *task, isc_event_t *event) {
|
zone_shutdown(isc_task_t *task, isc_event_t *event) {
|
||||||
dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
|
dns_zone_t *zone = (dns_zone_t *) event->ev_arg;
|
||||||
notify_t *notify;
|
dns_notify_t *notify;
|
||||||
isc_result_t result;
|
isc_result_t result;
|
||||||
|
|
||||||
UNUSED(task);
|
UNUSED(task);
|
||||||
@@ -2995,7 +3463,7 @@ record_serial() {
|
|||||||
static void
|
static void
|
||||||
notify_done(isc_task_t *task, isc_event_t *event) {
|
notify_done(isc_task_t *task, isc_event_t *event) {
|
||||||
const char me[] = "notify_done";
|
const char me[] = "notify_done";
|
||||||
notify_t *notify;
|
dns_notify_t *notify;
|
||||||
dns_zone_t *zone = NULL;
|
dns_zone_t *zone = NULL;
|
||||||
|
|
||||||
UNUSED(task);
|
UNUSED(task);
|
||||||
|
Reference in New Issue
Block a user