mirror of
https://gitlab.isc.org/isc-projects/bind9
synced 2025-08-22 01:59:26 +00:00
Add support for zone templates
A "template" statement can contain the same configuration clauses as a "zone" statement. A "zone" statement can now reference a template, and all the clauses in that template will be used as default values for the zone. For example: template primary { type primary; file "$name.db"; initial-file "primary.db"; }; zone example.com { template primary; file "different-name.db"; // overrides the template };
This commit is contained in:
parent
598ae3f63c
commit
b8f325ae01
@ -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 "
|
||||
@ -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,11 +877,13 @@ 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;
|
||||
@ -910,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;
|
||||
@ -951,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);
|
||||
@ -960,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;
|
||||
@ -992,13 +1010,13 @@ 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 = cfg_map_get(zoptions, "initial-file", &obj);
|
||||
result = named_config_get(nooptions, "initial-file", &obj);
|
||||
if (result == ISC_R_SUCCESS) {
|
||||
initial_file = cfg_obj_asstring(obj);
|
||||
}
|
||||
@ -1074,7 +1092,7 @@ named_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
@ -1433,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,
|
||||
@ -1533,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));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1618,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);
|
||||
@ -1769,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));
|
||||
@ -1782,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);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1886,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;
|
||||
|
||||
@ -1927,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;
|
||||
@ -1971,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 {
|
||||
@ -1999,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");
|
||||
}
|
||||
@ -2041,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";
|
||||
};
|
@ -34,14 +34,23 @@ zone "." {
|
||||
file "../../_common/root.hint";
|
||||
};
|
||||
|
||||
zone "example" {
|
||||
template primary {
|
||||
type primary;
|
||||
file "$name.db";
|
||||
};
|
||||
|
||||
zone "example" {
|
||||
template primary;
|
||||
};
|
||||
|
||||
zone "missing" {
|
||||
type primary;
|
||||
file "$name.db";
|
||||
template primary;
|
||||
};
|
||||
|
||||
zone "different" {
|
||||
template primary;
|
||||
initial-file "example.db";
|
||||
file "alternate.db";
|
||||
};
|
||||
|
||||
zone "initial" {
|
||||
|
@ -17,7 +17,9 @@ import dns.zone
|
||||
import isctest
|
||||
import pytest
|
||||
|
||||
pytestmark = pytest.mark.extra_artifacts(["ns2/copied.db", "ns2/present.db"])
|
||||
pytestmark = pytest.mark.extra_artifacts(
|
||||
["ns2/copied.db", "ns2/present.db", "ns2/alternate.db"]
|
||||
)
|
||||
|
||||
|
||||
def test_masterfile_include_semantics():
|
||||
@ -91,7 +93,20 @@ example. 300 IN SOA mname1. . 2010042407 20 20 1814400 3600
|
||||
|
||||
|
||||
def test_masterfile_initial_file():
|
||||
"""Test zone configuration with initial template files"""
|
||||
"""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
|
||||
@ -101,13 +116,30 @@ initial. 300 IN SOA mname1. . 2010042407 20 20 1814400 3600
|
||||
isctest.check.rrsets_equal(res_soa.answer, expected.answer)
|
||||
isctest.check.file_contents_equal("ns2/example.db", "ns2/copied.db")
|
||||
|
||||
# the 'present.db' file already existed and shouldn't load
|
||||
# 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`.
|
||||
|
||||
@ -7377,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>;
|
||||
|
@ -60,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> );
|
||||
|
@ -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,6 @@ 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 },
|
||||
@ -2457,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,
|
||||
@ -2493,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 };
|
||||
@ -3845,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;
|
||||
}
|
||||
@ -3853,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");
|
||||
|
Loading…
x
Reference in New Issue
Block a user