mirror of
https://github.com/isc-projects/bind9.git
synced 2026-06-11 01:31:48 -04:00
In order to make zone.c more readable, we are splitting it up in
separate source files. This moves the set and get functions to its
own file ("zoneproperties.c").
Since this code accesses the zone structure directly, move the
'struct dns_zone' and its prerequisites to "zone_p.h".
The helper functions 'inline_raw()', 'inline_secure()',
'dns_zone_setview_helper()', 'zone_settimer(), 'set_resigntime()', and
'zone_freedbargs()' need to be internally accessible to both source
files.
A few set/get functions remain in zone.c for now:
- dns_zone_getserial
- dns_zone_getversion
- dns_zone_setviewcommit
- dns_zone_setviewrevert
- dns_zone_get_rpz_num
- dns_zone_set_parentcatz
- dns_zone_get_parentcatz
- dns_zone_setrawdata
- dns_zone_setskr
- dns_zone_getskrbundle
- dns_zone_setnsec3param
- dns_zone_setoption
- dns_zone_getoptions
- dns_zone_getrequesttransporttype
- dns_zone_getredirecttype
- dns__zone_getnotifyctx
- dns_zone_getgluecachestats
- dns_zone_setplugins
- dns_zone_setserial
- dns_zone_getxfr
- dns_zone_getkeystores
272 lines
6.8 KiB
C
272 lines
6.8 KiB
C
/*
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
|
*
|
|
* SPDX-License-Identifier: MPL-2.0
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*
|
|
* See the COPYRIGHT file distributed with this work for additional
|
|
* information regarding copyright ownership.
|
|
*/
|
|
|
|
/*! \file */
|
|
|
|
#include <isc/async.h>
|
|
#include <isc/loop.h>
|
|
|
|
#include <dns/resolver.h>
|
|
#include <dns/view.h>
|
|
#include <dns/zone.h>
|
|
#include <dns/zonefetch.h>
|
|
#include <dns/zoneproperties.h>
|
|
|
|
#include "zone_p.h"
|
|
|
|
void
|
|
dns_zonefetch_run(void *arg) {
|
|
dns_zonefetch_t *fetch = (dns_zonefetch_t *)arg;
|
|
dns_zone_t *zone;
|
|
dns_view_t *view;
|
|
isc_loop_t *loop;
|
|
isc_result_t result;
|
|
dns_resolver_t *resolver = NULL;
|
|
|
|
zone = fetch->zone;
|
|
if (dns__zone_exiting(zone)) {
|
|
result = ISC_R_SHUTTINGDOWN;
|
|
goto cancel;
|
|
}
|
|
view = dns_zone_getview(zone);
|
|
loop = dns_zone_getloop(zone);
|
|
|
|
INSIST(view != NULL);
|
|
INSIST(loop != NULL);
|
|
|
|
result = fetch->fetchmethods.start_fetch(fetch);
|
|
if (result != ISC_R_SUCCESS) {
|
|
goto cancel;
|
|
}
|
|
|
|
result = dns_view_getresolver(view, &resolver);
|
|
if (result != ISC_R_SUCCESS) {
|
|
goto cancel;
|
|
}
|
|
|
|
if (isc_log_wouldlog(ISC_LOG_DEBUG(3))) {
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
|
char typebuf[DNS_RDATATYPE_FORMATSIZE];
|
|
dns_name_format(fetch->qname, namebuf, sizeof(namebuf));
|
|
dns_rdatatype_format(fetch->qtype, typebuf, sizeof(typebuf));
|
|
dns_zone_logc(zone, DNS_LOGCATEGORY_DNSSEC, ISC_LOG_DEBUG(3),
|
|
"Do fetch for %s/%s request", namebuf, typebuf);
|
|
}
|
|
|
|
/*
|
|
* Use of DNS_FETCHOPT_NOCACHED is essential here. If it is not
|
|
* set and the cache still holds a non-expired, validated version
|
|
* of the RRset being queried for by the time the response is
|
|
* received, the cached RRset will be passed to dns_zonefetch_done()
|
|
* instead of the one received in the response as the latter will
|
|
* have a lower trust level due to not being validated until
|
|
* dns_zonefetch_done() is called.
|
|
*/
|
|
INSIST((fetch->options & DNS_FETCHOPT_NOCACHED) != 0);
|
|
|
|
result = dns_resolver_createfetch(
|
|
resolver, fetch->qname, fetch->qtype, NULL, NULL, NULL, NULL, 0,
|
|
fetch->options, 0, NULL, NULL, NULL, loop, dns_zonefetch_done,
|
|
fetch, NULL, &fetch->rrset, &fetch->sigset, &fetch->fetch);
|
|
|
|
dns_resolver_detach(&resolver);
|
|
|
|
cancel:
|
|
if (result == ISC_R_SUCCESS) {
|
|
return;
|
|
} else if (result != ISC_R_SHUTTINGDOWN) {
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
|
char typebuf[DNS_RDATATYPE_FORMATSIZE];
|
|
dns_name_format(fetch->qname, namebuf, sizeof(namebuf));
|
|
dns_rdatatype_format(fetch->qtype, typebuf, sizeof(typebuf));
|
|
dns_zone_log(zone, ISC_LOG_WARNING,
|
|
"Failed fetch for %s/%s request", namebuf,
|
|
typebuf);
|
|
}
|
|
|
|
/*
|
|
* Fetch failed, cancel.
|
|
*/
|
|
dns__zone_lock(zone);
|
|
|
|
dns_name_t *zname = dns_fixedname_name(&fetch->name);
|
|
isc_mem_t *mctx = dns_zone_getmctx(zone);
|
|
bool free_needed;
|
|
|
|
isc_refcount_decrement(dns__zone_irefs(zone));
|
|
dns_name_free(zname, mctx);
|
|
|
|
fetch->fetchmethods.cancel_fetch(fetch);
|
|
|
|
isc_mem_putanddetach(&fetch->mctx, fetch, sizeof(*fetch));
|
|
free_needed = dns__zone_free_check(zone);
|
|
|
|
dns__zone_unlock(zone);
|
|
|
|
if (free_needed) {
|
|
dns__zone_free(zone);
|
|
}
|
|
}
|
|
|
|
void
|
|
dns_zonefetch_done(void *arg) {
|
|
dns_fetchresponse_t *resp = (dns_fetchresponse_t *)arg;
|
|
isc_result_t result = ISC_R_NOMORE;
|
|
isc_result_t eresult;
|
|
dns_zonefetch_t *fetch = NULL;
|
|
dns_zone_t *zone = NULL;
|
|
dns_view_t *view = NULL;
|
|
isc_mem_t *mctx = NULL;
|
|
dns_name_t *zname = NULL;
|
|
dns_rdataset_t *rrset = NULL;
|
|
dns_rdataset_t *sigset = NULL;
|
|
|
|
INSIST(resp != NULL);
|
|
|
|
fetch = resp->arg;
|
|
|
|
INSIST(fetch != NULL);
|
|
|
|
mctx = fetch->mctx;
|
|
zone = fetch->zone;
|
|
zname = dns_fixedname_name(&fetch->name);
|
|
rrset = &fetch->rrset;
|
|
sigset = &fetch->sigset;
|
|
view = dns_zone_getview(zone);
|
|
eresult = resp->result;
|
|
|
|
/* Free resources which are not of interest */
|
|
if (resp->node != NULL) {
|
|
dns_db_detachnode(&resp->node);
|
|
}
|
|
if (resp->cache != NULL) {
|
|
dns_db_detach(&resp->cache);
|
|
}
|
|
dns_resolver_destroyfetch(&fetch->fetch);
|
|
|
|
dns__zone_lock(zone);
|
|
if (dns__zone_exiting(zone) || view == NULL) {
|
|
goto cleanup;
|
|
}
|
|
|
|
result = fetch->fetchmethods.done_fetch(fetch, eresult);
|
|
|
|
cleanup:
|
|
isc_refcount_decrement(dns__zone_irefs(zone));
|
|
|
|
dns_rdataset_cleanup(rrset);
|
|
dns_rdataset_cleanup(sigset);
|
|
|
|
fetch->fetchmethods.cleanup_fetch(fetch);
|
|
|
|
dns_resolver_freefresp(&resp);
|
|
|
|
if (result == DNS_R_CONTINUE) {
|
|
dns__zone_unlock(zone);
|
|
fetch->fetchmethods.continue_fetch(fetch);
|
|
} else {
|
|
bool free_needed = false;
|
|
dns_name_free(zname, mctx);
|
|
isc_mem_putanddetach(&fetch->mctx, fetch,
|
|
sizeof(dns_zonefetch_t));
|
|
free_needed = dns__zone_free_check(zone);
|
|
|
|
dns__zone_unlock(zone);
|
|
|
|
if (free_needed) {
|
|
dns__zone_free(zone);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
zonefetch_schedule(dns_zonefetch_t *fetch, dns_name_t *name) {
|
|
dns_zone_t *zone = fetch->zone;
|
|
|
|
isc_refcount_increment0(dns__zone_irefs(zone));
|
|
|
|
if (name != NULL) {
|
|
dns_name_t *fname = dns_fixedname_initname(&fetch->name);
|
|
dns_name_dup(name, fetch->mctx, fname);
|
|
}
|
|
|
|
dns_rdataset_init(&fetch->rrset);
|
|
dns_rdataset_init(&fetch->sigset);
|
|
|
|
isc_async_run(dns_zone_getloop(zone), dns_zonefetch_run, fetch);
|
|
}
|
|
|
|
void
|
|
dns_zonefetch_schedule(dns_zonefetch_t *fetch, dns_name_t *name) {
|
|
REQUIRE(fetch != NULL);
|
|
REQUIRE(name != NULL);
|
|
|
|
zonefetch_schedule(fetch, name);
|
|
}
|
|
|
|
void
|
|
dns_zonefetch_reschedule(dns_zonefetch_t *fetch) {
|
|
REQUIRE(fetch != NULL);
|
|
|
|
zonefetch_schedule(fetch, NULL);
|
|
}
|
|
|
|
isc_result_t
|
|
dns_zonefetch_verify(dns_zonefetch_t *fetch, isc_result_t eresult,
|
|
dns_trust_t trust) {
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
|
char typebuf[DNS_RDATATYPE_FORMATSIZE];
|
|
dns_rdataset_t *rrset = NULL;
|
|
dns_rdataset_t *sigset = NULL;
|
|
|
|
REQUIRE(fetch != NULL);
|
|
|
|
rrset = &fetch->rrset;
|
|
sigset = &fetch->sigset;
|
|
dns_name_format(fetch->qname, namebuf, sizeof(namebuf));
|
|
dns_rdatatype_format(fetch->qtype, typebuf, sizeof(typebuf));
|
|
|
|
if (eresult != ISC_R_SUCCESS) {
|
|
dns_zone_logc(fetch->zone, DNS_LOGCATEGORY_DNSSEC,
|
|
ISC_LOG_WARNING, "Unable to fetch %s/%s: %s",
|
|
namebuf, typebuf, isc_result_totext(eresult));
|
|
return eresult;
|
|
}
|
|
|
|
/* No records found */
|
|
if (!dns_rdataset_isassociated(rrset)) {
|
|
dns_zone_logc(fetch->zone, DNS_LOGCATEGORY_DNSSEC,
|
|
ISC_LOG_WARNING, "No %s records found for '%s'",
|
|
typebuf, namebuf);
|
|
return ISC_R_NOTFOUND;
|
|
}
|
|
|
|
/* No RRSIGs found */
|
|
if (!dns_rdataset_isassociated(sigset)) {
|
|
dns_zone_logc(fetch->zone, DNS_LOGCATEGORY_DNSSEC,
|
|
ISC_LOG_WARNING, "No %s RRSIGs found for '%s'",
|
|
typebuf, namebuf);
|
|
return DNS_R_NOVALIDSIG;
|
|
}
|
|
|
|
/* Check trust level */
|
|
if (rrset->trust < trust) {
|
|
dns_zone_logc(fetch->zone, DNS_LOGCATEGORY_DNSSEC,
|
|
ISC_LOG_WARNING,
|
|
"Invalid %s RRset for '%s' trust level %u",
|
|
typebuf, namebuf, rrset->trust);
|
|
return DNS_R_NOVALIDSIG;
|
|
}
|
|
|
|
return ISC_R_SUCCESS;
|
|
}
|