2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-22 10:10:06 +00:00

normalize syntax checks between named and libisccfg

there were some duplicated syntax checks in named_zone_configure()
that are no longer needed, now that we perform those same checks
using isccfg_check_zoneconf().

there were also some syntax checks that were *only* in
named_zone_configure(), which have now been moved to
isccfg_check_zoneconf(). test cases for them have been
added to the checkconf system test.
This commit is contained in:
Evan Hunt 2025-05-30 23:11:14 -07:00
parent 2d57c1e737
commit 0b8f943a6a
6 changed files with 212 additions and 135 deletions

View File

@ -968,18 +968,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
result = cfg_map_get(zoptions, "dlz", &obj);
if (result == ISC_R_SUCCESS) {
const char *dlzname = cfg_obj_asstring(obj);
size_t len;
if (cpval != default_dbtype) {
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
"zone '%s': both 'database' and 'dlz' "
"specified",
zname);
CHECK(ISC_R_FAILURE);
}
len = strlen(dlzname) + 5;
size_t len = strlen(dlzname) + 5;
cpval = isc_mem_allocate(mctx, len);
snprintf(cpval, len, "dlz %s", dlzname);
}
@ -1007,19 +996,6 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
filename = cfg_obj_asstring(obj);
}
/*
* Unless we're using some alternative database, a primary zone
* will be needing a master file.
*/
if (ztype == dns_zone_primary && cpval == default_dbtype &&
filename == NULL)
{
isc_log_write(NAMED_LOGCATEGORY_GENERAL, NAMED_LOGMODULE_SERVER,
ISC_LOG_ERROR, "zone '%s': 'file' not specified",
zname);
CHECK(ISC_R_FAILURE);
}
if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) {
masterformat = dns_masterformat_raw;
} else {
@ -1032,10 +1008,8 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
if (strcasecmp(masterformatstr, "text") == 0) {
masterformat = dns_masterformat_text;
} else if (strcasecmp(masterformatstr, "raw") == 0) {
masterformat = dns_masterformat_raw;
} else {
UNREACHABLE();
masterformat = dns_masterformat_raw;
}
}
@ -1043,22 +1017,10 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
result = named_config_get(maps, "masterfile-style", &obj);
if (result == ISC_R_SUCCESS) {
const char *masterstylestr = cfg_obj_asstring(obj);
if (masterformat != dns_masterformat_text) {
cfg_obj_log(obj, ISC_LOG_ERROR,
"zone '%s': 'masterfile-style' "
"can only be used with "
"'masterfile-format text'",
zname);
CHECK(ISC_R_FAILURE);
}
if (strcasecmp(masterstylestr, "full") == 0) {
masterstyle = &dns_master_style_full;
} else if (strcasecmp(masterstylestr, "relative") == 0) {
masterstyle = &dns_master_style_default;
} else {
UNREACHABLE();
masterstyle = &dns_master_style_default;
}
}
@ -1329,16 +1291,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
journal_size = -1;
}
} else {
uint64_t value = cfg_obj_asuint64(obj);
if (value > DNS_JOURNAL_SIZE_MAX) {
cfg_obj_log(obj, ISC_LOG_ERROR,
"'max-journal-size "
"%" PRId64 "' "
"is too large",
value);
CHECK(ISC_R_RANGE);
}
journal_size = (uint32_t)value;
journal_size = (uint32_t)cfg_obj_asuint64(obj);
}
if (raw != NULL) {
dns_zone_setjournalsize(raw, journal_size);
@ -1529,16 +1482,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
journal_size = -1;
}
} else {
uint64_t value = cfg_obj_asuint64(obj);
if (value > DNS_JOURNAL_SIZE_MAX) {
cfg_obj_log(obj, ISC_LOG_ERROR,
"'max-journal-size "
"%" PRId64 "' "
"is too large",
value);
CHECK(ISC_R_RANGE);
}
journal_size = (uint32_t)value;
journal_size = (uint32_t)cfg_obj_asuint64(obj);
}
dns_zone_setjournalsize(zone, journal_size);
}
@ -1877,22 +1821,6 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
cfg_obj_asuint32(cfg_tuple_get(obj, "traffic_bytes"));
uint32_t time_minutes =
cfg_obj_asuint32(cfg_tuple_get(obj, "time_minutes"));
if (traffic_bytes == 0) {
cfg_obj_log(obj, ISC_LOG_ERROR,
"zone '%s': 'min-transfer-rate-in' bytes"
"value can not be '0'",
zname);
CHECK(ISC_R_FAILURE);
}
/* Max. 28 days (in minutes). */
const unsigned int time_minutes_max = 28 * 24 * 60;
if (time_minutes < 1 || time_minutes > time_minutes_max) {
cfg_obj_log(obj, ISC_LOG_ERROR,
"zone '%s': 'min-transfer-rate-in' minutes"
"value is out of range (1..%u)",
zname, time_minutes_max);
CHECK(ISC_R_FAILURE);
}
dns_zone_setminxfrratein(mayberaw, traffic_bytes,
transferinsecs ? time_minutes
: time_minutes * 60);

View File

@ -0,0 +1,19 @@
/*
* 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.
*/
zone "clone" {
type secondary;
primaries { ::1; };
file "xxx";
max-journal-size 3g;
};

View File

@ -0,0 +1,19 @@
/*
* 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.
*/
zone example {
type primary;
file "filename";
masterfile-format raw;
masterfile-style relative;
};

View File

@ -0,0 +1,19 @@
/*
* 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.
*/
zone "clone" {
type secondary;
primaries { ::1; };
file "xxx";
min-transfer-rate-in 0 28800;
};

View File

@ -0,0 +1,19 @@
/*
* 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.
*/
zone "clone" {
type secondary;
primaries { ::1; };
file "xxx";
min-transfer-rate-in 1024 65536;
};

View File

@ -45,6 +45,7 @@
#include <dns/acl.h>
#include <dns/dnstap.h>
#include <dns/fixedname.h>
#include <dns/journal.h>
#include <dns/kasp.h>
#include <dns/keystore.h>
#include <dns/keyvalues.h>
@ -2921,6 +2922,32 @@ check:
return result;
}
/*
* Try to find a zone option in one of up to three levels of options:
* for example, the zone, view, and global option blocks.
* (Fewer levels can be specified for options that aren't defined at
* all three levels.)
*/
static isc_result_t
get_zoneopt(const cfg_obj_t *opts1, const cfg_obj_t *opts2,
const cfg_obj_t *opts3, const char *name, const cfg_obj_t **objp) {
isc_result_t result = ISC_R_NOTFOUND;
REQUIRE(*objp == NULL);
if (opts1 != NULL) {
result = cfg_map_get(opts1, name, objp);
}
if (*objp == NULL && opts2 != NULL) {
result = cfg_map_get(opts2, name, objp);
}
if (*objp == NULL && opts3 != NULL) {
result = cfg_map_get(opts3, name, objp);
}
return result;
}
isc_result_t
isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
const cfg_obj_t *config, isc_symtab_t *symtab,
@ -3168,13 +3195,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
* Check if a dnssec-policy is set.
*/
obj = NULL;
(void)cfg_map_get(zoptions, "dnssec-policy", &obj);
if (obj == NULL && voptions != NULL) {
(void)cfg_map_get(voptions, "dnssec-policy", &obj);
}
if (obj == NULL && goptions != NULL) {
(void)cfg_map_get(goptions, "dnssec-policy", &obj);
}
(void)get_zoneopt(zoptions, voptions, goptions, "dnssec-policy", &obj);
if (obj != NULL) {
kaspname = cfg_obj_asstring(obj);
if (strcmp(kaspname, "default") == 0) {
@ -3237,13 +3258,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
* */
if (has_dnssecpolicy) {
obj = NULL;
(void)cfg_map_get(zoptions, "max-zone-ttl", &obj);
if (obj == NULL && voptions != NULL) {
(void)cfg_map_get(voptions, "max-zone-ttl", &obj);
}
if (obj == NULL && goptions != NULL) {
(void)cfg_map_get(goptions, "max-zone-ttl", &obj);
}
(void)get_zoneopt(zoptions, voptions, goptions, "max-zone-ttl",
&obj);
if (obj != NULL) {
cfg_obj_log(obj, ISC_LOG_ERROR,
"zone '%s': option 'max-zone-ttl' "
@ -3305,13 +3321,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
bool donotify = true;
obj = NULL;
tresult = cfg_map_get(zoptions, "notify", &obj);
if (tresult != ISC_R_SUCCESS && voptions != NULL) {
tresult = cfg_map_get(voptions, "notify", &obj);
}
if (tresult != ISC_R_SUCCESS && goptions != NULL) {
tresult = cfg_map_get(goptions, "notify", &obj);
}
tresult = get_zoneopt(zoptions, voptions, goptions, "notify",
&obj);
if (tresult == ISC_R_SUCCESS) {
if (cfg_obj_isboolean(obj)) {
donotify = cfg_obj_asboolean(obj);
@ -3334,11 +3345,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
"'notify' is disabled",
znamestr);
}
if (tresult != ISC_R_SUCCESS && voptions != NULL) {
tresult = cfg_map_get(voptions, "also-notify", &obj);
}
if (tresult != ISC_R_SUCCESS && goptions != NULL) {
tresult = cfg_map_get(goptions, "also-notify", &obj);
if (tresult != ISC_R_SUCCESS) {
tresult = get_zoneopt(voptions, goptions, NULL,
"also-notify", &obj);
}
if (tresult == ISC_R_SUCCESS && donotify) {
uint32_t count;
@ -3467,11 +3476,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
* we should also check for allow-update at the
* view and options levels.
*/
if (res1 != ISC_R_SUCCESS && voptions != NULL) {
res1 = cfg_map_get(voptions, "allow-update", &au);
}
if (res1 != ISC_R_SUCCESS && goptions != NULL) {
res1 = cfg_map_get(goptions, "allow-update", &au);
if (res1 != ISC_R_SUCCESS) {
res1 = get_zoneopt(voptions, goptions, NULL,
"allow-update", &au);
}
if (res2 == ISC_R_SUCCESS) {
@ -3550,12 +3557,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
*/
obj = NULL;
if (root) {
if (voptions != NULL) {
(void)cfg_map_get(voptions, "forwarders", &obj);
}
if (obj == NULL && goptions != NULL) {
(void)cfg_map_get(goptions, "forwarders", &obj);
}
(void)get_zoneopt(voptions, goptions, NULL, "forwarders", &obj);
}
if (check_forward(config, zoptions, obj) != ISC_R_SUCCESS) {
result = ISC_R_FAILURE;
@ -3572,12 +3574,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
/*
* Forward mode not explicitly configured.
*/
if (voptions != NULL) {
cfg_map_get(voptions, "forward", &obj);
}
if (obj == NULL && goptions != NULL) {
cfg_map_get(goptions, "forward", &obj);
}
(void)get_zoneopt(voptions, goptions, NULL, "forward",
&obj);
if (obj == NULL ||
strcasecmp(cfg_obj_asstring(obj), "first") == 0)
{
@ -3679,13 +3677,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
* Warn if key-directory doesn't exist
*/
obj = NULL;
(void)cfg_map_get(zoptions, "key-directory", &obj);
if (obj == NULL && voptions != NULL) {
(void)cfg_map_get(voptions, "key-directory", &obj);
}
if (obj == NULL && goptions != NULL) {
(void)cfg_map_get(goptions, "key-directory", &obj);
}
(void)get_zoneopt(zoptions, voptions, goptions, "key-directory", &obj);
if (obj != NULL) {
dir = cfg_obj_asstring(obj);
@ -3706,7 +3698,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
cfg_obj_log(obj, ISC_LOG_WARNING,
"key-directory: '%s' %s", dir,
isc_result_totext(tresult));
result = tresult;
if (result == ISC_R_SUCCESS) {
result = tresult;
}
}
}
@ -3722,7 +3716,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
tresult = keydirexist(zconfig, "key-directory", zname,
dir, kaspname, keydirs, mctx);
}
if (tresult != ISC_R_SUCCESS) {
if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS) {
result = tresult;
}
}
@ -3739,7 +3733,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
cfg_obj_log(zconfig, ISC_LOG_ERROR,
"'log-report-channel' cannot be set in "
"the root zone");
result = ISC_R_FAILURE;
if (result == ISC_R_SUCCESS) {
result = ISC_R_FAILURE;
}
}
}
@ -3747,7 +3743,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
* Check various options.
*/
tresult = check_options(zoptions, config, false, mctx, optlevel_zone);
if (tresult != ISC_R_SUCCESS) {
if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS) {
result = tresult;
}
@ -3770,7 +3766,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
"zone '%s': cannot specify both 'dlz' "
"and 'database'",
znamestr);
result = ISC_R_FAILURE;
if (result == ISC_R_SUCCESS) {
result = ISC_R_FAILURE;
}
} else if (!dlz &&
(tresult == ISC_R_NOTFOUND ||
(tresult == ISC_R_SUCCESS &&
@ -3789,14 +3787,17 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
cfg_obj_log(zconfig, ISC_LOG_ERROR,
"zone '%s': missing 'file' entry",
znamestr);
result = tresult;
if (result == ISC_R_SUCCESS) {
result = tresult;
}
} else if (tresult == ISC_R_SUCCESS && files != NULL &&
(ztype == CFG_ZONE_SECONDARY ||
ztype == CFG_ZONE_MIRROR || ddns ||
has_dnssecpolicy))
{
tresult = fileexist(fileobj, files, true);
if (tresult != ISC_R_SUCCESS) {
if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
{
result = tresult;
}
} else if (tresult == ISC_R_SUCCESS && files != NULL &&
@ -3804,12 +3805,84 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
ztype == CFG_ZONE_HINT))
{
tresult = fileexist(fileobj, files, false);
if (tresult != ISC_R_SUCCESS) {
if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
{
result = tresult;
}
}
}
/*
* Check that masterfile-format and masterfile-style are
* consistent.
*/
obj = NULL;
tresult = get_zoneopt(zoptions, voptions, goptions, "masterfile-format",
&obj);
if (tresult == ISC_R_SUCCESS &&
strcasecmp(cfg_obj_asstring(obj), "raw") == 0)
{
obj = NULL;
tresult = get_zoneopt(zoptions, voptions, goptions,
"masterfile-style", &obj);
if (tresult == ISC_R_SUCCESS) {
cfg_obj_log(obj, ISC_LOG_ERROR,
"zone '%s': 'masterfile-style' "
"can only be used with "
"'masterfile-format text'",
znamestr);
if (result == ISC_R_SUCCESS) {
result = ISC_R_FAILURE;
}
}
}
obj = NULL;
(void)get_zoneopt(zoptions, voptions, goptions, "max-journal-size",
&obj);
if (obj != NULL && cfg_obj_isuint64(obj)) {
uint64_t value = cfg_obj_asuint64(obj);
if (value > DNS_JOURNAL_SIZE_MAX) {
cfg_obj_log(obj, ISC_LOG_ERROR,
"'max-journal-size %" PRId64 "' "
"is too large",
value);
if (result == ISC_R_SUCCESS) {
result = ISC_R_RANGE;
}
}
}
obj = NULL;
(void)get_zoneopt(zoptions, voptions, goptions, "min-transfer-rate-in",
&obj);
if (obj != NULL) {
uint32_t traffic_bytes =
cfg_obj_asuint32(cfg_tuple_get(obj, "traffic_bytes"));
uint32_t time_minutes =
cfg_obj_asuint32(cfg_tuple_get(obj, "time_minutes"));
if (traffic_bytes == 0) {
cfg_obj_log(obj, ISC_LOG_ERROR,
"zone '%s': 'min-transfer-rate-in' bytes "
"value cannot be '0'",
znamestr);
if (result == ISC_R_SUCCESS) {
result = ISC_R_RANGE;
}
}
/* Max. 28 days (in minutes). */
const unsigned int time_minutes_max = 28 * 24 * 60;
if (time_minutes < 1 || time_minutes > time_minutes_max) {
cfg_obj_log(obj, ISC_LOG_ERROR,
"zone '%s': 'min-transfer-rate-in' minutes "
"value is out of range (1..%u)",
znamestr, time_minutes_max);
if (result == ISC_R_SUCCESS) {
result = ISC_R_RANGE;
}
}
}
return result;
}