diff options
Diffstat (limited to 'lib/dns/zone.c')
| -rw-r--r-- | lib/dns/zone.c | 121 | 
1 files changed, 61 insertions, 60 deletions
diff --git a/lib/dns/zone.c b/lib/dns/zone.c index 11b7cc336ec6..329fbef31924 100644 --- a/lib/dns/zone.c +++ b/lib/dns/zone.c @@ -395,6 +395,7 @@ struct dns_zonemgr {  	isc_ratelimiter_t *	rl;  	isc_rwlock_t		rwlock;  	isc_mutex_t		iolock; +	isc_rwlock_t		urlock;  	/* Locked by rwlock. */  	dns_zonelist_t		zones; @@ -412,7 +413,7 @@ struct dns_zonemgr {  	dns_iolist_t		high;  	dns_iolist_t		low; -	/* Locked by rwlock. */ +	/* Locked by urlock. */  	/* LRU cache */  	struct dns_unreachable	unreachable[UNREACH_CHACHE_SIZE];  }; @@ -1607,12 +1608,16 @@ zone_gotwritehandle(isc_task_t *task, isc_event_t *event) {  	LOCK_ZONE(zone);  	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_read); -	dns_db_currentversion(zone->db, &version); -	result = dns_master_dumpinc2(zone->mctx, zone->db, version, -				     &dns_master_style_default, -				     zone->masterfile, zone->task, dump_done, -				     zone, &zone->dctx, zone->masterformat); -	dns_db_closeversion(zone->db, &version, ISC_FALSE); +	if (zone->db != NULL) { +		dns_db_currentversion(zone->db, &version); +		result = dns_master_dumpinc2(zone->mctx, zone->db, version, +					     &dns_master_style_default, +					     zone->masterfile, zone->task, +					     dump_done, zone, &zone->dctx, +					     zone->masterformat); +		dns_db_closeversion(zone->db, &version, ISC_FALSE); +	} else +		result = ISC_R_CANCELED;  	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_read);  	UNLOCK_ZONE(zone);  	if (result != DNS_R_CONTINUE) @@ -3478,6 +3483,7 @@ dns_zone_setmasterswithkeys(dns_zone_t *zone,  	/*  	 * Everything is ok so attach to the zone.  	 */ +	zone->curmaster = 0;  	zone->masters = new;  	zone->mastersok = newok;  	zone->masterkeynames = newname; @@ -6541,6 +6547,14 @@ zone_unload(dns_zone_t *zone) {  	REQUIRE(LOCKED_ZONE(zone)); +	if (!DNS_ZONE_FLAG(zone, DNS_ZONEFLG_FLUSH) || +	    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_DUMPING)) { +		if (zone->writeio != NULL) +			zonemgr_cancelio(zone->writeio); + +		if (zone->dctx != NULL) +			dns_dumpctx_cancel(zone->dctx); +	}  	ZONEDB_LOCK(&zone->dblock, isc_rwlocktype_write);  	zone_detachdb(zone);  	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write); @@ -7255,6 +7269,8 @@ stub_callback(isc_task_t *task, isc_event_t *event) {  	TIME_NOW(&now); +	LOCK_ZONE(zone); +  	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_EXITING)) {  		zone_debuglog(zone, me, 1, "exiting");  		exiting = ISC_TRUE; @@ -7267,9 +7283,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) {  	if (revent->result != ISC_R_SUCCESS) {  		if (revent->result == ISC_R_TIMEDOUT &&  		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) { -			LOCK_ZONE(zone);  			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); -			UNLOCK_ZONE(zone);  			dns_zone_log(zone, ISC_LOG_DEBUG(1),  				     "refreshing stub: timeout retrying "  				     " without EDNS master %s (source %s)", @@ -7311,9 +7325,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) {  				     "refreshing stub: rcode (%.*s) retrying "  				     "without EDNS master %s (source %s)",  				     (int)rb.used, rcode, master, source); -			LOCK_ZONE(zone);  			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); -			UNLOCK_ZONE(zone);  			goto same_master;  		} @@ -7335,9 +7347,7 @@ stub_callback(isc_task_t *task, isc_event_t *event) {  				     master, source);  			goto next_master;  		} -		LOCK_ZONE(zone);  		DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC); -		UNLOCK_ZONE(zone);  		goto same_master;  	} @@ -7392,21 +7402,17 @@ stub_callback(isc_task_t *task, isc_event_t *event) {  	ZONEDB_UNLOCK(&zone->dblock, isc_rwlocktype_write);  	dns_db_detach(&stub->db); -	if (zone->masterfile != NULL) { -		dns_zone_dump(zone); -		TIME_NOW(&zone->loadtime); -	} +	if (zone->masterfile != NULL) +		zone_needdump(zone, 0);  	dns_message_destroy(&msg);  	isc_event_free(&event); -	LOCK_ZONE(zone);  	dns_request_destroy(&zone->request);  	DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);  	DNS_ZONE_JITTER_ADD(&now, zone->refresh, &zone->refreshtime);  	isc_interval_set(&i, zone->expire, 0);  	DNS_ZONE_TIME_ADD(&now, zone->expire, &zone->expiretime);  	zone_settimer(zone, &now); -	UNLOCK_ZONE(zone);  	goto free_stub;   next_master: @@ -7417,7 +7423,6 @@ stub_callback(isc_task_t *task, isc_event_t *event) {  	if (msg != NULL)  		dns_message_destroy(&msg);  	isc_event_free(&event); -	LOCK_ZONE(zone);  	dns_request_destroy(&zone->request);  	/*  	 * Skip to next failed / untried master. @@ -7455,25 +7460,23 @@ stub_callback(isc_task_t *task, isc_event_t *event) {  			DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_REFRESH);  			zone_settimer(zone, &now); -			UNLOCK_ZONE(zone);  			goto free_stub;  		}  	}  	queue_soa_query(zone); -	UNLOCK_ZONE(zone);  	goto free_stub;   same_master:  	if (msg != NULL)  		dns_message_destroy(&msg);  	isc_event_free(&event); -	LOCK_ZONE(zone);  	dns_request_destroy(&zone->request); -	UNLOCK_ZONE(zone);  	ns_query(zone, NULL, stub); +	UNLOCK_ZONE(zone);  	goto done;   free_stub: +	UNLOCK_ZONE(zone);  	stub->magic = 0;  	dns_zone_idetach(&stub->zone);  	INSIST(stub->db == NULL); @@ -7504,6 +7507,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  	isc_result_t result;  	isc_uint32_t serial, oldserial = 0;  	unsigned int j; +	isc_boolean_t do_queue_xfrin = ISC_FALSE;  	zone = revent->ev_arg;  	INSIST(DNS_ZONE_VALID(zone)); @@ -7512,6 +7516,10 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  	ENTER; +	TIME_NOW(&now); + +	LOCK_ZONE(zone); +  	/*  	 * if timeout log and next master;  	 */ @@ -7519,14 +7527,10 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  	isc_sockaddr_format(&zone->masteraddr, master, sizeof(master));  	isc_sockaddr_format(&zone->sourceaddr, source, sizeof(source)); -	TIME_NOW(&now); -  	if (revent->result != ISC_R_SUCCESS) {  		if (revent->result == ISC_R_TIMEDOUT &&  		    !DNS_ZONE_FLAG(zone, DNS_ZONEFLG_NOEDNS)) { -			LOCK_ZONE(zone);  			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); -			UNLOCK_ZONE(zone);  			dns_zone_log(zone, ISC_LOG_DEBUG(1),  				     "refresh: timeout retrying without EDNS "  				     "master %s (source %s)", master, source); @@ -7546,10 +7550,8 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  							     &zone->sourceaddr,  							     &now))  				{ -					LOCK_ZONE(zone);  					DNS_ZONE_SETFLAG(zone,  						     DNS_ZONEFLG_SOABEFOREAXFR); -					UNLOCK_ZONE(zone);  					goto tcp_transfer;  				}  				dns_zone_log(zone, ISC_LOG_DEBUG(1), @@ -7596,9 +7598,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  				     "refresh: rcode (%.*s) retrying without "  				     "EDNS master %s (source %s)",  				     (int)rb.used, rcode, master, source); -			LOCK_ZONE(zone);  			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_NOEDNS); -			UNLOCK_ZONE(zone);  			goto same_master;  		}  		dns_zone_log(zone, ISC_LOG_INFO, @@ -7624,9 +7624,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  				     "initiating TCP zone xfer "  				     "for master %s (source %s)",  				     master, source); -			LOCK_ZONE(zone);  			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_SOABEFOREAXFR); -			UNLOCK_ZONE(zone);  			goto tcp_transfer;  		} else {  			INSIST(zone->type == dns_zone_stub); @@ -7637,9 +7635,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  					     master, source);  				goto next_master;  			} -			LOCK_ZONE(zone);  			DNS_ZONE_SETFLAG(zone, DNS_ZONEFLG_USEVC); -			UNLOCK_ZONE(zone);  			goto same_master;  		}  	} @@ -7700,6 +7696,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  			     soacnt, master, source);  		goto next_master;  	} +  	/*  	 * Extract serial  	 */ @@ -7727,7 +7724,9 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  	serial = soa.serial;  	if (DNS_ZONE_FLAG(zone, DNS_ZONEFLG_LOADED)) { -		result = dns_zone_getserial2(zone, &oldserial); +		result = zone_get_from_db(zone, zone->db, NULL, NULL, +					  &oldserial, NULL, NULL, NULL, NULL, +					  NULL);  		RUNTIME_CHECK(result == ISC_R_SUCCESS);  		zone_debuglog(zone, me, 1, "serial: new %u, old %u",  			      serial, oldserial); @@ -7751,11 +7750,9 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  		}   tcp_transfer:  		isc_event_free(&event); -		LOCK_ZONE(zone);  		dns_request_destroy(&zone->request); -		UNLOCK_ZONE(zone);  		if (zone->type == dns_zone_slave) { -			queue_xfrin(zone); +			do_queue_xfrin = ISC_TRUE;  		} else {  			INSIST(zone->type == dns_zone_stub);  			ns_query(zone, rdataset, NULL); @@ -7777,9 +7774,7 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  							  &now);  			/* Someone removed the file from underneath us! */  			if (result == ISC_R_FILENOTFOUND) { -				LOCK_ZONE(zone);  				zone_needdump(zone, DNS_DUMP_DELAY); -				UNLOCK_ZONE(zone);  			} else if (result != ISC_R_SUCCESS)  				dns_zone_log(zone, ISC_LOG_ERROR,  					     "refresh: could not set file " @@ -7809,7 +7804,6 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  	if (msg != NULL)  		dns_message_destroy(&msg);  	isc_event_free(&event); -	LOCK_ZONE(zone);  	dns_request_destroy(&zone->request);  	/*  	 * Skip to next failed / untried master. @@ -7851,25 +7845,24 @@ refresh_callback(isc_task_t *task, isc_event_t *event) {  		}  		DNS_ZONE_CLRFLAG(zone, DNS_ZONEFLG_USEALTXFRSRC);  		zone_settimer(zone, &now); -		UNLOCK_ZONE(zone);  		goto detach;  	}   requeue:  	queue_soa_query(zone); -	UNLOCK_ZONE(zone);  	goto detach;   same_master:  	if (msg != NULL)  		dns_message_destroy(&msg);  	isc_event_free(&event); -	LOCK_ZONE(zone);  	dns_request_destroy(&zone->request);  	queue_soa_query(zone); -	UNLOCK_ZONE(zone);   detach: +	UNLOCK_ZONE(zone); +	if (do_queue_xfrin) +		queue_xfrin(zone);  	dns_zone_idetach(&zone);  	return;  } @@ -8227,13 +8220,13 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {  	isc_uint16_t udpsize = SEND_BUFFER_SIZE;  	REQUIRE(DNS_ZONE_VALID(zone)); +	REQUIRE(LOCKED_ZONE(zone));  	REQUIRE((soardataset != NULL && stub == NULL) ||  		(soardataset == NULL && stub != NULL));  	REQUIRE(stub == NULL || DNS_STUB_VALID(stub));  	ENTER; -	LOCK_ZONE(zone);  	if (stub == NULL) {  		stub = isc_mem_get(zone->mctx, sizeof(*stub));  		if (stub == NULL) @@ -8419,10 +8412,9 @@ ns_query(dns_zone_t *zone, dns_rdataset_t *soardataset, dns_stub_t *stub) {  	}  	if (message != NULL)  		dns_message_destroy(&message); -  unlock: + unlock:  	if (key != NULL)  		dns_tsigkey_detach(&key); -	UNLOCK_ZONE(zone);  	return;  } @@ -10569,15 +10561,22 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,  	zmgr->transfersin = 10;  	zmgr->transfersperns = 2; +	/* Unreachable lock. */ +	result = isc_rwlock_init(&zmgr->urlock, 0, 0); +	if (result != ISC_R_SUCCESS) +		goto free_rwlock; +  	/* Create a single task for queueing of SOA queries. */  	result = isc_task_create(taskmgr, 1, &zmgr->task);  	if (result != ISC_R_SUCCESS) -		goto free_rwlock; +		goto free_urlock; +  	isc_task_setname(zmgr->task, "zmgr", zmgr);  	result = isc_ratelimiter_create(mctx, timermgr, zmgr->task,  					&zmgr->rl);  	if (result != ISC_R_SUCCESS)  		goto free_task; +  	/* default to 20 refresh queries / notifies per second. */  	isc_interval_set(&interval, 0, 1000000000/2);  	result = isc_ratelimiter_setinterval(zmgr->rl, &interval); @@ -10606,6 +10605,8 @@ dns_zonemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr,  	isc_ratelimiter_detach(&zmgr->rl);   free_task:  	isc_task_detach(&zmgr->task); + free_urlock: +	isc_rwlock_destroy(&zmgr->urlock);   free_rwlock:  	isc_rwlock_destroy(&zmgr->rwlock);   free_mem: @@ -10786,7 +10787,6 @@ dns_zonemgr_shutdown(dns_zonemgr_t *zmgr) {  		UNLOCK_ZONE(zone);  	}  	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_read); -  }  isc_result_t @@ -10830,6 +10830,7 @@ zonemgr_free(dns_zonemgr_t *zmgr) {  	DESTROYLOCK(&zmgr->iolock);  	isc_ratelimiter_detach(&zmgr->rl); +	isc_rwlock_destroy(&zmgr->urlock);  	isc_rwlock_destroy(&zmgr->rwlock);  	mctx = zmgr->mctx;  	isc_mem_put(zmgr->mctx, zmgr, sizeof(*zmgr)); @@ -11242,12 +11243,12 @@ dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,  	REQUIRE(DNS_ZONEMGR_VALID(zmgr));  	locktype = isc_rwlocktype_read; -	RWLOCK(&zmgr->rwlock, locktype); +	RWLOCK(&zmgr->urlock, locktype);  	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {  		if (zmgr->unreachable[i].expire >= seconds &&  		    isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&  		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) { -			result = isc_rwlock_tryupgrade(&zmgr->rwlock); +			result = isc_rwlock_tryupgrade(&zmgr->urlock);  			if (result == ISC_R_SUCCESS) {  				locktype = isc_rwlocktype_write;  				zmgr->unreachable[i].last = seconds; @@ -11255,7 +11256,7 @@ dns_zonemgr_unreachable(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,  			break;  		}  	} -	RWUNLOCK(&zmgr->rwlock, locktype); +	RWUNLOCK(&zmgr->urlock, locktype);  	return (ISC_TF(i < UNREACH_CHACHE_SIZE));  } @@ -11276,11 +11277,11 @@ dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,  	REQUIRE(DNS_ZONEMGR_VALID(zmgr));  	locktype = isc_rwlocktype_read; -	RWLOCK(&zmgr->rwlock, locktype); +	RWLOCK(&zmgr->urlock, locktype);  	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {  		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) &&  		    isc_sockaddr_equal(&zmgr->unreachable[i].local, local)) { -			result = isc_rwlock_tryupgrade(&zmgr->rwlock); +			result = isc_rwlock_tryupgrade(&zmgr->urlock);  			if (result == ISC_R_SUCCESS) {  				locktype = isc_rwlocktype_write;  				zmgr->unreachable[i].expire = 0; @@ -11293,7 +11294,7 @@ dns_zonemgr_unreachabledel(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,  			break;  		}  	} -	RWUNLOCK(&zmgr->rwlock, locktype); +	RWUNLOCK(&zmgr->urlock, locktype);  }  void @@ -11306,7 +11307,7 @@ dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,  	REQUIRE(DNS_ZONEMGR_VALID(zmgr)); -	RWLOCK(&zmgr->rwlock, isc_rwlocktype_write); +	RWLOCK(&zmgr->urlock, isc_rwlocktype_write);  	for (i = 0; i < UNREACH_CHACHE_SIZE; i++) {  		/* Existing entry? */  		if (isc_sockaddr_equal(&zmgr->unreachable[i].remote, remote) && @@ -11345,7 +11346,7 @@ dns_zonemgr_unreachableadd(dns_zonemgr_t *zmgr, isc_sockaddr_t *remote,  		zmgr->unreachable[oldest].remote = *remote;  		zmgr->unreachable[oldest].local = *local;  	} -	RWUNLOCK(&zmgr->rwlock, isc_rwlocktype_write); +	RWUNLOCK(&zmgr->urlock, isc_rwlocktype_write);  }  void  | 
