diff --git a/bin/tests/system/checkconf/bad-template-file-reuse.conf b/bin/tests/system/checkconf/bad-template-file-reuse.conf new file mode 100644 index 0000000000..2887071dbc --- /dev/null +++ b/bin/tests/system/checkconf/bad-template-file-reuse.conf @@ -0,0 +1,15 @@ +template a { + type secondary; + primaries { 192.0.0.2; }; + file "$name.db"; +}; + +zone example { + template a; +}; + +zone other { + type secondary; + primaries { 192.0.0.2; }; + file "example.db"; +}; diff --git a/bin/tests/system/checkconf/good-template-file-reuse.conf b/bin/tests/system/checkconf/good-template-file-reuse.conf new file mode 100644 index 0000000000..87886559e6 --- /dev/null +++ b/bin/tests/system/checkconf/good-template-file-reuse.conf @@ -0,0 +1,17 @@ +template a { + type secondary; + primaries { 192.0.0.2; }; + file "$name.db"; +}; + +zone one { + template a; +}; + +zone two { + template a; +}; + +zone three { + template a; +}; diff --git a/bin/tests/system/masterfile/ns2/named.conf.j2 b/bin/tests/system/masterfile/ns2/named.conf.j2 index cdebfae368..72fa31d161 100644 --- a/bin/tests/system/masterfile/ns2/named.conf.j2 +++ b/bin/tests/system/masterfile/ns2/named.conf.j2 @@ -50,3 +50,17 @@ zone "present" { file "present.db"; initial-file "example.db"; }; + +template secondary { + type secondary; + primaries { 10.53.0.1; }; + file "$name.db"; +}; + +zone "extra1" { + template secondary; +}; + +zone "extra2" { + template secondary; +}; diff --git a/bin/tests/system/masterfile/tests_masterfile.py b/bin/tests/system/masterfile/tests_masterfile.py index 598445555d..7109407a8f 100644 --- a/bin/tests/system/masterfile/tests_masterfile.py +++ b/bin/tests/system/masterfile/tests_masterfile.py @@ -18,7 +18,13 @@ import pytest import isctest pytestmark = pytest.mark.extra_artifacts( - ["ns2/copied.db", "ns2/present.db", "ns2/alternate.db"] + [ + "ns2/copied.db", + "ns2/present.db", + "ns2/alternate.db", + "ns2/extra1.db", + "ns2/extra2.db", + ] ) diff --git a/lib/dns/include/dns/zoneproperties.h b/lib/dns/include/dns/zoneproperties.h index ed7a8b1881..524ae33132 100644 --- a/lib/dns/include/dns/zoneproperties.h +++ b/lib/dns/include/dns/zoneproperties.h @@ -1557,3 +1557,36 @@ dns_zone_getkeystores(dns_zone_t *zone); * Get the keystores pointer, it should never be NULL once the server is * initialized. */ + +void +dns_zone_expandzonefile(isc_buffer_t *b, const char *filename, + const dns_name_t *zonename, const char *viewname, + const char *typename); +/*%< + * Expands the zone file name ('filename') using the inputs + * 'zonename', 'viewname' and 'typename'. The expanded file name + * is stored in the buffer 'b'. The follow expansions are available: + * + * - $name or "%s" to the zone name, in lowercase + * - $type or "%t" to the zone type + * - $view or "%v" to the view name + * - $char1 or "%1" to the first character of the zone name + * - $char2 or "%2" to the second character of the zone name (or a dot if + * there is no second character) + * - $char3 or "%3" to the third character of the zone name (or a dot if + * there is no third character) + * - $label1 or "%z" to the toplevel domain of the zone (or a dot if it is + * the TLD) + * - $label2 or "%y" to the next label under the toplevel domain (or a dot if + * there is no next label) + * - $label2 or "%x" to the next-next label under the toplevel domain (or a + * dot if there is no next-next label) + * + * If 'viewname' is NULL, it is treated as an empty string. + * + * Requires: + * \li 'b' to be non NULL. + * \li 'filename' to be non NULL. + * \li 'zonename' to be a valid name. + * \li 'typename' to be non NULL. + */ diff --git a/lib/dns/zoneproperties.c b/lib/dns/zoneproperties.c index 06c0c57c27..96f9d8eef4 100644 --- a/lib/dns/zoneproperties.c +++ b/lib/dns/zoneproperties.c @@ -273,15 +273,23 @@ setstring(dns_zone_t *zone, char **field, const char *value) { } typedef struct foundtoken foundtoken_t; -typedef isc_result_t (*tokenparse_t)(const dns_zone_t *zone, +typedef struct token_names token_names_t; +typedef isc_result_t (*tokenparse_t)(const token_names_t *names, const foundtoken_t *token, isc_buffer_t *b); + struct foundtoken { const char *pos; size_t len; tokenparse_t parse; }; +struct token_names { + dns_name_t *zonename; + const char *viewname; + const char *typename; +}; + static int foundtoken_order(const void *a, const void *b) { /* sort char pointers in order of which occurs first in memory */ @@ -301,80 +309,62 @@ putmem(isc_buffer_t *b, const char *base, size_t length) { } static isc_result_t -tokenparse_type(const dns_zone_t *zone, const foundtoken_t *token, - isc_buffer_t *b) { - const char *typename = dns_zonetype_name(zone->type); - - UNUSED(token); - - return putmem(b, typename, strlen(typename)); -} - -static isc_result_t -tokenparse_name(const dns_zone_t *zone, const foundtoken_t *token, - isc_buffer_t *b) { - isc_result_t result; - char buf[DNS_NAME_FORMATSIZE]; - dns_fixedname_t fn; - dns_name_t *name = dns_fixedname_initname(&fn); - - UNUSED(token); - - result = dns_name_downcase(&zone->origin, name); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - dns_name_format(name, buf, sizeof(buf)); - result = putmem(b, buf, strlen(buf)); - - return result; -} - -static isc_result_t -tokenparse_view(const dns_zone_t *zone, const foundtoken_t *token, +tokenparse_type(const token_names_t *names, const foundtoken_t *token, isc_buffer_t *b) { UNUSED(token); - return putmem(b, zone->view->name, strlen(zone->view->name)); + return putmem(b, names->typename, strlen(names->typename)); } static isc_result_t -tokenparse_char(const dns_zone_t *zone, const foundtoken_t *token, +tokenparse_name(const token_names_t *names, + const foundtoken_t *token ISC_ATTR_UNUSED, isc_buffer_t *b) { + char name[DNS_NAME_FORMATSIZE]; + + dns_name_format(names->zonename, name, sizeof(name)); + return putmem(b, name, strlen(name)); +} + +static isc_result_t +tokenparse_view(const token_names_t *names, const foundtoken_t *token, isc_buffer_t *b) { - isc_result_t result; - char buf[DNS_NAME_FORMATSIZE]; - dns_fixedname_t fn; - dns_name_t *name = dns_fixedname_initname(&fn); + UNUSED(token); + + return putmem(b, names->viewname, strlen(names->viewname)); +} + +static isc_result_t +tokenparse_char(const token_names_t *names, const foundtoken_t *token, + isc_buffer_t *b) { + char name[DNS_NAME_FORMATSIZE]; size_t chartokidx; char c; - result = dns_name_downcase(&zone->origin, name); - RUNTIME_CHECK(result == ISC_R_SUCCESS); - dns_name_format(name, buf, sizeof(buf)); + dns_name_format(names->zonename, name, sizeof(name)); chartokidx = token->pos[token->len - 1] - '1'; INSIST(chartokidx <= 2); - if (chartokidx < strlen(buf)) { - c = buf[chartokidx]; + if (chartokidx < strlen(name)) { + c = name[chartokidx]; } else { c = '.'; } - result = putmem(b, &c, 1); - - return result; + return putmem(b, &c, 1); } static isc_result_t -tokenparse_label(const dns_zone_t *zone, const foundtoken_t *token, +tokenparse_label(const token_names_t *names, const foundtoken_t *token, isc_buffer_t *b) { isc_result_t result; char buf[DNS_NAME_FORMATSIZE]; - dns_fixedname_t fn; - dns_name_t *name = dns_fixedname_initname(&fn); - unsigned int labels = dns_name_countlabels(&zone->origin); + dns_fixedname_t ft; + dns_name_t *target = dns_fixedname_initname(&ft); + unsigned int labels; char labeltokidx; int ilabel = -1; - result = dns_name_fromstring(name, ".", NULL, 0, NULL); - INSIST(result == ISC_R_SUCCESS); + dns_name_copy(dns_rootname, target); + labels = dns_name_countlabels(names->zonename); labeltokidx = token->pos[token->len - 1]; if (token->len == 2) { @@ -389,23 +379,18 @@ tokenparse_label(const dns_zone_t *zone, const foundtoken_t *token, INSIST(labeltokidx >= '1' && labeltokidx <= '3'); } - /* - * Even if implicit, the root label counts as one label. - */ if (labeltokidx == '1' || labeltokidx == 'z') { - ilabel = labels - 2; + ilabel = labels - 1; } else if (labeltokidx == '2' || labeltokidx == 'y') { - ilabel = labels - 3; + ilabel = labels - 2; } else if (labeltokidx == '3' || labeltokidx == 'x') { - ilabel = labels - 4; + ilabel = labels - 3; } if (ilabel >= 0) { - dns_name_getlabelsequence(&zone->origin, ilabel, 1, name); - result = dns_name_downcase(name, name); - RUNTIME_CHECK(result == ISC_R_SUCCESS); + dns_name_getlabelsequence(names->zonename, ilabel, 1, target); } - dns_name_format(name, buf, sizeof(buf)); + dns_name_format(target, buf, sizeof(buf)); result = putmem(b, buf, strlen(buf)); return result; @@ -447,22 +432,33 @@ static const token_t tokens[] = { * * Cap the length at PATH_MAX. */ -static void -setfilename(dns_zone_t *zone, char **field, const char *value) { +void +dns_zone_expandzonefile(isc_buffer_t *b, const char *filename, + const dns_name_t *zonename, const char *viewname, + const char *typename) { isc_result_t result; foundtoken_t founds[ARRAY_SIZE(tokens)]; - char filename[PATH_MAX]; - isc_buffer_t b; + dns_fixedname_t fz; size_t tags = 0; + token_names_t names = { .zonename = dns_fixedname_initname(&fz), + .viewname = viewname, + .typename = typename }; - if (value == NULL) { - *field = NULL; - return; + REQUIRE(zonename != NULL); + REQUIRE(filename != NULL); + REQUIRE(typename != NULL); + + if (viewname == NULL) { + names.viewname = ""; } + /* Normalize the name by converting to lower case */ + result = dns_name_downcase(zonename, names.zonename); + INSIST(result == ISC_R_SUCCESS); + for (size_t i = 0; i < ARRAY_SIZE(tokens); i++) { const token_t *token = &tokens[i]; - const char *p = strcasestr(value, token->name); + const char *p = strcasestr(filename, token->name); if (p != NULL) { founds[tags++] = @@ -473,34 +469,48 @@ setfilename(dns_zone_t *zone, char **field, const char *value) { } if (tags == 0) { - setstring(zone, field, value); - return; + putmem(b, filename, strlen(filename)); + goto cleanup; } - isc_buffer_init(&b, filename, sizeof(filename)); - /* sort the tag offsets in order of occurrence */ qsort(founds, tags, sizeof(foundtoken_t), foundtoken_order); - const char *p = value; + const char *p = filename; for (size_t i = 0; i < tags; i++) { foundtoken_t *token = &founds[i]; - CHECK(putmem(&b, p, token->pos - p)); + CHECK(putmem(b, p, token->pos - p)); p = token->pos; INSIST(p != NULL); - CHECK(token->parse(zone, token, &b)); + CHECK(token->parse(&names, token, b)); /* Advance the input pointer past the token */ p += founds[i].len; } - const char *end = value + strlen(value); - putmem(&b, p, end - p); + const char *end = filename + strlen(filename); + putmem(b, p, end - p); cleanup: - isc_buffer_putuint8(&b, 0); + isc_buffer_putuint8(b, 0); +} + +static void +setfilename(dns_zone_t *zone, char **field, const char *value) { + char filename[PATH_MAX]; + isc_buffer_t b; + + if (value == NULL) { + *field = NULL; + return; + } + + isc_buffer_init(&b, filename, sizeof(filename)); + dns_zone_expandzonefile(&b, value, &zone->origin, + zone->view != NULL ? zone->view->name : NULL, + dns_zonetype_name(zone->type)); setstring(zone, field, filename); } diff --git a/lib/isccfg/check.c b/lib/isccfg/check.c index 6596b50637..232d4d1890 100644 --- a/lib/isccfg/check.c +++ b/lib/isccfg/check.c @@ -57,6 +57,7 @@ #include #include #include +#include #include @@ -74,7 +75,9 @@ static in_port_t dnsport = 53; static isc_result_t -fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, bool writeable); +fileexist(const cfg_obj_t *obj, const dns_name_t *zonename, + const char *viewname, const char *typename, isc_symtab_t *symtab, + bool writeable, isc_mem_t *mctx); static isc_result_t keydirexist(const cfg_obj_t *zcgf, const char *optname, dns_name_t *zname, @@ -4186,7 +4189,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, ztype == CFG_ZONE_MIRROR || ddns || has_dnssecpolicy)) { - tresult = fileexist(fileobj, files, true); + tresult = fileexist(fileobj, zname, viewname, + dns_zonetype_name(ztype), files, + true, mctx); if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS) { result = tresult; @@ -4195,7 +4200,9 @@ isccfg_check_zoneconf(const cfg_obj_t *zconfig, const cfg_obj_t *voptions, (ztype == CFG_ZONE_PRIMARY || ztype == CFG_ZONE_HINT)) { - tresult = fileexist(fileobj, files, false); + tresult = fileexist(fileobj, zname, viewname, + dns_zonetype_name(ztype), files, + false, mctx); if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS) { result = tresult; @@ -4396,20 +4403,33 @@ typedef enum symtab_file_type { } symtab_file_type_t; static isc_result_t -fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, bool writeable) { +fileexist(const cfg_obj_t *obj, const dns_name_t *zonename, + const char *viewname, const char *typename, isc_symtab_t *symtab, + bool writeable, isc_mem_t *mctx) { isc_result_t result_ro, result_w; isc_symvalue_t symvalue_ro, symvalue_w; - unsigned int line; - const char *file; + const char *filename = cfg_obj_asstring(obj); + char buf[PATH_MAX]; + + /* + * If the filename contains '$' or "%' characters, it's probably + * a template file and should not be tested for uniqueness. + */ + if (strpbrk(filename, "%$") != NULL) { + isc_buffer_t b; + isc_buffer_init(&b, buf, sizeof(buf)); + dns_zone_expandzonefile(&b, filename, zonename, viewname, + typename); + filename = buf; + } /* * Since symtab doesn't let us query the file type, we need to query * twice. Once per type. */ - result_ro = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), READ_ONLY, + result_ro = isc_symtab_lookup(symtab, filename, READ_ONLY, &symvalue_ro); - result_w = isc_symtab_lookup(symtab, cfg_obj_asstring(obj), WRITEABLE, - &symvalue_w); + result_w = isc_symtab_lookup(symtab, filename, WRITEABLE, &symvalue_w); bool found_read_only = result_ro == ISC_R_SUCCESS; bool found_writable = result_w == ISC_R_SUCCESS; @@ -4423,8 +4443,8 @@ fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, bool writeable) { ? symvalue_ro : symvalue_w; - file = cfg_obj_file(symvalue.as_cpointer); - line = cfg_obj_line(symvalue.as_cpointer); + const char *file = cfg_obj_file(symvalue.as_cpointer); + unsigned int line = cfg_obj_line(symvalue.as_cpointer); cfg_obj_log(obj, ISC_LOG_ERROR, "writeable file '%s': already in use: " "%s:%u", @@ -4439,9 +4459,12 @@ fileexist(const cfg_obj_t *obj, isc_symtab_t *symtab, bool writeable) { isc_symvalue_t symvalue = (isc_symvalue_t){ .as_cpointer = obj }; symtab_file_type_t type = writeable ? WRITEABLE : READ_ONLY; - isc_result_t result = - isc_symtab_define(symtab, cfg_obj_asstring(obj), type, - symvalue, isc_symexists_reject); + char *key = isc_mem_strdup(mctx, filename); + isc_result_t result = isc_symtab_define( + symtab, key, type, symvalue, isc_symexists_reject); + if (result == ISC_R_EXISTS) { + isc_mem_free(mctx, key); + } return result; } } @@ -6205,7 +6228,7 @@ isccfg_check_namedconf(const cfg_obj_t *config, unsigned int flags, * case sensitive. This will prevent people using FOO.DB and foo.db * on case sensitive file systems but that shouldn't be a major issue. */ - isc_symtab_create(mctx, NULL, NULL, false, &files); + isc_symtab_create(mctx, freekey, mctx, false, &files); isc_symtab_create(mctx, freekey, mctx, false, &keydirs); isc_symtab_create(mctx, freekey, mctx, true, &inview); diff --git a/tests/dns/zonefile_test.c b/tests/dns/zonefile_test.c index b3bbb9568e..6858dfacc3 100644 --- a/tests/dns/zonefile_test.c +++ b/tests/dns/zonefile_test.c @@ -34,7 +34,7 @@ #include typedef struct { - const char *name, *input, *expected; + const char *name, *view, *type, *input, *expected; } zonefile_test_params_t; static int @@ -50,103 +50,106 @@ teardown_test(void **state) { } ISC_LOOP_TEST_IMPL(filename) { - isc_result_t result; - dns_zone_t *zone = NULL; + isc_buffer_t b; + dns_fixedname_t of; + dns_name_t *origin = dns_fixedname_initname(&of); + char buf[PATH_MAX]; const zonefile_test_params_t tests[] = { - { "example.COM", "$name", "example.com" }, - { "example.COM", "$name.db", "example.com.db" }, - { "example.COM", "./dir/$name.db", "./dir/example.com.db" }, - { "example.COM", "%s", "example.com" }, - { "example.COM", "%s.db", "example.com.db" }, - { "example.COM", "./dir/%s.db", "./dir/example.com.db" }, - { "example.COM", "$type", "primary" }, - { "example.COM", "$type-file", "primary-file" }, - { "example.COM", "./dir/$type", "./dir/primary" }, - { "example.COM", "./$type/$name.db", + { "example.COM", "local", "primary", "$name", "example.com" }, + { "example.COM", "local", "primary", "$name.db", + "example.com.db" }, + { "example.COM", "local", "primary", "./dir/$name.db", + "./dir/example.com.db" }, + { "example.COM", "local", "primary", "%s", "example.com" }, + { "example.COM", "local", "primary", "%s.db", + "example.com.db" }, + { "example.COM", "local", "primary", "./dir/%s.db", + "./dir/example.com.db" }, + { "example.COM", "local", "primary", "$type", "primary" }, + { "example.COM", "local", "primary", "$type-file", + "primary-file" }, + { "example.COM", "local", "primary", "./dir/$type", + "./dir/primary" }, + { "example.COM", "local", "secondary", "./dir/$type", + "./dir/secondary" }, + { "example.COM", "local", "primary", "./$type/$name.db", "./primary/example.com.db" }, - { "example.COM", "%t", "primary" }, - { "example.COM", "%t-file", "primary-file" }, - { "example.COM", "./dir/%t", "./dir/primary" }, - { "example.COM", "./%t/%s.db", "./primary/example.com.db" }, - { "example.COM", "./$TyPe/$NAmE.db", + { "example.COM", "local", "primary", "%t", "primary" }, + { "example.COM", "local", "primary", "%t-file", + "primary-file" }, + { "example.COM", "local", "primary", "./dir/%t", + "./dir/primary" }, + { "example.COM", "local", "primary", "./%t/%s.db", "./primary/example.com.db" }, - { "example.COM", "./$name/$type", "./example.com/primary" }, - { "example.COM", "$name.$type", "example.com.primary" }, - { "example.COM", "$type$name", "primaryexample.com" }, - { "example.COM", "$type$type", "primary$type" }, - { "example.COM", "$name$name", "example.com$name" }, - { "example.COM", "typename", "typename" }, - { "example.COM", "$view", "local" }, - { "example.COM", "%v", "local" }, - { "example.COM", "./$type/$view-$name.db", + { "example.COM", "local", "secondary", "./%t/%s.db", + "./secondary/example.com.db" }, + { "example.COM", "local", "primary", "./$TyPe/$NAmE.db", + "./primary/example.com.db" }, + { "example.COM", "local", "primary", "./$name/$type", + "./example.com/primary" }, + { "example.COM", "local", "primary", "$name.$type", + "example.com.primary" }, + { "example.COM", "local", "primary", "$type$name", + "primaryexample.com" }, + { "example.COM", "local", "primary", "$type$type", + "primary$type" }, + { "example.COM", "local", "primary", "$name$name", + "example.com$name" }, + { "example.COM", "local", "primary", "typename", "typename" }, + { "example.COM", "local", "primary", "$view", "local" }, + { "example.COM", NULL, "primary", "$view", "" }, + { "example.COM", "local", "primary", "%v", "local" }, + { "example.COM", "local", "primary", "./$type/$view-$name.db", "./primary/local-example.com.db" }, - { "example.COM", "./$view/$type-$name.db", + { "example.COM", "local", "primary", "./$view/$type-$name.db", "./local/primary-example.com.db" }, - { "example.COM", "./$name/$view-$type.db", + { "example.COM", "local", "primary", "./$name/$view-$type.db", "./example.com/local-primary.db" }, - { "example.COM", "./%s/%v-%t.db", + { "example.COM", "local", "primary", "./%s/%v-%t.db", "./example.com/local-primary.db" }, - { "example.COM", "", "" }, - { "example.COM", "$char1", "e" }, - { "example.COM", "$char2", "x" }, - { "example.COM", "$char3", "a" }, - { "example.COM", "%1", "e" }, - { "example.COM", "%2", "x" }, - { "example.COM", "%3", "a" }, - { "example.COM", "$label1", "com" }, - { "example.COM", "$label2", "example" }, - { "example.COM", "$label3", "." }, - { "example.COM", "%z", "com" }, - { "example.COM", "%y", "example" }, - { "example.COM", "%x", "." }, - { "example", "$label1", "example" }, - { "example", "$label2", "." }, - { "example", "$label3", "." }, - { "a.b.c.d.e", "$label1", "e" }, - { "a.b.c.d.e", "$label2", "d" }, - { "a.b.c.d.e", "$label3", "c" }, - { "a.b.c", "$char1", "a" }, - { "a.b.c", "$char2", "." }, - { "a.b.c", "$char3", "b" }, - { "a.b.c", "%1", "a" }, - { "a.b.c", "%2", "." }, - { "a.b.c", "%3", "b" }, - { "a", "%1", "a" }, - { "a", "%2", "." }, - { "a", "%3", "." }, - { "a.b.c.d", "%1$char2%3$label1%x", "a.bdb" } + { "example.COM", "local", "primary", "", "" }, + { "example.COM", "local", "primary", "$char1", "e" }, + { "example.COM", "local", "primary", "$char2", "x" }, + { "example.COM", "local", "primary", "$char3", "a" }, + { "example.COM", "local", "primary", "%1", "e" }, + { "example.COM", "local", "primary", "%2", "x" }, + { "example.COM", "local", "primary", "%3", "a" }, + { "example.COM", "local", "primary", "$label1", "com" }, + { "example.COM", "local", "primary", "$label2", "example" }, + { "example.COM", "local", "primary", "$label3", "." }, + { "example.COM", "local", "primary", "%z", "com" }, + { "example.COM", "local", "primary", "%y", "example" }, + { "example.COM", "local", "primary", "%x", "." }, + { "example", "local", "primary", "$label1", "example" }, + { "example", "local", "primary", "$label2", "." }, + { "example", "local", "primary", "$label3", "." }, + { "a.b.c.d.e", "local", "primary", "$label1", "e" }, + { "a.b.c.d.e", "local", "primary", "$label2", "d" }, + { "a.b.c.d.e", "local", "primary", "$label3", "c" }, + { "a.b.c", "local", "primary", "$char1", "a" }, + { "a.b.c", "local", "primary", "$char2", "." }, + { "a.b.c", "local", "primary", "$char3", "b" }, + { "a.b.c", "local", "primary", "%1", "a" }, + { "a.b.c", "local", "primary", "%2", "." }, + { "a.b.c", "local", "primary", "%3", "b" }, + { "a", "local", "primary", "%1", "a" }, + { "a", "local", "primary", "%2", "." }, + { "a", "local", "primary", "%3", "." }, + { "a.b.c.d", "local", "primary", "%1$char2%3$label1%x", + "a.bdb" } }; - dns_view_t *view = NULL; - result = dns_test_makeview("local", false, false, &view); - assert_int_equal(result, ISC_R_SUCCESS); - for (size_t i = 0; i < ARRAY_SIZE(tests); i++) { - result = dns_test_makezone(tests[i].name, &zone, view, false); - assert_int_equal(result, ISC_R_SUCCESS); - - dns_zone_setview(zone, view); - 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); - - dns_zone_detach(&zone); + isc_buffer_init(&b, buf, sizeof(buf)); + dns_test_namefromstring(tests[i].name, &of); + dns_zone_expandzonefile(&b, tests[i].input, origin, + tests[i].view, tests[i].type); + assert_string_equal(buf, tests[i].expected); } - /* 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); - /* 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 @@ -154,13 +157,14 @@ ISC_LOOP_TEST_IMPL(filename) { * 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_buffer_init(&b, buf, sizeof(buf)); + dns_test_namefromstring("example.COM", &of); + dns_zone_expandzonefile(&b, longname, origin, "local", "primary"); + memmove(longname, "example.com", 11); + assert_string_equal(buf, longname); + isc_loopmgr_shutdown(); }