mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 10:10:06 +00:00
new: usr: Add support for zone templates
To simplify the configuration of multiple similar zones, BIND now supports a zone template mechanism. `template` blocks containing zone options can be defined at the top level of the configuration file; they can then be referenced in `zone` statements. A zone referencing a template will use the options in the specified `template` block as defaults. (Options locally defined in the `zone` statement override the template.) The filename for a zone can now be generated parametrically from a format specified in the `file` option. The first occurrences of `$name`, `$type` and `$view` in `file` are replaced with the zone origin, the zone type (i.e., primary, secondary, etc), and the view name, respectively. Primary zones can now take an `initial-file` option, specifying the path to a generic zone file that will be copied into the zone's `file` path when the zone is first loaded, if the `file` does not already exist. For example, the following template can be used for primary zones: ``` template primary { type primary; file "$name.db"; initial-file "generic.db"; }; ``` With this template in place, a new primary zone could be added using a single `rndc addzone` command: ``` $ rndc addzone example.com '{ template primary; };' ``` The zone would be created using the filename `example.com.db`, which would be copied into place from `generic.db`. Closes #2964 Merge branch '2964-zone-templates' into 'main' See merge request isc-projects/bind9!10407
This commit is contained in:
commit
93c44ba551
@ -656,7 +656,7 @@ load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
|
||||
dns_zone_setstream(zone, stdin, fileformat,
|
||||
&dns_master_style_default);
|
||||
} else {
|
||||
dns_zone_setfile(zone, filename, fileformat,
|
||||
dns_zone_setfile(zone, filename, NULL, fileformat,
|
||||
&dns_master_style_default);
|
||||
}
|
||||
if (journal != NULL) {
|
||||
|
@ -387,6 +387,23 @@ named_config_get(cfg_obj_t const *const *maps, const char *name,
|
||||
return ISC_R_NOTFOUND;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
named_config_findopt(const cfg_obj_t *opts1, const cfg_obj_t *opts2,
|
||||
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);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
isc_result_t
|
||||
named_checknames_get(const cfg_obj_t **maps, const char *const names[],
|
||||
const cfg_obj_t **obj) {
|
||||
|
@ -67,3 +67,7 @@ named_config_getport(const cfg_obj_t *config, const char *type,
|
||||
isc_result_t
|
||||
named_config_getkeyalgorithm(const char *str, unsigned int *typep,
|
||||
uint16_t *digestbits);
|
||||
|
||||
isc_result_t
|
||||
named_config_findopt(const cfg_obj_t *opts1, const cfg_obj_t *opts2,
|
||||
const char *name, const cfg_obj_t **objp);
|
||||
|
@ -63,7 +63,7 @@ named_zone_inlinesigning(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
|
||||
isc_result_t
|
||||
named_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone,
|
||||
dns_rdataclass_t rdclass, dns_name_t *name);
|
||||
/*%>
|
||||
/*%<
|
||||
* configure a DLZ zone, setting up the database methods and calling
|
||||
* postload to load the origin values
|
||||
*
|
||||
@ -73,3 +73,11 @@ named_zone_configure_writeable_dlz(dns_dlzdb_t *dlzdatabase, dns_zone_t *zone,
|
||||
* \li 'rdclass' to be a valid rdataclass
|
||||
* \li 'name' to be a valid zone origin name
|
||||
*/
|
||||
|
||||
const cfg_obj_t *
|
||||
named_zone_templateopts(const cfg_obj_t *config, const cfg_obj_t *zoptions);
|
||||
/*%<
|
||||
* If a zone with options `zoptions` specifies a zone template, look
|
||||
* the template options and return them. If no such template is found,
|
||||
* return NULL.
|
||||
*/
|
||||
|
@ -3097,12 +3097,12 @@ cleanup:
|
||||
|
||||
static isc_result_t
|
||||
create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view,
|
||||
const cfg_obj_t *zonelist, const char **empty_dbtype,
|
||||
int empty_dbtypec, dns_zonestat_level_t statlevel) {
|
||||
const cfg_obj_t *config, const cfg_obj_t *voptions,
|
||||
const char **empty_dbtype, int empty_dbtypec,
|
||||
dns_zonestat_level_t statlevel) {
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
const cfg_obj_t *obj = NULL;
|
||||
const cfg_obj_t *zconfig = NULL;
|
||||
const cfg_obj_t *zoptions = NULL;
|
||||
const cfg_obj_t *zonelist = NULL;
|
||||
const char *default_dbtype[4] = { ZONEDB_DEFAULT };
|
||||
const char *sep = ": view ";
|
||||
const char *str = NULL;
|
||||
@ -3126,12 +3126,20 @@ create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view,
|
||||
ns = dns_fixedname_initname(&nsfixed);
|
||||
contact = dns_fixedname_initname(&cfixed);
|
||||
|
||||
if (voptions != NULL) {
|
||||
(void)cfg_map_get(voptions, "zone", &zonelist);
|
||||
} else {
|
||||
(void)cfg_map_get(config, "zone", &zonelist);
|
||||
}
|
||||
/*
|
||||
* Look for forward "zones" beneath this empty zone and if so
|
||||
* create a custom db for the empty zone.
|
||||
*/
|
||||
CFG_LIST_FOREACH (zonelist, element) {
|
||||
zconfig = cfg_listelt_value(element);
|
||||
const cfg_obj_t *zconfig = cfg_listelt_value(element);
|
||||
const cfg_obj_t *zoptions = cfg_tuple_get(zconfig, "options");
|
||||
const cfg_obj_t *toptions = NULL;
|
||||
|
||||
str = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
|
||||
CHECK(dns_name_fromstring(zname, str, dns_rootname, 0, NULL));
|
||||
namereln = dns_name_fullcompare(zname, name, &order, &nlabels);
|
||||
@ -3139,15 +3147,16 @@ create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view,
|
||||
continue;
|
||||
}
|
||||
|
||||
zoptions = cfg_tuple_get(zconfig, "options");
|
||||
toptions = named_zone_templateopts(config, zoptions);
|
||||
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "type", &obj);
|
||||
(void)named_config_findopt(zoptions, toptions, "type", &obj);
|
||||
if (obj != NULL &&
|
||||
strcasecmp(cfg_obj_asstring(obj), "forward") == 0)
|
||||
{
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "forward", &obj);
|
||||
(void)named_config_findopt(zoptions, toptions,
|
||||
"forward", &obj);
|
||||
if (obj == NULL) {
|
||||
continue;
|
||||
}
|
||||
@ -5468,9 +5477,9 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
|
||||
dns_view_detach(&pview);
|
||||
}
|
||||
|
||||
CHECK(create_empty_zone(zone, name, view, zonelist,
|
||||
empty_dbtype, empty_dbtypec,
|
||||
statlevel));
|
||||
CHECK(create_empty_zone(zone, name, view, config,
|
||||
voptions, empty_dbtype,
|
||||
empty_dbtypec, statlevel));
|
||||
if (zone != NULL) {
|
||||
dns_zone_detach(&zone);
|
||||
}
|
||||
@ -6151,6 +6160,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
dns_zone_t *dupzone = NULL;
|
||||
const cfg_obj_t *options = NULL;
|
||||
const cfg_obj_t *zoptions = NULL;
|
||||
const cfg_obj_t *toptions = NULL;
|
||||
const cfg_obj_t *typeobj = NULL;
|
||||
const cfg_obj_t *forwarders = NULL;
|
||||
const cfg_obj_t *forwardtype = NULL;
|
||||
@ -6160,10 +6170,10 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
isc_result_t tresult;
|
||||
isc_buffer_t buffer;
|
||||
dns_fixedname_t fixorigin;
|
||||
dns_name_t *origin;
|
||||
const char *zname;
|
||||
dns_name_t *origin = NULL;
|
||||
const char *zname = NULL;
|
||||
dns_rdataclass_t zclass;
|
||||
const char *ztypestr;
|
||||
const char *ztypestr = NULL;
|
||||
dns_rpz_num_t rpz_num;
|
||||
bool zone_is_catz = false;
|
||||
bool zone_maybe_inline = false;
|
||||
@ -6174,6 +6184,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
(void)cfg_map_get(config, "options", &options);
|
||||
|
||||
zoptions = cfg_tuple_get(zconfig, "options");
|
||||
toptions = named_zone_templateopts(config, zoptions);
|
||||
|
||||
/*
|
||||
* Get the zone origin as a dns_name_t.
|
||||
@ -6258,7 +6269,7 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
(void)cfg_map_get(zoptions, "type", &typeobj);
|
||||
(void)named_config_findopt(zoptions, toptions, "type", &typeobj);
|
||||
if (typeobj == NULL) {
|
||||
cfg_obj_log(zconfig, ISC_LOG_ERROR,
|
||||
"zone '%s' 'type' not specified", zname);
|
||||
@ -6273,7 +6284,9 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
*/
|
||||
if (strcasecmp(ztypestr, "hint") == 0) {
|
||||
const cfg_obj_t *fileobj = NULL;
|
||||
if (cfg_map_get(zoptions, "file", &fileobj) != ISC_R_SUCCESS) {
|
||||
(void)named_config_findopt(zoptions, toptions, "file",
|
||||
&fileobj);
|
||||
if (fileobj == NULL) {
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
"zone '%s': 'file' not specified", zname);
|
||||
@ -6303,8 +6316,10 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
forwardtype = NULL;
|
||||
forwarders = NULL;
|
||||
|
||||
(void)cfg_map_get(zoptions, "forward", &forwardtype);
|
||||
(void)cfg_map_get(zoptions, "forwarders", &forwarders);
|
||||
(void)named_config_findopt(zoptions, toptions, "forward",
|
||||
&forwardtype);
|
||||
(void)named_config_findopt(zoptions, toptions, "forwarders",
|
||||
&forwarders);
|
||||
CHECK(configure_forward(config, view, origin, forwarders,
|
||||
forwardtype));
|
||||
goto cleanup;
|
||||
@ -6463,9 +6478,11 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
* selective forwarding.
|
||||
*/
|
||||
forwarders = NULL;
|
||||
if (cfg_map_get(zoptions, "forwarders", &forwarders) == ISC_R_SUCCESS) {
|
||||
named_config_findopt(zoptions, toptions, "forwarders", &forwarders);
|
||||
if (forwarders != NULL) {
|
||||
forwardtype = NULL;
|
||||
(void)cfg_map_get(zoptions, "forward", &forwardtype);
|
||||
named_config_findopt(zoptions, toptions, "forward",
|
||||
&forwardtype);
|
||||
CHECK(configure_forward(config, view, origin, forwarders,
|
||||
forwardtype));
|
||||
}
|
||||
@ -6497,9 +6514,9 @@ configure_zone(const cfg_obj_t *config, const cfg_obj_t *zconfig,
|
||||
dns_zone_setstats(raw, named_g_server->zonestats);
|
||||
CHECK(dns_zone_link(zone, raw));
|
||||
}
|
||||
if (cfg_map_get(zoptions, "ixfr-from-differences",
|
||||
&ixfrfromdiffs) == ISC_R_SUCCESS)
|
||||
{
|
||||
named_config_findopt(zoptions, toptions,
|
||||
"ixfr-from-differences", &ixfrfromdiffs);
|
||||
if (ixfrfromdiffs != NULL) {
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
|
||||
"zone '%s': 'ixfr-from-differences' is "
|
||||
@ -6599,7 +6616,7 @@ add_keydata_zone(dns_view_t *view, const char *directory, isc_mem_t *mctx) {
|
||||
CHECK(isc_file_sanitize(
|
||||
directory, defaultview ? "managed-keys" : view->name,
|
||||
defaultview ? "bind" : "mkeys", filename, sizeof(filename)));
|
||||
dns_zone_setfile(zone, filename, dns_masterformat_text,
|
||||
dns_zone_setfile(zone, filename, NULL, dns_masterformat_text,
|
||||
&dns_master_style_default);
|
||||
|
||||
dns_zone_setview(zone, view);
|
||||
@ -12459,11 +12476,9 @@ nzd_save(MDB_txn **txnp, MDB_dbi dbi, dns_zone_t *zone,
|
||||
}
|
||||
} else {
|
||||
/* We're creating or overwriting the zone */
|
||||
const cfg_obj_t *zoptions;
|
||||
const cfg_obj_t *zoptions = cfg_tuple_get(zconfig, "options");
|
||||
|
||||
isc_buffer_allocate(view->mctx, &text, 256);
|
||||
|
||||
zoptions = cfg_tuple_get(zconfig, "options");
|
||||
if (zoptions == NULL) {
|
||||
isc_log_write(NAMED_LOGCATEGORY_GENERAL,
|
||||
NAMED_LOGMODULE_SERVER, ISC_LOG_ERROR,
|
||||
@ -12785,16 +12800,14 @@ load_nzf(dns_view_t *view, ns_cfgctx_t *nzcfg) {
|
||||
isc_buffer_allocate(view->mctx, &text, 256);
|
||||
|
||||
CFG_LIST_FOREACH (zonelist, element) {
|
||||
const cfg_obj_t *zconfig;
|
||||
const cfg_obj_t *zconfig = cfg_listelt_value(element);
|
||||
const cfg_obj_t *zoptions;
|
||||
char zname[DNS_NAME_FORMATSIZE];
|
||||
dns_fixedname_t fname;
|
||||
dns_name_t *name;
|
||||
const char *origin;
|
||||
dns_name_t *name = NULL;
|
||||
const char *origin = NULL;
|
||||
isc_buffer_t b;
|
||||
|
||||
zconfig = cfg_listelt_value(element);
|
||||
|
||||
origin = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));
|
||||
if (origin == NULL) {
|
||||
result = ISC_R_FAILURE;
|
||||
@ -12943,10 +12956,15 @@ newzone_parse(named_server_t *server, char *command, dns_view_t **viewp,
|
||||
if (obj != NULL) {
|
||||
(void)putstr(text, "'in-view' zones not supported by ");
|
||||
(void)putstr(text, bn);
|
||||
} else {
|
||||
(void)putstr(text, "zone type not specified");
|
||||
CHECK(ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
(void)cfg_map_get(zoptions, "template", &obj);
|
||||
if (obj == NULL) {
|
||||
(void)putstr(text, "no zone type or "
|
||||
"template specified");
|
||||
CHECK(ISC_R_FAILURE);
|
||||
}
|
||||
CHECK(ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
if (strcasecmp(cfg_obj_asstring(obj), "hint") == 0 ||
|
||||
@ -13518,14 +13536,12 @@ named_server_changezone(named_server_t *server, char *command,
|
||||
(void)putstr(text, "Not allowing new zones in view '");
|
||||
(void)putstr(text, view->name);
|
||||
(void)putstr(text, "'");
|
||||
result = ISC_R_NOPERM;
|
||||
goto cleanup;
|
||||
CHECK(ISC_R_NOPERM);
|
||||
}
|
||||
|
||||
cfg = (ns_cfgctx_t *)view->new_zone_config;
|
||||
if (cfg == NULL) {
|
||||
result = ISC_R_FAILURE;
|
||||
goto cleanup;
|
||||
CHECK(ISC_R_FAILURE);
|
||||
}
|
||||
|
||||
zonename = cfg_obj_asstring(cfg_tuple_get(zoneobj, "name"));
|
||||
@ -13922,12 +13938,16 @@ find_name_in_list_from_map(const cfg_obj_t *config,
|
||||
if (result == ISC_R_SUCCESS &&
|
||||
dns_name_equal(name1, name2))
|
||||
{
|
||||
const cfg_obj_t *zoptions;
|
||||
const cfg_obj_t *zoptions =
|
||||
cfg_tuple_get(obj, "options");
|
||||
const cfg_obj_t *typeobj = NULL;
|
||||
zoptions = cfg_tuple_get(obj, "options");
|
||||
|
||||
if (zoptions != NULL) {
|
||||
cfg_map_get(zoptions, "type", &typeobj);
|
||||
const cfg_obj_t *toptions =
|
||||
named_zone_templateopts(
|
||||
config, zoptions);
|
||||
named_config_findopt(zoptions, toptions,
|
||||
"type", &typeobj);
|
||||
}
|
||||
if (redirect && typeobj != NULL &&
|
||||
strcasecmp(cfg_obj_asstring(typeobj),
|
||||
|
@ -77,12 +77,12 @@ configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
|
||||
void (*setzacl)(dns_zone_t *, dns_acl_t *),
|
||||
void (*clearzacl)(dns_zone_t *)) {
|
||||
isc_result_t result;
|
||||
const cfg_obj_t *maps[5] = { NULL, NULL, NULL, NULL, NULL };
|
||||
const cfg_obj_t *maps[6] = { 0 };
|
||||
const cfg_obj_t *aclobj = NULL;
|
||||
int i = 0;
|
||||
dns_acl_t **aclp = NULL, *acl = NULL;
|
||||
const char *aclname;
|
||||
dns_view_t *view;
|
||||
dns_view_t *view = NULL;
|
||||
|
||||
view = dns_zone_getview(zone);
|
||||
|
||||
@ -129,7 +129,7 @@ configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
|
||||
|
||||
/* First check to see if ACL is defined within the zone */
|
||||
if (zconfig != NULL) {
|
||||
maps[0] = cfg_tuple_get(zconfig, "options");
|
||||
maps[i] = cfg_tuple_get(zconfig, "options");
|
||||
(void)named_config_get(maps, aclname, &aclobj);
|
||||
if (aclobj != NULL) {
|
||||
aclp = NULL;
|
||||
@ -137,6 +137,14 @@ configure_zone_acl(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
|
||||
}
|
||||
}
|
||||
|
||||
if (config != NULL && maps[i] != NULL) {
|
||||
const cfg_obj_t *toptions = named_zone_templateopts(config,
|
||||
maps[i]);
|
||||
if (toptions != NULL) {
|
||||
maps[i++] = toptions;
|
||||
}
|
||||
}
|
||||
|
||||
/* Failing that, see if there's a default ACL already in the view */
|
||||
if (aclp != NULL && *aclp != NULL) {
|
||||
(*setzacl)(zone, *aclp);
|
||||
@ -187,8 +195,8 @@ parse_acl:
|
||||
* Parse the zone update-policy statement.
|
||||
*/
|
||||
static isc_result_t
|
||||
configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone,
|
||||
const char *zname) {
|
||||
configure_zone_ssutable(const cfg_obj_t *zconfig, const cfg_obj_t *tconfig,
|
||||
dns_zone_t *zone, const char *zname) {
|
||||
const cfg_obj_t *updatepolicy = NULL;
|
||||
dns_ssutable_t *table = NULL;
|
||||
isc_mem_t *mctx = dns_zone_getmctx(zone);
|
||||
@ -200,8 +208,8 @@ configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone,
|
||||
isc_buffer_init(&dbuf, debug, sizeof(debug));
|
||||
isc_buffer_setmctx(&dbuf, mctx);
|
||||
|
||||
(void)cfg_map_get(zconfig, "update-policy", &updatepolicy);
|
||||
|
||||
(void)named_config_findopt(zconfig, tconfig, "update-policy",
|
||||
&updatepolicy);
|
||||
if (updatepolicy == NULL) {
|
||||
dns_zone_setssutable(zone, NULL);
|
||||
return ISC_R_SUCCESS;
|
||||
@ -540,8 +548,8 @@ configure_staticstub_servernames(const cfg_obj_t *zconfig, dns_zone_t *zone,
|
||||
* Configure static-stub zone.
|
||||
*/
|
||||
static isc_result_t
|
||||
configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone,
|
||||
const char *zname, const char *dbtype) {
|
||||
configure_staticstub(const cfg_obj_t *zconfig, const cfg_obj_t *tconfig,
|
||||
dns_zone_t *zone, const char *zname, const char *dbtype) {
|
||||
int i = 0;
|
||||
const cfg_obj_t *obj;
|
||||
isc_mem_t *mctx = dns_zone_getmctx(zone);
|
||||
@ -583,18 +591,16 @@ configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone,
|
||||
|
||||
/* Prepare zone RRs from the configuration */
|
||||
obj = NULL;
|
||||
result = cfg_map_get(zconfig, "server-addresses", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
INSIST(obj != NULL);
|
||||
(void)named_config_findopt(zconfig, tconfig, "server-addresses", &obj);
|
||||
if (obj != NULL) {
|
||||
CHECK(configure_staticstub_serveraddrs(obj, zone, &rdatalist_ns,
|
||||
&rdatalist_a,
|
||||
&rdatalist_aaaa));
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
result = cfg_map_get(zconfig, "server-names", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
INSIST(obj != NULL);
|
||||
(void)named_config_findopt(zconfig, tconfig, "server-names", &obj);
|
||||
if (obj != NULL) {
|
||||
CHECK(configure_staticstub_servernames(obj, zone, &rdatalist_ns,
|
||||
zname));
|
||||
}
|
||||
@ -682,12 +688,11 @@ cleanup:
|
||||
* Convert a config file zone type into a server zone type.
|
||||
*/
|
||||
static dns_zonetype_t
|
||||
zonetype_fromconfig(const cfg_obj_t *map) {
|
||||
zonetype_fromconfig(const cfg_obj_t *zmap, const cfg_obj_t *tmap) {
|
||||
const cfg_obj_t *obj = NULL;
|
||||
isc_result_t result;
|
||||
|
||||
result = cfg_map_get(map, "type", &obj);
|
||||
INSIST(result == ISC_R_SUCCESS && obj != NULL);
|
||||
(void)named_config_findopt(zmap, tmap, "type", &obj);
|
||||
INSIST(obj != NULL);
|
||||
return named_config_getzonetype(obj);
|
||||
}
|
||||
|
||||
@ -872,12 +877,15 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
const char *zname;
|
||||
dns_rdataclass_t zclass;
|
||||
dns_rdataclass_t vclass;
|
||||
const cfg_obj_t *maps[5];
|
||||
const cfg_obj_t *nodefault[4];
|
||||
const cfg_obj_t *maps[6];
|
||||
const cfg_obj_t *nodefault[5];
|
||||
const cfg_obj_t *nooptions[3];
|
||||
const cfg_obj_t *zoptions = NULL;
|
||||
const cfg_obj_t *toptions = NULL;
|
||||
const cfg_obj_t *options = NULL;
|
||||
const cfg_obj_t *obj;
|
||||
const cfg_obj_t *obj = NULL;
|
||||
const char *filename = NULL;
|
||||
const char *initial_file = NULL;
|
||||
const char *kaspname = NULL;
|
||||
const char *dupcheck;
|
||||
dns_checkdstype_t checkdstype = dns_checkdstype_yes;
|
||||
@ -909,23 +917,34 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
bool transferinsecs = ns_server_getoption(named_g_server->sctx,
|
||||
NS_SERVER_TRANSFERINSECS);
|
||||
|
||||
REQUIRE(config != NULL);
|
||||
REQUIRE(zconfig != NULL);
|
||||
|
||||
i = 0;
|
||||
if (zconfig != NULL) {
|
||||
zoptions = cfg_tuple_get(zconfig, "options");
|
||||
nodefault[i] = maps[i] = zoptions;
|
||||
|
||||
zoptions = cfg_tuple_get(zconfig, "options");
|
||||
INSIST(zoptions != NULL);
|
||||
nodefault[i] = nooptions[i] = maps[i] = zoptions;
|
||||
i++;
|
||||
|
||||
toptions = named_zone_templateopts(config, zoptions);
|
||||
if (toptions != NULL) {
|
||||
nodefault[i] = nooptions[i] = maps[i] = toptions;
|
||||
i++;
|
||||
}
|
||||
|
||||
nooptions[i] = NULL;
|
||||
if (vconfig != NULL) {
|
||||
nodefault[i] = maps[i] = cfg_tuple_get(vconfig, "options");
|
||||
i++;
|
||||
}
|
||||
if (config != NULL) {
|
||||
(void)cfg_map_get(config, "options", &options);
|
||||
if (options != NULL) {
|
||||
nodefault[i] = maps[i] = options;
|
||||
i++;
|
||||
}
|
||||
|
||||
(void)cfg_map_get(config, "options", &options);
|
||||
if (options != NULL) {
|
||||
nodefault[i] = maps[i] = options;
|
||||
i++;
|
||||
}
|
||||
|
||||
nodefault[i] = NULL;
|
||||
maps[i++] = named_g_defaults;
|
||||
maps[i] = NULL;
|
||||
@ -950,7 +969,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
dns_zone_setclass(raw, zclass);
|
||||
}
|
||||
|
||||
ztype = zonetype_fromconfig(zoptions);
|
||||
ztype = zonetype_fromconfig(zoptions, toptions);
|
||||
if (raw != NULL) {
|
||||
dns_zone_settype(raw, ztype);
|
||||
dns_zone_settype(zone, dns_zone_primary);
|
||||
@ -959,13 +978,13 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
result = cfg_map_get(zoptions, "database", &obj);
|
||||
result = named_config_get(nooptions, "database", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
result = cfg_map_get(zoptions, "dlz", &obj);
|
||||
result = named_config_get(nooptions, "dlz", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
const char *dlzname = cfg_obj_asstring(obj);
|
||||
size_t len = strlen(dlzname) + 5;
|
||||
@ -991,11 +1010,17 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
result = cfg_map_get(zoptions, "file", &obj);
|
||||
result = named_config_get(nooptions, "file", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
filename = cfg_obj_asstring(obj);
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
result = named_config_get(nooptions, "initial-file", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
initial_file = cfg_obj_asstring(obj);
|
||||
}
|
||||
|
||||
if (ztype == dns_zone_secondary || ztype == dns_zone_mirror) {
|
||||
masterformat = dns_masterformat_raw;
|
||||
} else {
|
||||
@ -1053,18 +1078,21 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
size_t signedlen = strlen(filename) + sizeof(SIGNED);
|
||||
char *signedname;
|
||||
|
||||
dns_zone_setfile(raw, filename, masterformat, masterstyle);
|
||||
dns_zone_setfile(raw, filename, initial_file, masterformat,
|
||||
masterstyle);
|
||||
signedname = isc_mem_get(mctx, signedlen);
|
||||
|
||||
(void)snprintf(signedname, signedlen, "%s" SIGNED, filename);
|
||||
dns_zone_setfile(zone, signedname, dns_masterformat_raw, NULL);
|
||||
dns_zone_setfile(zone, signedname, NULL, dns_masterformat_raw,
|
||||
NULL);
|
||||
isc_mem_put(mctx, signedname, signedlen);
|
||||
} else {
|
||||
dns_zone_setfile(zone, filename, masterformat, masterstyle);
|
||||
dns_zone_setfile(zone, filename, initial_file, masterformat,
|
||||
masterstyle);
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
result = cfg_map_get(zoptions, "journal", &obj);
|
||||
result = named_config_get(nooptions, "journal", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
dns_zone_setjournal(mayberaw, cfg_obj_asstring(obj));
|
||||
}
|
||||
@ -1423,7 +1451,8 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
cfg_obj_asboolean(obj));
|
||||
|
||||
obj = NULL;
|
||||
result = cfg_map_get(zoptions, "log-report-channel", &obj);
|
||||
result = named_config_get(nooptions, "log-report-channel",
|
||||
&obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
logreports = cfg_obj_asboolean(obj);
|
||||
dns_zone_setoption(zone, DNS_ZONEOPT_LOGREPORTS,
|
||||
@ -1523,7 +1552,8 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
zname);
|
||||
}
|
||||
|
||||
CHECK(configure_zone_ssutable(zoptions, mayberaw, zname));
|
||||
CHECK(configure_zone_ssutable(zoptions, toptions, mayberaw,
|
||||
zname));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1608,7 +1638,8 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
*/
|
||||
if (ztype == dns_zone_primary || ztype == dns_zone_secondary) {
|
||||
const cfg_obj_t *parentals = NULL;
|
||||
(void)cfg_map_get(zoptions, "parental-agents", &parentals);
|
||||
(void)named_config_get(nooptions, "parental-agents",
|
||||
&parentals);
|
||||
if (parentals != NULL) {
|
||||
dns_ipkeylist_t ipkl;
|
||||
dns_ipkeylist_init(&ipkl);
|
||||
@ -1759,7 +1790,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
* are explicitly enabled by zone configuration.
|
||||
*/
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "allow-transfer", &obj);
|
||||
(void)named_config_get(nooptions, "allow-transfer", &obj);
|
||||
if (obj == NULL) {
|
||||
dns_acl_t *none;
|
||||
CHECK(dns_acl_none(mctx, &none));
|
||||
@ -1772,9 +1803,9 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
case dns_zone_redirect:
|
||||
count = 0;
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "primaries", &obj);
|
||||
(void)named_config_get(nooptions, "primaries", &obj);
|
||||
if (obj == NULL) {
|
||||
(void)cfg_map_get(zoptions, "masters", &obj);
|
||||
(void)named_config_get(nooptions, "masters", &obj);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1876,7 +1907,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
break;
|
||||
|
||||
case dns_zone_staticstub:
|
||||
CHECK(configure_staticstub(zoptions, zone, zname,
|
||||
CHECK(configure_staticstub(zoptions, toptions, zone, zname,
|
||||
default_dbtype));
|
||||
break;
|
||||
|
||||
@ -1917,20 +1948,22 @@ named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig,
|
||||
const cfg_obj_t *vconfig, const cfg_obj_t *config,
|
||||
dns_kasplist_t *kasplist) {
|
||||
const cfg_obj_t *zoptions = NULL;
|
||||
const cfg_obj_t *toptions = NULL;
|
||||
const cfg_obj_t *obj = NULL;
|
||||
const char *cfilename;
|
||||
const char *zfilename;
|
||||
const char *cfilename = NULL;
|
||||
const char *zfilename = NULL;
|
||||
dns_zone_t *raw = NULL;
|
||||
bool has_raw, inline_signing;
|
||||
dns_zonetype_t ztype;
|
||||
|
||||
zoptions = cfg_tuple_get(zconfig, "options");
|
||||
toptions = named_zone_templateopts(config, zoptions);
|
||||
|
||||
/*
|
||||
* We always reconfigure a static-stub zone for simplicity, assuming
|
||||
* the amount of data to be loaded is small.
|
||||
*/
|
||||
if (zonetype_fromconfig(zoptions) == dns_zone_staticstub) {
|
||||
if (zonetype_fromconfig(zoptions, toptions) == dns_zone_staticstub) {
|
||||
dns_zone_log(zone, ISC_LOG_DEBUG(1),
|
||||
"not reusable: staticstub");
|
||||
return false;
|
||||
@ -1961,14 +1994,14 @@ named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (zonetype_fromconfig(zoptions) != ztype) {
|
||||
if (zonetype_fromconfig(zoptions, toptions) != ztype) {
|
||||
dns_zone_log(zone, ISC_LOG_DEBUG(1),
|
||||
"not reusable: type mismatch");
|
||||
return false;
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "file", &obj);
|
||||
(void)named_config_findopt(zoptions, toptions, "file", &obj);
|
||||
if (obj != NULL) {
|
||||
cfilename = cfg_obj_asstring(obj);
|
||||
} else {
|
||||
@ -1989,15 +2022,27 @@ named_zone_reusable(dns_zone_t *zone, const cfg_obj_t *zconfig,
|
||||
bool
|
||||
named_zone_inlinesigning(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
|
||||
const cfg_obj_t *config, dns_kasplist_t *kasplist) {
|
||||
const cfg_obj_t *maps[4];
|
||||
const cfg_obj_t *maps[5] = { 0 }, *noopts[3] = { 0 };
|
||||
const cfg_obj_t *signing = NULL;
|
||||
const cfg_obj_t *policy = NULL;
|
||||
const cfg_obj_t *toptions = NULL;
|
||||
dns_kasp_t *kasp = NULL;
|
||||
isc_result_t res;
|
||||
bool inline_signing = false;
|
||||
int i = 0;
|
||||
|
||||
maps[i++] = cfg_tuple_get(zconfig, "options");
|
||||
noopts[i] = maps[i] = cfg_tuple_get(zconfig, "options");
|
||||
i++;
|
||||
|
||||
if (config != NULL) {
|
||||
toptions = named_zone_templateopts(config, maps[0]);
|
||||
if (toptions != NULL) {
|
||||
noopts[i] = maps[i] = toptions;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
noopts[i] = NULL;
|
||||
if (vconfig != NULL) {
|
||||
maps[i++] = cfg_tuple_get(vconfig, "options");
|
||||
}
|
||||
@ -2031,13 +2076,35 @@ named_zone_inlinesigning(const cfg_obj_t *zconfig, const cfg_obj_t *vconfig,
|
||||
|
||||
/*
|
||||
* The zone option 'inline-signing' may override the value in
|
||||
* dnssec-policy. This is a zone-only option, so look in maps[0]
|
||||
* only.
|
||||
* dnssec-policy. This is a zone-only option, so look in the
|
||||
* zone and template blocks only.
|
||||
*/
|
||||
res = cfg_map_get(maps[0], "inline-signing", &signing);
|
||||
res = named_config_get(noopts, "inline-signing", &signing);
|
||||
if (res == ISC_R_SUCCESS && cfg_obj_isboolean(signing)) {
|
||||
return cfg_obj_asboolean(signing);
|
||||
}
|
||||
|
||||
return inline_signing;
|
||||
}
|
||||
|
||||
const cfg_obj_t *
|
||||
named_zone_templateopts(const cfg_obj_t *config, const cfg_obj_t *zoptions) {
|
||||
const cfg_obj_t *templates = NULL;
|
||||
const cfg_obj_t *obj = NULL;
|
||||
|
||||
(void)cfg_map_get(config, "template", &templates);
|
||||
(void)cfg_map_get(zoptions, "template", &obj);
|
||||
if (obj != NULL && templates != NULL) {
|
||||
const char *tmplname = cfg_obj_asstring(obj);
|
||||
CFG_LIST_FOREACH (templates, e) {
|
||||
const cfg_obj_t *t = cfg_tuple_get(cfg_listelt_value(e),
|
||||
"name");
|
||||
if (strcasecmp(cfg_obj_asstring(t), tmplname) == 0) {
|
||||
return cfg_tuple_get(cfg_listelt_value(e),
|
||||
"options");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
; See the COPYRIGHT file distributed with this work for additional
|
||||
; information regarding copyright ownership.
|
||||
|
||||
;$ORIGIN added.example.
|
||||
$TTL 300 ; 5 minutes
|
||||
@ IN SOA mname1. . (
|
||||
1 ; serial
|
||||
|
@ -28,6 +28,12 @@ controls {
|
||||
inet 10.53.0.2 port @CONTROLPORT@ allow { any; } keys { rndc_key; };
|
||||
};
|
||||
|
||||
template primary {
|
||||
type primary;
|
||||
file "$view-$name.db";
|
||||
initial-file "added.db";
|
||||
};
|
||||
|
||||
zone "." {
|
||||
type hint;
|
||||
file "../../_common/root.hint";
|
||||
|
@ -27,6 +27,12 @@ options {
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
template primary {
|
||||
type primary;
|
||||
file "$view-$name.db";
|
||||
initial-file "added.db";
|
||||
};
|
||||
|
||||
view internal {
|
||||
match-clients { 10.53.0.2; };
|
||||
allow-new-zones no;
|
||||
|
@ -27,6 +27,12 @@ options {
|
||||
dnssec-validation no;
|
||||
};
|
||||
|
||||
template primary {
|
||||
type primary;
|
||||
file "$view-$name.db";
|
||||
initial-file "added.db";
|
||||
};
|
||||
|
||||
view internal {
|
||||
match-clients { 10.53.0.2; };
|
||||
allow-new-zones no;
|
||||
|
@ -745,5 +745,29 @@ if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
n=$((n + 1))
|
||||
|
||||
echo_i "checking addzone with zone template (primary) ($n)"
|
||||
ret=0
|
||||
$RNDCCMD 10.53.0.2 addzone 'template.example in external { template primary; };' 2>&1 | sed 's/^/I:ns2 /'
|
||||
$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.2 a.template.example a >dig.out.ns2.int.$n || ret=1
|
||||
grep 'status: NOERROR' dig.out.ns2.int.$n >/dev/null || ret=1
|
||||
grep 'ANSWER: 0' dig.out.ns2.int.$n >/dev/null || ret=1
|
||||
$DIG +norec $DIGOPTS @10.53.0.2 -b 10.53.0.4 a.template.example a >dig.out.ns2.ext.$n || ret=1
|
||||
grep 'status: NOERROR' dig.out.ns2.ext.$n >/dev/null || ret=1
|
||||
grep 'ANSWER: 1' dig.out.ns2.ext.$n >/dev/null || ret=1
|
||||
test -f ns2/external-template.example.db
|
||||
n=$((n + 1))
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "checking addzone with nonexistent template ($n)"
|
||||
ret=0
|
||||
nextpart ns2/named.run >/dev/null
|
||||
$RNDCCMD 10.53.0.2 addzone 'wrong.example in external { template nope; };' 2>&1 | grep -qF "failure" || ret=1
|
||||
nextpart ns2/named.run | grep -qF "zone 'wrong.example': template 'nope' not found" || ret=1
|
||||
test -f ns2/wrong-template.example.db && ret=1
|
||||
n=$((n + 1))
|
||||
if [ $ret != 0 ]; then echo_i "failed"; fi
|
||||
status=$((status + ret))
|
||||
|
||||
echo_i "exit status: $status"
|
||||
[ $status -eq 0 ] || exit 1
|
||||
|
@ -26,6 +26,7 @@ pytestmark = pytest.mark.extra_artifacts(
|
||||
"ns2/K*.private",
|
||||
"ns2/K*.state",
|
||||
"ns2/external.nzd",
|
||||
"ns2/external-template.example.db",
|
||||
"ns2/extra.nzd",
|
||||
"ns2/inline.db.jbk",
|
||||
"ns2/inline.db.signed",
|
||||
|
23
bin/tests/system/checkconf/bad-template-1.conf
Normal file
23
bin/tests/system/checkconf/bad-template-1.conf
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
template a {
|
||||
type primary;
|
||||
file "$name.db";
|
||||
initial-file "template.db";
|
||||
};
|
||||
|
||||
zone example {
|
||||
template a;
|
||||
type secondary;
|
||||
};
|
22
bin/tests/system/checkconf/bad-template-2.conf
Normal file
22
bin/tests/system/checkconf/bad-template-2.conf
Normal file
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
template a {
|
||||
type primary;
|
||||
file "$name.db";
|
||||
initial-file "template.db";
|
||||
};
|
||||
|
||||
template b {
|
||||
template a;
|
||||
};
|
23
bin/tests/system/checkconf/bad-template-3.conf
Normal file
23
bin/tests/system/checkconf/bad-template-3.conf
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
template a {
|
||||
type primary;
|
||||
file "$name.db";
|
||||
initial-file "template.db";
|
||||
};
|
||||
|
||||
zone example.com {
|
||||
# specify an undefined template
|
||||
template c;
|
||||
};
|
17
bin/tests/system/checkconf/bad-template-4.conf
Normal file
17
bin/tests/system/checkconf/bad-template-4.conf
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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.com {
|
||||
# specify a template, but there are no templates
|
||||
template c;
|
||||
};
|
23
bin/tests/system/checkconf/good-template-1.conf
Normal file
23
bin/tests/system/checkconf/good-template-1.conf
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
template a {
|
||||
type primary;
|
||||
file "$name.db";
|
||||
initial-file "template.db";
|
||||
};
|
||||
|
||||
zone example {
|
||||
template a;
|
||||
file "othername.db";
|
||||
};
|
@ -11,6 +11,7 @@
|
||||
|
||||
import difflib
|
||||
import shutil
|
||||
import os
|
||||
from typing import Optional
|
||||
|
||||
import dns.rcode
|
||||
@ -150,3 +151,7 @@ def file_contents_equal(file1, file2):
|
||||
assert not line.startswith("+ ") and not line.startswith(
|
||||
"- "
|
||||
), f'file contents of "{file1}" and "{file2}" differ'
|
||||
|
||||
|
||||
def file_empty(file):
|
||||
assert os.path.getsize(file) == 0
|
||||
|
@ -34,12 +34,33 @@ zone "." {
|
||||
file "../../_common/root.hint";
|
||||
};
|
||||
|
||||
zone "example" {
|
||||
template primary {
|
||||
type primary;
|
||||
file "example.db";
|
||||
file "$name.db";
|
||||
};
|
||||
|
||||
zone "example" {
|
||||
template primary;
|
||||
};
|
||||
|
||||
zone "missing" {
|
||||
type primary;
|
||||
file "missing.db";
|
||||
template primary;
|
||||
};
|
||||
|
||||
zone "different" {
|
||||
template primary;
|
||||
initial-file "example.db";
|
||||
file "alternate.db";
|
||||
};
|
||||
|
||||
zone "initial" {
|
||||
type primary;
|
||||
file "copied.db";
|
||||
initial-file "example.db";
|
||||
};
|
||||
|
||||
zone "present" {
|
||||
type primary;
|
||||
file "present.db";
|
||||
initial-file "example.db";
|
||||
};
|
||||
|
19
bin/tests/system/masterfile/setup.sh
Normal file
19
bin/tests/system/masterfile/setup.sh
Normal file
@ -0,0 +1,19 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
# 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.
|
||||
|
||||
# shellcheck source=conf.sh
|
||||
. ../conf.sh
|
||||
|
||||
set -e
|
||||
|
||||
touch ns2/present.db
|
@ -15,6 +15,11 @@ import dns.message
|
||||
import dns.zone
|
||||
|
||||
import isctest
|
||||
import pytest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
["ns2/copied.db", "ns2/present.db", "ns2/alternate.db"]
|
||||
)
|
||||
|
||||
|
||||
def test_masterfile_include_semantics():
|
||||
@ -87,6 +92,54 @@ example. 300 IN SOA mname1. . 2010042407 20 20 1814400 3600
|
||||
isctest.check.rrsets_equal(res_soa.answer, expected.answer, compare_ttl=True)
|
||||
|
||||
|
||||
def test_masterfile_initial_file():
|
||||
"""Test zone configurations with initial template files"""
|
||||
# example inherited its configuration from the template,
|
||||
# make sure it works
|
||||
msg_soa = dns.message.make_query("example.", "SOA")
|
||||
res_soa = isctest.query.tcp(msg_soa, "10.53.0.2")
|
||||
expected_soa_rr = """;ANSWER
|
||||
example. 300 IN SOA mname1. . 2010042407 20 20 1814400 3600
|
||||
"""
|
||||
expected = dns.message.from_text(expected_soa_rr)
|
||||
isctest.check.rrsets_equal(res_soa.answer, expected.answer)
|
||||
|
||||
# initial uses an initial-file option with the "file"
|
||||
# option set to "copied.db". make sure it works and that
|
||||
# copied.db has been populated.
|
||||
msg_soa = dns.message.make_query("initial.", "SOA")
|
||||
res_soa = isctest.query.tcp(msg_soa, "10.53.0.2")
|
||||
expected_soa_rr = """;ANSWER
|
||||
initial. 300 IN SOA mname1. . 2010042407 20 20 1814400 3600
|
||||
"""
|
||||
expected = dns.message.from_text(expected_soa_rr)
|
||||
isctest.check.rrsets_equal(res_soa.answer, expected.answer)
|
||||
isctest.check.file_contents_equal("ns2/example.db", "ns2/copied.db")
|
||||
|
||||
# present uses an initial-file option, but the file 'present.db'
|
||||
# already exists and is empty, so the initial-file should not be
|
||||
# copied into place and the zone should not load.
|
||||
msg_soa = dns.message.make_query("present.", "SOA")
|
||||
res_soa = isctest.query.tcp(msg_soa, "10.53.0.2")
|
||||
isctest.check.servfail(res_soa)
|
||||
isctest.check.file_empty("ns2/present.db")
|
||||
|
||||
|
||||
def test_masterfile_template_override():
|
||||
"""Test zone configurations with overridden template options"""
|
||||
# different inherited configuration from the template, but
|
||||
# overrides the "file" option to 'alternate.db'.
|
||||
msg_soa = dns.message.make_query("different.", "SOA")
|
||||
res_soa = isctest.query.tcp(msg_soa, "10.53.0.2")
|
||||
expected_soa_rr = """;ANSWER
|
||||
different. 300 IN SOA mname1. . 2010042407 20 20 1814400 3600
|
||||
"""
|
||||
expected = dns.message.from_text(expected_soa_rr)
|
||||
isctest.check.rrsets_equal(res_soa.answer, expected.answer)
|
||||
isctest.check.file_contents_equal("ns2/example.db", "ns2/alternate.db")
|
||||
assert not os.path.exists("ns2/different.db")
|
||||
|
||||
|
||||
def test_masterfile_missing_master_file_servfail():
|
||||
"""Test nameserver returning SERVFAIL for a missing master file"""
|
||||
msg_soa = dns.message.make_query("missing.", "SOA")
|
||||
|
@ -7038,6 +7038,13 @@ mid-1970s. Zone data for it can be specified with the ``CHAOS`` class.
|
||||
Zone Options
|
||||
^^^^^^^^^^^^
|
||||
|
||||
.. namedconf:statement:: template
|
||||
:tags: zone
|
||||
:short: Specifies a template to use for zone configuration.
|
||||
|
||||
This specifies a zone template from which to import other zone options.
|
||||
See :ref:`zone_templates` for details.
|
||||
|
||||
:any:`allow-notify`
|
||||
See the description of :any:`allow-notify` in :ref:`access_control`.
|
||||
|
||||
@ -7132,13 +7139,21 @@ Zone Options
|
||||
:tags: zone
|
||||
:short: Specifies the zone's filename.
|
||||
|
||||
This sets the zone's filename. In :any:`primary <type primary>`, :any:`hint <type hint>`, and :any:`redirect <type redirect>`
|
||||
This sets the zone's filename. In :any:`primary <type primary>`,
|
||||
:any:`hint <type hint>`, and :any:`redirect <type redirect>`
|
||||
zones which do not have :any:`primaries` defined, zone data is loaded from
|
||||
this file. In :any:`secondary <type secondary>`, :any:`mirror <type mirror>`, :any:`stub <type stub>`, and :any:`redirect <type redirect>` zones
|
||||
which do have :any:`primaries` defined, zone data is retrieved from
|
||||
another server and saved in this file. This option is not applicable
|
||||
to other zone types.
|
||||
|
||||
The filename can be generated parametrically by including special
|
||||
tokens in the string: the first instance of ``$name`` in the string
|
||||
is replaced with the zone name in lower case; the first instance of
|
||||
``$type`` is replaced with the zone type -- i.e., ``primary``,
|
||||
``secondary``, etc); and the first instance of ``$view`` is replaced
|
||||
with the view name. These tokens are case-insensitive.
|
||||
|
||||
:any:`forward`
|
||||
This option is only meaningful if the zone has a forwarders list. The ``only`` value
|
||||
causes the lookup to fail after trying the forwarders and getting no
|
||||
@ -7149,6 +7164,34 @@ Zone Options
|
||||
specified in a zone of type :any:`forward`, no forwarding is done for
|
||||
the zone and the global options are not used.
|
||||
|
||||
.. namedconf:statement:: initial-file
|
||||
:tags: zone
|
||||
:short: Specifies a file with the initial contents of a newly created zone.
|
||||
|
||||
When a :any:`primary <type primary>` zone is loaded for the first time,
|
||||
if the zone's :any:`file` does not exist but ``initial-file`` does, the
|
||||
zone file is copied into place from the initial file before loading.
|
||||
This can be used to simplify the process of adding new zones, removing
|
||||
the need to create the zone file before configuring the zone. For example,
|
||||
a template zonefile could be used by running:
|
||||
|
||||
::
|
||||
|
||||
$ rndc addzone example.com \
|
||||
'{ type primary; file "$name.db"; initial-file "template.db"; };'
|
||||
|
||||
This creates a zone ``example.com``, with filename ``example.com.db``.
|
||||
|
||||
Using "@" to reference the zone origin within the initial file
|
||||
allows the same file to be used for multiple zones, as in:
|
||||
|
||||
::
|
||||
|
||||
$TTL 300
|
||||
@ IN SOA ns hosmaster 1 1800 1800 86400 3600
|
||||
NS ns
|
||||
ns A 192.0.2.1
|
||||
|
||||
.. namedconf:statement:: journal
|
||||
:tags: zone
|
||||
:short: Allows the default journal's filename to be overridden.
|
||||
@ -7341,6 +7384,52 @@ Zone Options
|
||||
:any:`send-report-channel`
|
||||
See the description of :any:`send-report-channel` in :namedconf:ref:`options`.
|
||||
|
||||
.. _zone_templates:
|
||||
|
||||
Zone Templates
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
To simplify the configuration of multiple similar zones, BIND 9
|
||||
supports a zone template mechanism. ``template`` blocks can be
|
||||
defined at the top level of the configuration; these blocks can
|
||||
contain any set of options that could be set in a :any:`zone`
|
||||
statement, with the exceptions of :any:`in-view` and :any:`template`.
|
||||
|
||||
Once a template has been defined, it can be referenced in a
|
||||
:any:`zone` statement; the zone is then configured using the
|
||||
options specified in the :any:`template` as defaults.
|
||||
Options that are locally defined within the :any:`zone` statement
|
||||
override the template.
|
||||
|
||||
For example, the following configuration would define two primary
|
||||
and two secondary zones:
|
||||
|
||||
::
|
||||
|
||||
template primary {
|
||||
type primary;
|
||||
file "$type/$name.db";
|
||||
initial-file "initial.db";
|
||||
};
|
||||
|
||||
template secondary {
|
||||
type secondary;
|
||||
file "$type/$name.db";
|
||||
primaries { 192.0.2.1; };
|
||||
};
|
||||
|
||||
zone example.com { template primary; };
|
||||
zone example.org { template primary; };
|
||||
zone example.net { template secondary; };
|
||||
zone example.edu { template secondary; };
|
||||
|
||||
Templates can also be used for zones that are added using
|
||||
``rndc addzone`` (see :any:`allow-new-zones`):
|
||||
|
||||
::
|
||||
|
||||
$ rndc addzone example.biz '{ template secondary; };'
|
||||
|
||||
.. _dynamic_update_policies:
|
||||
|
||||
Dynamic Update Policies
|
||||
|
@ -2,4 +2,5 @@ zone <string> [ <class> ] {
|
||||
type forward;
|
||||
forward ( first | only );
|
||||
forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
|
||||
template <string>;
|
||||
};
|
||||
|
@ -2,4 +2,5 @@ zone <string> [ <class> ] {
|
||||
type hint;
|
||||
check-names ( fail | warn | ignore );
|
||||
file <quoted_string>;
|
||||
template <string>;
|
||||
};
|
||||
|
@ -38,6 +38,7 @@ zone <string> [ <class> ] {
|
||||
request-expire <boolean>;
|
||||
request-ixfr <boolean>;
|
||||
request-ixfr-max-diffs <integer>;
|
||||
template <string>;
|
||||
transfer-source ( <ipv4_address> | * );
|
||||
transfer-source-v6 ( <ipv6_address> | * );
|
||||
try-tcp-refresh <boolean>;
|
||||
|
@ -362,6 +362,93 @@ statistics-channels {
|
||||
inet ( <ipv4_address> | <ipv6_address> | * ) [ port ( <integer> | * ) ] [ allow { <address_match_element>; ... } ]; // may occur multiple times
|
||||
}; // optional (only available if configured), may occur multiple times
|
||||
|
||||
template <string> {
|
||||
allow-notify { <address_match_element>; ... };
|
||||
allow-query { <address_match_element>; ... };
|
||||
allow-query-on { <address_match_element>; ... };
|
||||
allow-transfer [ port <integer> ] [ transport <string> ] { <address_match_element>; ... };
|
||||
allow-update { <address_match_element>; ... };
|
||||
allow-update-forwarding { <address_match_element>; ... };
|
||||
also-notify [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
|
||||
check-dup-records ( fail | warn | ignore );
|
||||
check-integrity <boolean>;
|
||||
check-mx ( fail | warn | ignore );
|
||||
check-mx-cname ( fail | warn | ignore );
|
||||
check-names ( fail | warn | ignore );
|
||||
check-sibling <boolean>;
|
||||
check-spf ( warn | ignore );
|
||||
check-srv-cname ( fail | warn | ignore );
|
||||
check-svcb <boolean>;
|
||||
check-wildcard <boolean>;
|
||||
checkds ( explicit | <boolean> );
|
||||
database <string>;
|
||||
dlz <string>;
|
||||
dnskey-sig-validity <integer>; // obsolete
|
||||
dnssec-dnskey-kskonly <boolean>; // obsolete
|
||||
dnssec-loadkeys-interval <integer>;
|
||||
dnssec-policy <string>;
|
||||
dnssec-secure-to-insecure <boolean>; // obsolete
|
||||
dnssec-update-mode ( maintain | no-resign ); // obsolete
|
||||
file <quoted_string>;
|
||||
forward ( first | only );
|
||||
forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
|
||||
initial-file <quoted_string>;
|
||||
inline-signing <boolean>;
|
||||
ixfr-from-differences <boolean>;
|
||||
journal <quoted_string>;
|
||||
key-directory <quoted_string>;
|
||||
log-report-channel <boolean>;
|
||||
masterfile-format ( raw | text );
|
||||
masterfile-style ( full | relative );
|
||||
max-ixfr-ratio ( unlimited | <percentage> );
|
||||
max-journal-size ( default | unlimited | <sizeval> );
|
||||
max-records <integer>;
|
||||
max-records-per-type <integer>;
|
||||
max-refresh-time <integer>;
|
||||
max-retry-time <integer>;
|
||||
max-transfer-idle-in <integer>;
|
||||
max-transfer-idle-out <integer>;
|
||||
max-transfer-time-in <integer>;
|
||||
max-transfer-time-out <integer>;
|
||||
max-types-per-name <integer>;
|
||||
max-zone-ttl ( unlimited | <duration> ); // deprecated
|
||||
min-refresh-time <integer>;
|
||||
min-retry-time <integer>;
|
||||
min-transfer-rate-in <integer> <integer>;
|
||||
multi-master <boolean>;
|
||||
notify ( explicit | master-only | primary-only | <boolean> );
|
||||
notify-defer <integer>;
|
||||
notify-delay <integer>;
|
||||
notify-source ( <ipv4_address> | * );
|
||||
notify-source-v6 ( <ipv6_address> | * );
|
||||
notify-to-soa <boolean>;
|
||||
nsec3-test-zone <boolean>; // test only
|
||||
parental-agents [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
|
||||
parental-source ( <ipv4_address> | * );
|
||||
parental-source-v6 ( <ipv6_address> | * );
|
||||
primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
|
||||
provide-zoneversion <boolean>;
|
||||
request-expire <boolean>;
|
||||
request-ixfr <boolean>;
|
||||
request-ixfr-max-diffs <integer>;
|
||||
send-report-channel <string>;
|
||||
serial-update-method ( date | increment | unixtime );
|
||||
server-addresses { ( <ipv4_address> | <ipv6_address> ); ... };
|
||||
server-names { <string>; ... };
|
||||
sig-signing-nodes <integer>;
|
||||
sig-signing-signatures <integer>;
|
||||
sig-signing-type <integer>;
|
||||
sig-validity-interval <integer> [ <integer> ]; // obsolete
|
||||
transfer-source ( <ipv4_address> | * );
|
||||
transfer-source-v6 ( <ipv6_address> | * );
|
||||
try-tcp-refresh <boolean>;
|
||||
type ( primary | master | secondary | slave | mirror | forward | hint | redirect | static-stub | stub );
|
||||
update-check-ksk <boolean>; // obsolete
|
||||
update-policy ( local | { ( deny | grant ) <string> ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain | ms-subdomain-self-rhs | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesub ) [ <string> ] <rrtypelist>; ... } );
|
||||
zero-no-soa-ttl <boolean>;
|
||||
zone-statistics ( full | terse | none | <boolean> );
|
||||
}; // may occur multiple times
|
||||
|
||||
tls <string> {
|
||||
ca-file <quoted_string>;
|
||||
cert-file <quoted_string>;
|
||||
|
@ -27,6 +27,7 @@ zone <string> [ <class> ] {
|
||||
file <quoted_string>;
|
||||
forward ( first | only );
|
||||
forwarders [ port <integer> ] [ tls <string> ] { ( <ipv4_address> | <ipv6_address> ) [ port <integer> ] [ tls <string> ]; ... };
|
||||
initial-file <quoted_string>;
|
||||
inline-signing <boolean>;
|
||||
ixfr-from-differences <boolean>;
|
||||
journal <quoted_string>;
|
||||
@ -59,6 +60,7 @@ zone <string> [ <class> ] {
|
||||
sig-signing-signatures <integer>;
|
||||
sig-signing-type <integer>;
|
||||
sig-validity-interval <integer> [ <integer> ]; // obsolete
|
||||
template <string>;
|
||||
update-check-ksk <boolean>; // obsolete
|
||||
update-policy ( local | { ( deny | grant ) <string> ( 6to4-self | external | krb5-self | krb5-selfsub | krb5-subdomain | krb5-subdomain-self-rhs | ms-self | ms-selfsub | ms-subdomain | ms-subdomain-self-rhs | name | self | selfsub | selfwild | subdomain | tcp-self | wildcard | zonesub ) [ <string> ] <rrtypelist>; ... } );
|
||||
zero-no-soa-ttl <boolean>;
|
||||
|
@ -11,5 +11,6 @@ zone <string> [ <class> ] {
|
||||
max-types-per-name <integer>;
|
||||
max-zone-ttl ( unlimited | <duration> ); // deprecated
|
||||
primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
|
||||
template <string>;
|
||||
zone-statistics ( full | terse | none | <boolean> );
|
||||
};
|
||||
|
@ -60,6 +60,7 @@ zone <string> [ <class> ] {
|
||||
sig-signing-signatures <integer>;
|
||||
sig-signing-type <integer>;
|
||||
sig-validity-interval <integer> [ <integer> ]; // obsolete
|
||||
template <string>;
|
||||
transfer-source ( <ipv4_address> | * );
|
||||
transfer-source-v6 ( <ipv6_address> | * );
|
||||
try-tcp-refresh <boolean>;
|
||||
|
@ -9,5 +9,6 @@ zone <string> [ <class> ] {
|
||||
max-types-per-name <integer>;
|
||||
server-addresses { ( <ipv4_address> | <ipv6_address> ); ... };
|
||||
server-names { <string>; ... };
|
||||
template <string>;
|
||||
zone-statistics ( full | terse | none | <boolean> );
|
||||
};
|
||||
|
@ -21,6 +21,7 @@ zone <string> [ <class> ] {
|
||||
min-transfer-rate-in <integer> <integer>;
|
||||
multi-master <boolean>;
|
||||
primaries [ port <integer> ] [ source ( <ipv4_address> | * ) ] [ source-v6 ( <ipv6_address> | * ) ] { ( <server-list> | <ipv4_address> [ port <integer> ] | <ipv6_address> [ port <integer> ] ) [ key <string> ] [ tls <string> ]; ... };
|
||||
template <string>;
|
||||
transfer-source ( <ipv4_address> | * );
|
||||
transfer-source-v6 ( <ipv6_address> | * );
|
||||
zone-statistics ( full | terse | none | <boolean> );
|
||||
|
@ -212,7 +212,7 @@ LLVMFuzzerInitialize(int *argc ISC_ATTR_UNUSED, char ***argv ISC_ATTR_UNUSED) {
|
||||
dns_zone_setclass(zone, view->rdclass);
|
||||
dns_zone_settype(zone, dns_zone_primary);
|
||||
dns_zone_setkeydirectory(zone, wd);
|
||||
dns_zone_setfile(zone, pathbuf, dns_masterformat_text,
|
||||
dns_zone_setfile(zone, pathbuf, NULL, dns_masterformat_text,
|
||||
&dns_master_style_default);
|
||||
|
||||
result = dns_zone_load(zone, false);
|
||||
|
@ -290,16 +290,18 @@ dns_zone_getorigin(dns_zone_t *zone);
|
||||
*/
|
||||
|
||||
void
|
||||
dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
|
||||
const dns_master_style_t *style);
|
||||
dns_zone_setfile(dns_zone_t *zone, const char *file, const char *initial_file,
|
||||
dns_masterformat_t format, const dns_master_style_t *style);
|
||||
/*%<
|
||||
* Sets the name of the master file in the format of 'format' from which
|
||||
* the zone loads its database to 'file'.
|
||||
*
|
||||
* For zones that have no associated master file, 'file' will be NULL.
|
||||
* For some zone types, e.g. secondary zones, 'file' is optional, but
|
||||
* for primary zones it is mandatory. If the master file does not exist
|
||||
* during loading, then it will be copied into place from 'initial_file'.
|
||||
*
|
||||
* For zones with persistent databases, the file name
|
||||
* setting is ignored.
|
||||
* For zones with persistent databases, the file name setting is ignored.
|
||||
*
|
||||
* Require:
|
||||
*\li 'zone' to be a valid zone.
|
||||
|
166
lib/dns/zone.c
166
lib/dns/zone.c
@ -284,6 +284,7 @@ struct dns_zone {
|
||||
dns_name_t origin;
|
||||
dns_name_t rad;
|
||||
char *masterfile;
|
||||
char *initfile;
|
||||
const FILE *stream; /* loading from a stream? */
|
||||
ISC_LIST(dns_include_t) includes; /* Include files */
|
||||
ISC_LIST(dns_include_t) newincludes; /* Loading */
|
||||
@ -1289,9 +1290,13 @@ zone_free(dns_zone_t *zone) {
|
||||
if (zone->masterfile != NULL) {
|
||||
isc_mem_free(zone->mctx, zone->masterfile);
|
||||
}
|
||||
if (zone->initfile != NULL) {
|
||||
isc_mem_free(zone->mctx, zone->initfile);
|
||||
}
|
||||
if (zone->keydirectory != NULL) {
|
||||
isc_mem_free(zone->mctx, zone->keydirectory);
|
||||
}
|
||||
|
||||
if (zone->kasp != NULL) {
|
||||
dns_kasp_detach(&zone->kasp);
|
||||
}
|
||||
@ -1792,14 +1797,117 @@ setstring(dns_zone_t *zone, char **field, const char *value) {
|
||||
*field = copy;
|
||||
}
|
||||
|
||||
static int
|
||||
position_order(const void *a, const void *b) {
|
||||
/* sort char pointers in order of which occurs first in memory */
|
||||
return (char *)*(char **)a - (char *)*(char **)b;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
putmem(isc_buffer_t *b, const char *base, size_t length) {
|
||||
size_t space = isc_buffer_availablelength(b) - 1;
|
||||
if (space < length) {
|
||||
isc_buffer_putmem(b, (const unsigned char *)base, space);
|
||||
return ISC_R_NOSPACE;
|
||||
}
|
||||
|
||||
isc_buffer_putmem(b, (const unsigned char *)base, length);
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the masterfile field, expanding $name to the zone name,
|
||||
* $type to the zone type, and $view to the view name. Cap the
|
||||
* length at PATH_MAX.
|
||||
*/
|
||||
static void
|
||||
setfilename(dns_zone_t *zone, char **field, const char *value) {
|
||||
isc_result_t result;
|
||||
char *t = NULL, *n = NULL, *v = NULL;
|
||||
char *positions[3];
|
||||
char filename[PATH_MAX];
|
||||
isc_buffer_t b;
|
||||
size_t tags = 0;
|
||||
|
||||
if (value == NULL) {
|
||||
*field = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
t = strcasestr(value, "$type");
|
||||
if (t != NULL) {
|
||||
positions[tags++] = t;
|
||||
}
|
||||
|
||||
n = strcasestr(value, "$name");
|
||||
if (n != NULL) {
|
||||
positions[tags++] = n;
|
||||
}
|
||||
|
||||
v = strcasestr(value, "$view");
|
||||
if (v != NULL) {
|
||||
positions[tags++] = v;
|
||||
}
|
||||
|
||||
if (tags == 0) {
|
||||
setstring(zone, field, value);
|
||||
return;
|
||||
}
|
||||
|
||||
isc_buffer_init(&b, filename, sizeof(filename));
|
||||
|
||||
/* sort the tag offsets in order of occurrence */
|
||||
qsort(positions, tags, sizeof(char *), position_order);
|
||||
|
||||
const char *p = value;
|
||||
for (size_t i = 0; i < tags; i++) {
|
||||
size_t tokenlen = 0;
|
||||
|
||||
CHECK(putmem(&b, p, (positions[i] - p)));
|
||||
|
||||
p = positions[i];
|
||||
INSIST(p != NULL);
|
||||
if (p == n) {
|
||||
dns_fixedname_t fn;
|
||||
dns_name_t *name = dns_fixedname_initname(&fn);
|
||||
char namebuf[DNS_NAME_FORMATSIZE];
|
||||
|
||||
result = dns_name_downcase(&zone->origin, name);
|
||||
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
||||
dns_name_format(name, namebuf, sizeof(namebuf));
|
||||
CHECK(putmem(&b, namebuf, strlen(namebuf)));
|
||||
tokenlen = 5; /* "$name" */
|
||||
} else if (p == t) {
|
||||
const char *typename = dns_zonetype_name(zone->type);
|
||||
CHECK(putmem(&b, typename, strlen(typename)));
|
||||
tokenlen = 5; /* "$type" */
|
||||
} else if (p == v) {
|
||||
CHECK(putmem(&b, zone->view->name,
|
||||
strlen(zone->view->name)));
|
||||
tokenlen = 5; /* "$view" */
|
||||
}
|
||||
|
||||
/* Advance the input pointer past the token */
|
||||
p += tokenlen;
|
||||
}
|
||||
|
||||
const char *end = value + strlen(value);
|
||||
putmem(&b, p, end - p);
|
||||
|
||||
failure:
|
||||
isc_buffer_putuint8(&b, 0);
|
||||
setstring(zone, field, filename);
|
||||
}
|
||||
|
||||
void
|
||||
dns_zone_setfile(dns_zone_t *zone, const char *file, dns_masterformat_t format,
|
||||
const dns_master_style_t *style) {
|
||||
dns_zone_setfile(dns_zone_t *zone, const char *file, const char *initial_file,
|
||||
dns_masterformat_t format, const dns_master_style_t *style) {
|
||||
REQUIRE(DNS_ZONE_VALID(zone));
|
||||
REQUIRE(zone->stream == NULL);
|
||||
|
||||
LOCK_ZONE(zone);
|
||||
setstring(zone, &zone->masterfile, file);
|
||||
setfilename(zone, &zone->masterfile, file);
|
||||
setstring(zone, &zone->initfile, initial_file);
|
||||
zone->masterformat = format;
|
||||
if (format == dns_masterformat_text) {
|
||||
zone->masterstyle = style;
|
||||
@ -2105,6 +2213,42 @@ zone_touched(dns_zone_t *zone) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
copy_initfile(dns_zone_t *zone) {
|
||||
isc_result_t result;
|
||||
FILE *input = NULL, *output = NULL;
|
||||
size_t len;
|
||||
|
||||
CHECK(isc_stdio_open(zone->initfile, "r", &input));
|
||||
CHECK(isc_stdio_open(zone->masterfile, "w", &output));
|
||||
|
||||
CHECK(isc_file_getsizefd(fileno(input), (off_t *)&len));
|
||||
|
||||
do {
|
||||
char buf[BUFSIZ];
|
||||
size_t rval;
|
||||
|
||||
result = isc_stdio_read(buf, 1, sizeof(buf), input, &rval);
|
||||
if (result != ISC_R_SUCCESS && result != ISC_R_EOF) {
|
||||
goto failure;
|
||||
}
|
||||
CHECK(isc_stdio_write(buf, rval, 1, output, NULL));
|
||||
len -= rval;
|
||||
} while (len > 0);
|
||||
|
||||
failure:
|
||||
if (input != NULL) {
|
||||
isc_stdio_close(input);
|
||||
}
|
||||
if (output != NULL) {
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
isc_file_remove(zone->masterfile);
|
||||
}
|
||||
isc_stdio_close(output);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note: when dealing with inline-signed zones, external callers will always
|
||||
* call zone_load() for the secure zone; zone_load() calls itself recursively
|
||||
@ -2347,6 +2491,22 @@ zone_load(dns_zone_t *zone, unsigned int flags, bool locked) {
|
||||
}
|
||||
}
|
||||
|
||||
if (zone->type == dns_zone_primary && zone->masterfile != NULL &&
|
||||
!isc_file_exists(zone->masterfile) && zone->initfile != NULL)
|
||||
{
|
||||
dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_INFO,
|
||||
"zone file %s not found; copying initial "
|
||||
"file %s",
|
||||
zone->masterfile, zone->initfile);
|
||||
result = copy_initfile(zone);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD,
|
||||
ISC_LOG_ERROR, "copy from %s failed: %s",
|
||||
zone->initfile,
|
||||
isc_result_totext(result));
|
||||
}
|
||||
}
|
||||
|
||||
dns_zone_logc(zone, DNS_LOGCATEGORY_ZONELOAD, ISC_LOG_DEBUG(1),
|
||||
"starting load");
|
||||
|
||||
|
@ -2923,14 +2923,15 @@ check:
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to find a zone option in one of up to three levels of options:
|
||||
* for example, the zone, view, and global option blocks.
|
||||
* Try to find a zone option in one of up to four levels of options:
|
||||
* for example, the zone, template, view, and global option blocks.
|
||||
* (Fewer levels can be specified for options that aren't defined at
|
||||
* all three levels.)
|
||||
* all four 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) {
|
||||
const cfg_obj_t *opts3, const cfg_obj_t *opts4, const char *name,
|
||||
const cfg_obj_t **objp) {
|
||||
isc_result_t result = ISC_R_NOTFOUND;
|
||||
|
||||
REQUIRE(*objp == NULL);
|
||||
@ -2944,6 +2945,9 @@ get_zoneopt(const cfg_obj_t *opts1, const cfg_obj_t *opts2,
|
||||
if (*objp == NULL && opts3 != NULL) {
|
||||
result = cfg_map_get(opts3, name, objp);
|
||||
}
|
||||
if (*objp == NULL && opts4 != NULL) {
|
||||
result = cfg_map_get(opts4, name, objp);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -2958,13 +2962,14 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
const char *znamestr = NULL;
|
||||
const char *typestr = NULL;
|
||||
const char *target = NULL;
|
||||
const char *tmplname = NULL;
|
||||
int ztype;
|
||||
const cfg_obj_t *zoptions, *goptions = NULL;
|
||||
const cfg_obj_t *zoptions = NULL, *toptions = NULL, *goptions = NULL;
|
||||
const cfg_obj_t *obj = NULL, *kasp = NULL;
|
||||
const cfg_obj_t *inviewobj = NULL;
|
||||
const cfg_obj_t *templates = NULL, *inviewobj = NULL;
|
||||
isc_result_t result = ISC_R_SUCCESS;
|
||||
isc_result_t tresult;
|
||||
unsigned int i;
|
||||
unsigned int i = 0;
|
||||
dns_rdataclass_t zclass;
|
||||
dns_fixedname_t fixedname;
|
||||
dns_name_t *zname = NULL; /* NULL if parsing of zone name fails. */
|
||||
@ -2976,6 +2981,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
bool ddns = false;
|
||||
bool has_dnssecpolicy = false;
|
||||
bool kasp_inlinesigning = false;
|
||||
bool inline_signing = false;
|
||||
const void *clauses = NULL;
|
||||
const char *option = NULL;
|
||||
const char *kaspname = NULL;
|
||||
@ -2995,14 +3001,37 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
cfg_map_get(config, "options", &goptions);
|
||||
}
|
||||
|
||||
inviewobj = NULL;
|
||||
/* If the zone specifies a template, find it too */
|
||||
(void)cfg_map_get(config, "template", &templates);
|
||||
(void)cfg_map_get(zoptions, "template", &obj);
|
||||
if (obj != NULL) {
|
||||
tmplname = cfg_obj_asstring(obj);
|
||||
|
||||
CFG_LIST_FOREACH (templates, e) {
|
||||
const cfg_obj_t *t = cfg_tuple_get(cfg_listelt_value(e),
|
||||
"name");
|
||||
if (strcasecmp(cfg_obj_asstring(t), tmplname) == 0) {
|
||||
toptions = cfg_tuple_get(cfg_listelt_value(e),
|
||||
"options");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (toptions == NULL) {
|
||||
cfg_obj_log(zconfig, ISC_LOG_ERROR,
|
||||
"zone '%s': template '%s' not found",
|
||||
znamestr, tmplname);
|
||||
return ISC_R_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
(void)cfg_map_get(zoptions, "in-view", &inviewobj);
|
||||
if (inviewobj != NULL) {
|
||||
target = cfg_obj_asstring(inviewobj);
|
||||
ztype = CFG_ZONE_INVIEW;
|
||||
} else {
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "type", &obj);
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL, "type", &obj);
|
||||
if (obj == NULL) {
|
||||
cfg_obj_log(zconfig, ISC_LOG_ERROR,
|
||||
"zone '%s': type not present", znamestr);
|
||||
@ -3195,7 +3224,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
* Check if a dnssec-policy is set.
|
||||
*/
|
||||
obj = NULL;
|
||||
(void)get_zoneopt(zoptions, voptions, goptions, "dnssec-policy", &obj);
|
||||
(void)get_zoneopt(zoptions, toptions, voptions, goptions,
|
||||
"dnssec-policy", &obj);
|
||||
if (obj != NULL) {
|
||||
kaspname = cfg_obj_asstring(obj);
|
||||
if (strcmp(kaspname, "default") == 0) {
|
||||
@ -3258,8 +3288,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
* */
|
||||
if (has_dnssecpolicy) {
|
||||
obj = NULL;
|
||||
(void)get_zoneopt(zoptions, voptions, goptions, "max-zone-ttl",
|
||||
&obj);
|
||||
(void)get_zoneopt(zoptions, toptions, voptions, goptions,
|
||||
"max-zone-ttl", &obj);
|
||||
if (obj != NULL) {
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
"zone '%s': option 'max-zone-ttl' "
|
||||
@ -3278,13 +3308,19 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
option = cfg_map_firstclause(&cfg_type_zoneopts, &clauses, &i);
|
||||
while (option != NULL) {
|
||||
obj = NULL;
|
||||
if (cfg_map_get(zoptions, option, &obj) == ISC_R_SUCCESS &&
|
||||
obj != NULL && !cfg_clause_validforzone(option, ztype))
|
||||
{
|
||||
bool topt = false;
|
||||
(void)cfg_map_get(zoptions, option, &obj);
|
||||
if (obj == NULL && toptions != NULL) {
|
||||
(void)cfg_map_get(toptions, option, &obj);
|
||||
topt = true;
|
||||
}
|
||||
if (obj != NULL && !cfg_clause_validforzone(option, ztype)) {
|
||||
cfg_obj_log(obj, ISC_LOG_WARNING,
|
||||
"option '%s' is not allowed "
|
||||
"in '%s' zone '%s'",
|
||||
option, typestr, znamestr);
|
||||
"in '%s' zone '%s'%s%s%s",
|
||||
option, typestr, znamestr,
|
||||
topt ? " (referencing template '" : "",
|
||||
topt ? tmplname : "", topt ? "')" : "");
|
||||
result = ISC_R_FAILURE;
|
||||
}
|
||||
option = cfg_map_nextclause(&cfg_type_zoneopts, &clauses, &i);
|
||||
@ -3321,9 +3357,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
bool donotify = true;
|
||||
|
||||
obj = NULL;
|
||||
tresult = get_zoneopt(zoptions, voptions, goptions, "notify",
|
||||
&obj);
|
||||
if (tresult == ISC_R_SUCCESS) {
|
||||
(void)get_zoneopt(zoptions, toptions, voptions, goptions,
|
||||
"notify", &obj);
|
||||
if (obj != NULL) {
|
||||
if (cfg_obj_isboolean(obj)) {
|
||||
donotify = cfg_obj_asboolean(obj);
|
||||
} else {
|
||||
@ -3338,18 +3374,19 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
tresult = cfg_map_get(zoptions, "also-notify", &obj);
|
||||
if (tresult == ISC_R_SUCCESS && !donotify) {
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL, "also-notify",
|
||||
&obj);
|
||||
if (obj != NULL && !donotify) {
|
||||
cfg_obj_log(zoptions, ISC_LOG_WARNING,
|
||||
"zone '%s': 'also-notify' set but "
|
||||
"'notify' is disabled",
|
||||
znamestr);
|
||||
}
|
||||
if (tresult != ISC_R_SUCCESS) {
|
||||
tresult = get_zoneopt(voptions, goptions, NULL,
|
||||
"also-notify", &obj);
|
||||
if (obj == NULL) {
|
||||
(void)get_zoneopt(voptions, goptions, NULL, NULL,
|
||||
"also-notify", &obj);
|
||||
}
|
||||
if (tresult == ISC_R_SUCCESS && donotify) {
|
||||
if (obj != NULL && donotify) {
|
||||
uint32_t count;
|
||||
tresult = validate_remotes(obj, config, &count, mctx);
|
||||
if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
|
||||
@ -3370,15 +3407,18 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
!dns_name_equal(zname, dns_rootname)))
|
||||
{
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "primaries", &obj);
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL, "primaries",
|
||||
&obj);
|
||||
if (obj == NULL) {
|
||||
/* If "primaries" was unset, check for "masters" */
|
||||
(void)cfg_map_get(zoptions, "masters", &obj);
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL,
|
||||
"masters", &obj);
|
||||
} else {
|
||||
const cfg_obj_t *obj2 = NULL;
|
||||
|
||||
/* ...bug if it was set, "masters" must not be. */
|
||||
(void)cfg_map_get(zoptions, "masters", &obj2);
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL,
|
||||
"masters", &obj2);
|
||||
if (obj2 != NULL) {
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
"'primaries' and 'masters' cannot "
|
||||
@ -3414,7 +3454,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
*/
|
||||
if (ztype == CFG_ZONE_PRIMARY || ztype == CFG_ZONE_SECONDARY) {
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "parental-agents", &obj);
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL,
|
||||
"parental-agents", &obj);
|
||||
if (obj != NULL) {
|
||||
uint32_t count;
|
||||
tresult = validate_remotes(obj, config, &count, mctx);
|
||||
@ -3451,22 +3492,22 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
*/
|
||||
if (ztype == CFG_ZONE_PRIMARY || ztype == CFG_ZONE_SECONDARY) {
|
||||
bool signing = false;
|
||||
isc_result_t res1, res2, res3;
|
||||
const cfg_obj_t *au = NULL;
|
||||
const cfg_obj_t *au = NULL, *up = NULL;
|
||||
|
||||
obj = NULL;
|
||||
res1 = cfg_map_get(zoptions, "allow-update", &au);
|
||||
obj = NULL;
|
||||
res2 = cfg_map_get(zoptions, "update-policy", &obj);
|
||||
if (res1 == ISC_R_SUCCESS && res2 == ISC_R_SUCCESS) {
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL,
|
||||
"allow-update", &au);
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL,
|
||||
"update-policy", &up);
|
||||
|
||||
if (au != NULL && up != NULL) {
|
||||
cfg_obj_log(au, ISC_LOG_ERROR,
|
||||
"zone '%s': 'allow-update' is ignored "
|
||||
"when 'update-policy' is present",
|
||||
znamestr);
|
||||
result = ISC_R_FAILURE;
|
||||
} else if (res2 == ISC_R_SUCCESS) {
|
||||
res3 = check_update_policy(obj);
|
||||
if (res3 != ISC_R_SUCCESS) {
|
||||
} else if (up != NULL) {
|
||||
tresult = check_update_policy(up);
|
||||
if (tresult != ISC_R_SUCCESS) {
|
||||
result = ISC_R_FAILURE;
|
||||
}
|
||||
}
|
||||
@ -3476,18 +3517,18 @@ 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) {
|
||||
res1 = get_zoneopt(voptions, goptions, NULL,
|
||||
"allow-update", &au);
|
||||
if (au == NULL) {
|
||||
(void)get_zoneopt(voptions, goptions, NULL, NULL,
|
||||
"allow-update", &au);
|
||||
}
|
||||
|
||||
if (res2 == ISC_R_SUCCESS) {
|
||||
if (up != NULL) {
|
||||
ddns = true;
|
||||
} else if (res1 == ISC_R_SUCCESS) {
|
||||
} else if (au != NULL) {
|
||||
dns_acl_t *acl = NULL;
|
||||
res1 = cfg_acl_fromconfig(au, config, actx, mctx, 0,
|
||||
&acl);
|
||||
if (res1 != ISC_R_SUCCESS) {
|
||||
tresult = cfg_acl_fromconfig(au, config, actx, mctx, 0,
|
||||
&acl);
|
||||
if (tresult != ISC_R_SUCCESS) {
|
||||
cfg_obj_log(au, ISC_LOG_ERROR,
|
||||
"acl expansion failed: %s",
|
||||
isc_result_totext(result));
|
||||
@ -3501,9 +3542,10 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
res1 = cfg_map_get(zoptions, "inline-signing", &obj);
|
||||
if (res1 == ISC_R_SUCCESS) {
|
||||
signing = cfg_obj_asboolean(obj);
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL,
|
||||
"inline-signing", &obj);
|
||||
if (obj != NULL) {
|
||||
inline_signing = signing = cfg_obj_asboolean(obj);
|
||||
} else if (has_dnssecpolicy) {
|
||||
signing = kasp_inlinesigning;
|
||||
}
|
||||
@ -3527,8 +3569,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
res1 = cfg_map_get(zoptions, "sig-signing-type", &obj);
|
||||
if (res1 == ISC_R_SUCCESS) {
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL,
|
||||
"sig-signing-type", &obj);
|
||||
if (obj != NULL) {
|
||||
uint32_t type = cfg_obj_asuint32(obj);
|
||||
if (type < 0xff00U || type > 0xffffU) {
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
@ -3540,10 +3583,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
res1 = cfg_map_get(zoptions, "dnssec-loadkeys-interval", &obj);
|
||||
if (res1 == ISC_R_SUCCESS && ztype == CFG_ZONE_SECONDARY &&
|
||||
!signing)
|
||||
{
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL,
|
||||
"dnssec-loadkeys-interval", &obj);
|
||||
if (obj != NULL && ztype == CFG_ZONE_SECONDARY && !signing) {
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
"dnssec-loadkeys-interval: requires "
|
||||
"inline-signing when used in secondary "
|
||||
@ -3557,7 +3599,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
*/
|
||||
obj = NULL;
|
||||
if (root) {
|
||||
(void)get_zoneopt(voptions, goptions, NULL, "forwarders", &obj);
|
||||
(void)get_zoneopt(voptions, goptions, NULL, NULL, "forwarders",
|
||||
&obj);
|
||||
}
|
||||
if (check_forward(config, zoptions, obj) != ISC_R_SUCCESS) {
|
||||
result = ISC_R_FAILURE;
|
||||
@ -3569,13 +3612,15 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
*/
|
||||
if (ztype == CFG_ZONE_FORWARD && (rfc1918 || ula)) {
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "forward", &obj);
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL, "forward",
|
||||
&obj);
|
||||
if (obj == NULL) {
|
||||
/*
|
||||
* Forward mode not explicitly configured.
|
||||
* Forward mode not explicitly configured
|
||||
* at the zone or template level.
|
||||
*/
|
||||
(void)get_zoneopt(voptions, goptions, NULL, "forward",
|
||||
&obj);
|
||||
(void)get_zoneopt(voptions, goptions, NULL, NULL,
|
||||
"forward", &obj);
|
||||
if (obj == NULL ||
|
||||
strcasecmp(cfg_obj_asstring(obj), "first") == 0)
|
||||
{
|
||||
@ -3593,7 +3638,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
* Check validity of static stub server addresses.
|
||||
*/
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "server-addresses", &obj);
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL, "server-addresses",
|
||||
&obj);
|
||||
if (ztype == CFG_ZONE_STATICSTUB && obj != NULL) {
|
||||
CFG_LIST_FOREACH (obj, element) {
|
||||
isc_sockaddr_t sa;
|
||||
@ -3616,7 +3662,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
* Check validity of static stub server names.
|
||||
*/
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "server-names", &obj);
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL, "server-names", &obj);
|
||||
if (zname != NULL && ztype == CFG_ZONE_STATICSTUB && obj != NULL) {
|
||||
CFG_LIST_FOREACH (obj, element) {
|
||||
const char *snamestr = NULL;
|
||||
@ -3649,7 +3695,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
(void)cfg_map_get(zoptions, "send-report-channel", &obj);
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL, "send-report-channel",
|
||||
&obj);
|
||||
if (obj != NULL) {
|
||||
const char *str = cfg_obj_asstring(obj);
|
||||
dns_fixedname_t fad;
|
||||
@ -3677,7 +3724,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
* Warn if key-directory doesn't exist
|
||||
*/
|
||||
obj = NULL;
|
||||
(void)get_zoneopt(zoptions, voptions, goptions, "key-directory", &obj);
|
||||
(void)get_zoneopt(zoptions, toptions, voptions, goptions,
|
||||
"key-directory", &obj);
|
||||
if (obj != NULL) {
|
||||
dir = cfg_obj_asstring(obj);
|
||||
|
||||
@ -3726,8 +3774,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
*/
|
||||
if (ztype == CFG_ZONE_PRIMARY || ztype == CFG_ZONE_SECONDARY) {
|
||||
obj = NULL;
|
||||
tresult = cfg_map_get(zoptions, "log-report-channel", &obj);
|
||||
if (tresult == ISC_R_SUCCESS && cfg_obj_asboolean(obj) &&
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL,
|
||||
"log-report-channel", &obj);
|
||||
if (obj != NULL && cfg_obj_asboolean(obj) &&
|
||||
dns_name_equal(zname, dns_rootname))
|
||||
{
|
||||
cfg_obj_log(zconfig, ISC_LOG_ERROR,
|
||||
@ -3754,14 +3803,14 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
*/
|
||||
obj = NULL;
|
||||
dlz = false;
|
||||
tresult = cfg_map_get(zoptions, "dlz", &obj);
|
||||
if (tresult == ISC_R_SUCCESS) {
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL, "dlz", &obj);
|
||||
if (obj != NULL) {
|
||||
dlz = true;
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
tresult = cfg_map_get(zoptions, "database", &obj);
|
||||
if (dlz && tresult == ISC_R_SUCCESS) {
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL, "database", &obj);
|
||||
if (dlz && obj != NULL) {
|
||||
cfg_obj_log(zconfig, ISC_LOG_ERROR,
|
||||
"zone '%s': cannot specify both 'dlz' "
|
||||
"and 'database'",
|
||||
@ -3769,28 +3818,23 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = ISC_R_FAILURE;
|
||||
}
|
||||
} else if (!dlz &&
|
||||
(tresult == ISC_R_NOTFOUND ||
|
||||
(tresult == ISC_R_SUCCESS &&
|
||||
strcmp(ZONEDB_DEFAULT, cfg_obj_asstring(obj)) == 0)))
|
||||
} else if (!dlz && (obj == NULL ||
|
||||
strcmp(ZONEDB_DEFAULT, cfg_obj_asstring(obj)) == 0))
|
||||
{
|
||||
isc_result_t res1;
|
||||
const cfg_obj_t *fileobj = NULL;
|
||||
tresult = cfg_map_get(zoptions, "file", &fileobj);
|
||||
obj = NULL;
|
||||
res1 = cfg_map_get(zoptions, "inline-signing", &obj);
|
||||
if (tresult != ISC_R_SUCCESS &&
|
||||
(void)get_zoneopt(zoptions, toptions, NULL, NULL, "file",
|
||||
&fileobj);
|
||||
if (fileobj == NULL &&
|
||||
(ztype == CFG_ZONE_PRIMARY || ztype == CFG_ZONE_HINT ||
|
||||
(ztype == CFG_ZONE_SECONDARY && res1 == ISC_R_SUCCESS &&
|
||||
cfg_obj_asboolean(obj))))
|
||||
(ztype == CFG_ZONE_SECONDARY && inline_signing)))
|
||||
{
|
||||
cfg_obj_log(zconfig, ISC_LOG_ERROR,
|
||||
"zone '%s': missing 'file' entry",
|
||||
znamestr);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
result = tresult;
|
||||
result = ISC_R_FAILURE;
|
||||
}
|
||||
} else if (tresult == ISC_R_SUCCESS && files != NULL &&
|
||||
} else if (fileobj != NULL && files != NULL &&
|
||||
(ztype == CFG_ZONE_SECONDARY ||
|
||||
ztype == CFG_ZONE_MIRROR || ddns ||
|
||||
has_dnssecpolicy))
|
||||
@ -3800,7 +3844,7 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
{
|
||||
result = tresult;
|
||||
}
|
||||
} else if (tresult == ISC_R_SUCCESS && files != NULL &&
|
||||
} else if (fileobj != NULL && files != NULL &&
|
||||
(ztype == CFG_ZONE_PRIMARY ||
|
||||
ztype == CFG_ZONE_HINT))
|
||||
{
|
||||
@ -3817,13 +3861,13 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
* consistent.
|
||||
*/
|
||||
obj = NULL;
|
||||
tresult = get_zoneopt(zoptions, voptions, goptions, "masterfile-format",
|
||||
&obj);
|
||||
tresult = get_zoneopt(zoptions, toptions, 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,
|
||||
tresult = get_zoneopt(zoptions, toptions, voptions, goptions,
|
||||
"masterfile-style", &obj);
|
||||
if (tresult == ISC_R_SUCCESS) {
|
||||
cfg_obj_log(obj, ISC_LOG_ERROR,
|
||||
@ -3838,8 +3882,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
(void)get_zoneopt(zoptions, voptions, goptions, "max-journal-size",
|
||||
&obj);
|
||||
(void)get_zoneopt(zoptions, toptions, 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) {
|
||||
@ -3854,8 +3898,8 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions,
|
||||
}
|
||||
|
||||
obj = NULL;
|
||||
(void)get_zoneopt(zoptions, voptions, goptions, "min-transfer-rate-in",
|
||||
&obj);
|
||||
(void)get_zoneopt(zoptions, toptions, voptions, goptions,
|
||||
"min-transfer-rate-in", &obj);
|
||||
if (obj != NULL) {
|
||||
uint32_t traffic_bytes =
|
||||
cfg_obj_asuint32(cfg_tuple_get(obj, "traffic_bytes"));
|
||||
|
@ -143,6 +143,8 @@ static cfg_type_t cfg_type_sizeval;
|
||||
static cfg_type_t cfg_type_sockaddr4wild;
|
||||
static cfg_type_t cfg_type_sockaddr6wild;
|
||||
static cfg_type_t cfg_type_statschannels;
|
||||
static cfg_type_t cfg_type_template;
|
||||
static cfg_type_t cfg_type_templateopts;
|
||||
static cfg_type_t cfg_type_tlsconf;
|
||||
static cfg_type_t cfg_type_view;
|
||||
static cfg_type_t cfg_type_viewopts;
|
||||
@ -471,6 +473,18 @@ static cfg_type_t cfg_type_zone = { "zone", cfg_parse_tuple,
|
||||
cfg_print_tuple, cfg_doc_tuple,
|
||||
&cfg_rep_tuple, zone_fields };
|
||||
|
||||
/*%
|
||||
* A zone statement.
|
||||
*/
|
||||
static cfg_tuplefielddef_t template_fields[] = {
|
||||
{ "name", &cfg_type_astring, 0 },
|
||||
{ "options", &cfg_type_templateopts, 0 },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
static cfg_type_t cfg_type_template = { "template", cfg_parse_tuple,
|
||||
cfg_print_tuple, cfg_doc_tuple,
|
||||
&cfg_rep_tuple, template_fields };
|
||||
|
||||
/*%
|
||||
* A dnssec-policy statement.
|
||||
*/
|
||||
@ -1155,6 +1169,7 @@ static cfg_clausedef_t namedconf_clauses[] = {
|
||||
{ "statistics-channels", &cfg_type_statschannels,
|
||||
CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_NOTCONFIGURED },
|
||||
#endif
|
||||
{ "template", &cfg_type_template, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "tls", &cfg_type_tlsconf, CFG_CLAUSEFLAG_MULTI },
|
||||
{ "view", &cfg_type_view, CFG_CLAUSEFLAG_MULTI },
|
||||
{ NULL, NULL, 0 }
|
||||
@ -2429,7 +2444,7 @@ static cfg_clausedef_t zone_only_clauses[] = {
|
||||
{ "file", &cfg_type_qstring,
|
||||
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
|
||||
CFG_ZONE_STUB | CFG_ZONE_HINT | CFG_ZONE_REDIRECT },
|
||||
{ "in-view", &cfg_type_astring, CFG_ZONE_INVIEW },
|
||||
{ "initial-file", &cfg_type_qstring, CFG_ZONE_PRIMARY },
|
||||
{ "inline-signing", &cfg_type_boolean,
|
||||
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY },
|
||||
{ "ixfr-base", NULL, CFG_CLAUSEFLAG_ANCIENT },
|
||||
@ -2456,6 +2471,15 @@ static cfg_clausedef_t zone_only_clauses[] = {
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
static cfg_clausedef_t non_template_clauses[] = {
|
||||
{ "in-view", &cfg_type_astring, CFG_ZONE_INVIEW },
|
||||
{ "template", &cfg_type_astring,
|
||||
CFG_ZONE_PRIMARY | CFG_ZONE_SECONDARY | CFG_ZONE_MIRROR |
|
||||
CFG_ZONE_STUB | CFG_ZONE_STATICSTUB | CFG_ZONE_DELEGATION |
|
||||
CFG_ZONE_HINT | CFG_ZONE_REDIRECT | CFG_ZONE_FORWARD },
|
||||
{ NULL, NULL, 0 }
|
||||
};
|
||||
|
||||
/*% The top-level named.conf syntax. */
|
||||
|
||||
static cfg_clausedef_t *namedconf_clausesets[] = { namedconf_clauses,
|
||||
@ -2492,11 +2516,24 @@ static cfg_type_t cfg_type_viewopts = { "view", cfg_parse_map,
|
||||
|
||||
/*% The "zone" statement syntax. */
|
||||
|
||||
static cfg_clausedef_t *zone_clausesets[] = { zone_only_clauses, zone_clauses,
|
||||
static cfg_clausedef_t *zone_clausesets[] = { non_template_clauses,
|
||||
zone_only_clauses, zone_clauses,
|
||||
NULL };
|
||||
cfg_type_t cfg_type_zoneopts = { "zoneopts", cfg_parse_map, cfg_print_map,
|
||||
cfg_doc_map, &cfg_rep_map, zone_clausesets };
|
||||
|
||||
/*%
|
||||
* The "template" statement syntax: any clause that "zone" can take,
|
||||
* except that zones can have a "template" option and templates cannot.
|
||||
*/
|
||||
|
||||
static cfg_clausedef_t *template_clausesets[] = { zone_only_clauses,
|
||||
zone_clauses, NULL };
|
||||
static cfg_type_t cfg_type_templateopts = {
|
||||
"templateopts", cfg_parse_map, cfg_print_map,
|
||||
cfg_doc_map, &cfg_rep_map, template_clausesets
|
||||
};
|
||||
|
||||
/*% The "dnssec-policy" statement syntax. */
|
||||
static cfg_clausedef_t *dnssecpolicy_clausesets[] = { dnssecpolicy_clauses,
|
||||
NULL };
|
||||
@ -3844,6 +3881,14 @@ cfg_clause_validforzone(const char *name, unsigned int ztype) {
|
||||
}
|
||||
valid = true;
|
||||
}
|
||||
for (clause = non_template_clauses; clause->name != NULL; clause++) {
|
||||
if ((clause->flags & ztype) == 0 ||
|
||||
strcmp(clause->name, name) != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
valid = true;
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
@ -3852,23 +3897,25 @@ void
|
||||
cfg_print_zonegrammar(const unsigned int zonetype, unsigned int flags,
|
||||
void (*f)(void *closure, const char *text, int textlen),
|
||||
void *closure) {
|
||||
#define NCLAUSES \
|
||||
(((sizeof(zone_clauses) + sizeof(zone_only_clauses)) / \
|
||||
sizeof(clause[0])) - \
|
||||
1)
|
||||
#define NCLAUSES \
|
||||
ARRAY_SIZE(non_template_clauses) + ARRAY_SIZE(zone_clauses) + \
|
||||
ARRAY_SIZE(zone_only_clauses) - 2
|
||||
|
||||
cfg_printer_t pctx;
|
||||
cfg_clausedef_t *clause = NULL;
|
||||
cfg_clausedef_t clauses[NCLAUSES];
|
||||
cfg_clausedef_t *clause = clauses;
|
||||
|
||||
pctx.f = f;
|
||||
pctx.closure = closure;
|
||||
pctx.indent = 0;
|
||||
pctx.flags = flags;
|
||||
|
||||
memmove(clauses, zone_clauses, sizeof(zone_clauses));
|
||||
memmove(clauses + sizeof(zone_clauses) / sizeof(zone_clauses[0]) - 1,
|
||||
zone_only_clauses, sizeof(zone_only_clauses));
|
||||
memmove(clause, zone_clauses, sizeof(zone_clauses));
|
||||
clause += ARRAY_SIZE(zone_clauses) - 1;
|
||||
memmove(clause, zone_only_clauses, sizeof(zone_only_clauses));
|
||||
clause += ARRAY_SIZE(zone_only_clauses) - 1;
|
||||
memmove(clause, non_template_clauses, sizeof(non_template_clauses));
|
||||
|
||||
qsort(clauses, NCLAUSES - 1, sizeof(clause[0]), cmp_clause);
|
||||
|
||||
cfg_print_cstr(&pctx, "zone <string> [ <class> ] {\n");
|
||||
|
@ -51,6 +51,7 @@ check_PROGRAMS = \
|
||||
transport_test \
|
||||
tsig_test \
|
||||
update_test \
|
||||
zonefile_test \
|
||||
zonemgr_test \
|
||||
zt_test
|
||||
|
||||
|
@ -120,7 +120,8 @@ nsec3param_change_test(const nsec3param_change_test_params_t *test) {
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
dns_zone_setfile(zone, TESTS_DIR "/testdata/nsec3param/nsec3.db.signed",
|
||||
dns_masterformat_text, &dns_master_style_default);
|
||||
NULL, dns_masterformat_text,
|
||||
&dns_master_style_default);
|
||||
|
||||
result = dns_zone_load(zone, false);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
121
tests/dns/zonefile_test.c
Normal file
121
tests/dns/zonefile_test.c
Normal file
@ -0,0 +1,121 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <sched.h> /* IWYU pragma: keep */
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define UNIT_TESTING
|
||||
#include <cmocka.h>
|
||||
|
||||
#include <isc/atomic.h>
|
||||
#include <isc/lib.h>
|
||||
|
||||
#include <dns/lib.h>
|
||||
#include <dns/view.h>
|
||||
|
||||
#include <tests/dns.h>
|
||||
|
||||
typedef struct {
|
||||
const char *input, *expected;
|
||||
} zonefile_test_params_t;
|
||||
|
||||
static int
|
||||
setup_test(void **state) {
|
||||
setup_loopmgr(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
teardown_test(void **state) {
|
||||
teardown_loopmgr(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ISC_LOOP_TEST_IMPL(filename) {
|
||||
isc_result_t result;
|
||||
dns_zone_t *zone = NULL;
|
||||
const zonefile_test_params_t tests[] = {
|
||||
{ "$name", "example.com" },
|
||||
{ "$name.db", "example.com.db" },
|
||||
{ "./dir/$name.db", "./dir/example.com.db" },
|
||||
{ "$type", "primary" },
|
||||
{ "$type-file", "primary-file" },
|
||||
{ "./dir/$type", "./dir/primary" },
|
||||
{ "./$type/$name.db", "./primary/example.com.db" },
|
||||
{ "./$TyPe/$NAmE.db", "./primary/example.com.db" },
|
||||
{ "./$name/$type", "./example.com/primary" },
|
||||
{ "$name.$type", "example.com.primary" },
|
||||
{ "$type$name", "primaryexample.com" },
|
||||
{ "$type$type", "primary$type" },
|
||||
{ "$name$name", "example.com$name" },
|
||||
{ "typename", "typename" },
|
||||
{ "$view", "local" },
|
||||
{ "./$type/$view-$name.db", "./primary/local-example.com.db" },
|
||||
{ "./$view/$type-$name.db", "./local/primary-example.com.db" },
|
||||
{ "./$name/$view-$type.db", "./example.com/local-primary.db" },
|
||||
{ "", "" },
|
||||
};
|
||||
|
||||
dns_view_t *view = NULL;
|
||||
result = dns_test_makeview("local", false, false, &view);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
/* use .COM here to test that the name is correctly downcased */
|
||||
result = dns_test_makezone("example.COM", &zone, view, false);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
|
||||
dns_zone_setview(zone, view);
|
||||
dns_view_detach(&view);
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(tests); i++) {
|
||||
dns_zone_setfile(zone, tests[i].input, NULL,
|
||||
dns_masterformat_text,
|
||||
&dns_master_style_default);
|
||||
assert_string_equal(dns_zone_getfile(zone), tests[i].expected);
|
||||
}
|
||||
|
||||
/* test PATH_MAX overrun */
|
||||
char longname[PATH_MAX] = { 0 };
|
||||
memset(longname, 'x', sizeof(longname) - 1);
|
||||
dns_zone_setfile(zone, longname, NULL, dns_masterformat_text,
|
||||
&dns_master_style_default);
|
||||
assert_string_equal(dns_zone_getfile(zone), longname);
|
||||
|
||||
/*
|
||||
* overwrite the beginning of the long name with $name. when
|
||||
* it's expanded to the zone name, the resulting string should
|
||||
* still be capped at PATH_MAX characters.
|
||||
*/
|
||||
memmove(longname, "$name", 5);
|
||||
dns_zone_setfile(zone, longname, NULL, dns_masterformat_text,
|
||||
&dns_master_style_default);
|
||||
assert_int_equal(strlen(longname), PATH_MAX - 1);
|
||||
memmove(longname, "example.com", 11);
|
||||
assert_string_equal(dns_zone_getfile(zone), longname);
|
||||
|
||||
dns_zone_detach(&zone);
|
||||
isc_loopmgr_shutdown(loopmgr);
|
||||
}
|
||||
|
||||
ISC_TEST_LIST_START
|
||||
ISC_TEST_ENTRY_CUSTOM(filename, setup_test, teardown_test)
|
||||
ISC_TEST_LIST_END
|
||||
|
||||
ISC_TEST_MAIN
|
@ -184,7 +184,7 @@ ISC_LOOP_TEST_IMPL(asyncload_zone) {
|
||||
fwrite(buf, 1, n, zonefile);
|
||||
fflush(zonefile);
|
||||
|
||||
dns_zone_setfile(zone, "./zone.data", dns_masterformat_text,
|
||||
dns_zone_setfile(zone, "./zone.data", NULL, dns_masterformat_text,
|
||||
&dns_master_style_default);
|
||||
|
||||
dns_zone_asyncload(zone, false, load_done_first, zone);
|
||||
@ -235,19 +235,19 @@ ISC_LOOP_TEST_IMPL(asyncload_zt) {
|
||||
|
||||
result = dns_test_makezone("foo", &zone1, NULL, true);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
dns_zone_setfile(zone1, TESTS_DIR "/testdata/zt/zone1.db",
|
||||
dns_zone_setfile(zone1, TESTS_DIR "/testdata/zt/zone1.db", NULL,
|
||||
dns_masterformat_text, &dns_master_style_default);
|
||||
view = dns_zone_getview(zone1);
|
||||
|
||||
result = dns_test_makezone("bar", &zone2, view, false);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
dns_zone_setfile(zone2, TESTS_DIR "/testdata/zt/zone1.db",
|
||||
dns_zone_setfile(zone2, TESTS_DIR "/testdata/zt/zone1.db", NULL,
|
||||
dns_masterformat_text, &dns_master_style_default);
|
||||
|
||||
/* This one will fail to load */
|
||||
result = dns_test_makezone("fake", &zone3, view, false);
|
||||
assert_int_equal(result, ISC_R_SUCCESS);
|
||||
dns_zone_setfile(zone3, TESTS_DIR "/testdata/zt/nonexistent.db",
|
||||
dns_zone_setfile(zone3, TESTS_DIR "/testdata/zt/nonexistent.db", NULL,
|
||||
dns_masterformat_text, &dns_master_style_default);
|
||||
|
||||
rcu_read_lock();
|
||||
|
@ -168,7 +168,7 @@ ns_test_serve_zone(const char *zonename, const char *filename,
|
||||
/*
|
||||
* Set path to the master file for the zone and then load it.
|
||||
*/
|
||||
dns_zone_setfile(served_zone, filename, dns_masterformat_text,
|
||||
dns_zone_setfile(served_zone, filename, NULL, dns_masterformat_text,
|
||||
&dns_master_style_default);
|
||||
result = dns_zone_load(served_zone, false);
|
||||
if (result != ISC_R_SUCCESS) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user