diff --git a/bin/named/server.c b/bin/named/server.c index 2491c3e31c..a66c3235ed 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -249,6 +249,12 @@ load_zone(dns_c_ctx_t *ctx, dns_c_zone_t *czone, dns_c_view_t *cview, * This is a new zone. */ result = dns_view_addzone(view, zone); + if (result != DNS_R_SUCCESS) + goto cleanup; + + result = dns_zonemgr_managezone(ns_g_zonemgr, zone); + if (result != DNS_R_SUCCESS) + goto cleanup; } } @@ -332,6 +338,13 @@ load_configuration(const char *filename) { dns_view_load(view); } + /* + * Force zone maintenance. Do this after loading + * so that we know when we need to force AXFR of + * slave zones whose master files are missing. + */ + dns_zonemgr_forcemaint(ns_g_zonemgr); + /* * Put the configuration into production. */ @@ -504,10 +517,10 @@ shutdown_server(isc_task_t *task, isc_event_t *event) { isc_task_detach(&server_task); - isc_taskpool_destroy(&ns_g_zonetasks); - dns_view_detach(&version_view); + dns_zonemgr_destroy(&ns_g_zonemgr); + ns_rootns_destroy(); isc_event_free(&event); @@ -524,12 +537,12 @@ ns_server_init(void) { if (result != ISC_R_SUCCESS) return (result); - result = create_version_view(); + result = dns_zonemgr_create(ns_g_mctx, ns_g_taskmgr, ns_g_timermgr, + &ns_g_zonemgr); if (result != ISC_R_SUCCESS) return (result); - result = isc_taskpool_create(ns_g_taskmgr, ns_g_mctx, 8 /* XXX */, - 0, &ns_g_zonetasks); + result = create_version_view(); if (result != ISC_R_SUCCESS) return (result); @@ -549,7 +562,7 @@ ns_server_init(void) { return (ISC_R_SUCCESS); - /* XXXRTH Add taskpool, and version view cleanups. */ + /* XXXRTH Add zonemgr, and version view cleanups. */ cleanup_task: isc_task_detach(&server_task); diff --git a/bin/named/update.c b/bin/named/update.c index 245e92f75b..cfd4713bcb 100644 --- a/bin/named/update.c +++ b/bin/named/update.c @@ -1707,10 +1707,7 @@ send_update_event(ns_client_t *client, dns_zone_t *zone) { event->zone = zone; event->result = DNS_R_SUCCESS; - isc_taskpool_gettask(ns_g_zonetasks, - dns_name_hash(dns_zone_getorigin(zone), - ISC_FALSE), - &zonetask); + dns_zone_gettask(zone, &zonetask); isc_task_send(zonetask, (isc_event_t **) &event); failure: diff --git a/lib/dns/include/dns/types.h b/lib/dns/include/dns/types.h index f5fbd56d8d..68e52c7b06 100644 --- a/lib/dns/include/dns/types.h +++ b/lib/dns/include/dns/types.h @@ -80,6 +80,7 @@ typedef struct dns_tsigkey dns_tsigkey_t; typedef struct dns_view dns_view_t; typedef ISC_LIST(dns_view_t) dns_viewlist_t; typedef struct dns_zone dns_zone_t; +typedef struct dns_zonemgr dns_zonemgr_t; typedef struct dns_zone_callbackarg dns_zone_callbackarg_t; typedef struct dns_a6context dns_a6context_t; typedef struct dns_rbt dns_rbt_t; diff --git a/lib/dns/include/dns/zone.h b/lib/dns/include/dns/zone.h index d4f827d73e..e2c98b375d 100644 --- a/lib/dns/include/dns/zone.h +++ b/lib/dns/include/dns/zone.h @@ -676,12 +676,15 @@ dns_zone_settask(dns_zone_t *zone, isc_task_t *task); * 'task' to be valid. */ -isc_task_t *dns_zone_gettask(dns_zone_t *zone); +void +dns_zone_gettask(dns_zone_t *zone, isc_task_t **target); /* - * Return a pointer to the zone's task. + * Attach the zone's task to '*target'. * * Requires: * 'zone' to be valid initialised zone. + * 'zone' to have a task. + * 'target' to be != NULL && '*target' == NULL. */ const char *dns_zone_getdatabase(dns_zone_t *zone); @@ -750,6 +753,42 @@ dns_zone_print(dns_zone_t *zone); * test use only */ +isc_result_t +dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, + isc_timermgr_t *timermgr, dns_zonemgr_t **zmgrp); +/* + * Create a zone manager. + * + * Requires: + * 'mctx' to be a valid memory context. + * 'taskmgr' to be a valid task manager. + * 'timermgr' to be a valid timer manager. + * 'zmgrp' to point to a NULL pointer. + */ + +isc_result_t +dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone); +/* + * Start managing the zone 'zone' with zone manager 'zmgr'. + */ + +isc_result_t +dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr); +/* + * Force zone maintenance of all zones managed by 'zmgr' at its + * earliest conveniene. + */ + +void +dns_zonemgr_destroy(dns_zonemgr_t **zmgrp); +/* + * Destroy a zone manager. + * + * Requires: + * '*zmgrp' is a valid, non-NULL zone manager pointer. + * Ensures: + * '*zmgrp' is NULL. + */ ISC_LANG_ENDDECLS diff --git a/lib/dns/zone.c b/lib/dns/zone.c index d33ac76922..88311a8714 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -15,7 +15,7 @@ * SOFTWARE. */ - /* $Id: zone.c,v 1.27 1999/10/25 13:44:52 marka Exp $ */ + /* $Id: zone.c,v 1.28 1999/10/29 00:46:52 gson Exp $ */ #include @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -42,7 +43,6 @@ #include #include #include -#include #include #include @@ -101,6 +101,8 @@ struct dns_zone { /* Locked */ dns_db_t *top; + dns_zonemgr_t *zmgr; + ISC_LINK(dns_zone_t) link; /* Used by zmgr. */ isc_timermgr_t *timgr; isc_timer_t *timer; unsigned int references; @@ -173,6 +175,17 @@ struct dns_zone { (((z)->options & (o)) != 0) : \ DNS_GLOBAL_OPTION(o)) +struct dns_zonemgr { + isc_mem_t * mctx; + isc_taskmgr_t * taskmgr; + isc_timermgr_t * timermgr; + isc_taskpool_t * zonetasks; + struct soaquery { + isc_task_t * task; + } soaquery; + ISC_LIST(dns_zone_t) zones; +}; + static void refresh_callback(isc_task_t *, isc_event_t *); static void zone_shutdown(isc_task_t *, isc_event_t *); static void soa_query(dns_zone_t *, isc_taskaction_t); @@ -246,6 +259,8 @@ dns_zone_create(dns_zone_t **zonep, isc_mem_t *mctx) { /* XXX MPA check that all elements are initialised */ zone->mctx = mctx; zone->top = NULL; + zone->zmgr = NULL; + ISC_LINK_INIT(zone, link); zone->timgr = NULL; zone->references = 1; /* Implicit attach. */ dns_name_init(&zone->origin, NULL); @@ -2977,11 +2992,10 @@ dns_zone_settask(dns_zone_t *zone, isc_task_t *task) { UNLOCK(&zone->lock); } -isc_task_t * -dns_zone_gettask(dns_zone_t *zone) { +void +dns_zone_gettask(dns_zone_t *zone, isc_task_t **target) { REQUIRE(DNS_ZONE_VALID(zone)); - - return (zone->task); /* attach? */ + isc_task_attach(zone->task, target); } const char * @@ -3178,3 +3192,110 @@ replacedb(dns_zone_t *zone, dns_db_t *db, isc_boolean_t dump) { dns_db_closeversion(db, &ver, ISC_FALSE); return (result); } + +/*** + *** Zone manager. + ***/ + +static void +xfrin_start_temporary_kludge(dns_zone_t *zone) { + isc_sockaddr_t sa; + in_port_t port; + if (zone->masterscnt < 1) + return; + port = zone->masterport; + if (port == 0) + port = 53; /* XXX is this the right place? */ + isc_sockaddr_fromin(&sa, &zone->masters[0].type.sin.sin_addr, + port); +#ifdef notyet + ns_xfrin_start(zone, &sa); +#endif +} + +isc_result_t +dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, + isc_timermgr_t *timermgr, dns_zonemgr_t **zmgrp) +{ + dns_zonemgr_t *zmgr; + isc_result_t result; + + zmgr = isc_mem_get(mctx, sizeof *zmgr); + if (zmgr == NULL) + return (ISC_R_NOMEMORY); + zmgr->mctx = mctx; + zmgr->taskmgr = taskmgr; + zmgr->timermgr = timermgr; + zmgr->zonetasks = NULL; + zmgr->soaquery.task = NULL; + ISC_LIST_INIT(zmgr->zones); + + /* Create the zone task pool. */ + result = isc_taskpool_create(taskmgr, mctx, + 8 /* XXX */, 0, &zmgr->zonetasks); + if (result != ISC_R_SUCCESS) + goto failure; + + /* Create a single task for queueing of SOA queries. */ + result = isc_task_create(taskmgr, mctx, 1, &zmgr->soaquery.task); + if (result != ISC_R_SUCCESS) + goto failure; + + *zmgrp = zmgr; + return (ISC_R_SUCCESS); + failure: + dns_zonemgr_destroy(&zmgr); + return (result); +} + +isc_result_t +dns_zonemgr_managezone(dns_zonemgr_t *zmgr, dns_zone_t *zone) { + isc_result_t result; + + REQUIRE(zone->task == NULL); + REQUIRE(zone->timer == NULL); + + isc_taskpool_gettask(zmgr->zonetasks, + dns_name_hash(dns_zone_getorigin(zone), + ISC_FALSE), + &zone->task); +#ifdef notyet + result = isc_timer_create(zmgr->timermgr, isc_timertype_inactive, + NULL, NULL, + zmgr->soaquery.task, soa_query_wanted, zone, + &zone->timer); +#endif + ISC_LIST_APPEND(zmgr->zones, zone, link); + + /* XXX more? */ + if (result != ISC_R_SUCCESS) + goto failure; + + failure: + return (result); +} + + +isc_result_t +dns_zonemgr_forcemaint(dns_zonemgr_t *zmgr) { + dns_zone_t *p; + for (p = ISC_LIST_HEAD(zmgr->zones); + p != NULL; + p = ISC_LIST_NEXT(p, link)) + { + if (p->type == dns_zone_slave) + xfrin_start_temporary_kludge(p); + } + return (ISC_R_SUCCESS); +} + +void +dns_zonemgr_destroy(dns_zonemgr_t **zmgrp) { + dns_zonemgr_t *zmgr = *zmgrp; + if (zmgr->soaquery.task != NULL) + isc_task_destroy(&zmgr->soaquery.task); + if (zmgr->zonetasks != NULL) + isc_taskpool_destroy(&zmgr->zonetasks); + isc_mem_put(zmgr->mctx, zmgr, sizeof *zmgr); + *zmgrp = NULL; +}