}
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 */
}
static isc_result_t
-tokenparse_type(const dns_zone_t *zone, const foundtoken_t *token,
+tokenparse_type(const token_names_t *names, const foundtoken_t *token,
isc_buffer_t *b) {
- const char *typename = dns_zonetype_name(zone->type);
-
UNUSED(token);
- return putmem(b, typename, strlen(typename));
+ return putmem(b, names->typename, strlen(names->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);
+tokenparse_name(const token_names_t *names,
+ const foundtoken_t *token ISC_ATTR_UNUSED, isc_buffer_t *b) {
+ char name[DNS_NAME_FORMATSIZE];
- 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;
+ dns_name_format(names->zonename, name, sizeof(name));
+ return putmem(b, name, strlen(name));
}
static isc_result_t
-tokenparse_view(const dns_zone_t *zone, const foundtoken_t *token,
+tokenparse_view(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->viewname, strlen(names->viewname));
}
static isc_result_t
-tokenparse_char(const dns_zone_t *zone, const foundtoken_t *token,
+tokenparse_char(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);
+ 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) {
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;
*
* 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++] =
}
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);
}
#include <tests/dns.h>
typedef struct {
- const char *name, *input, *expected;
+ const char *name, *view, *type, *input, *expected;
} zonefile_test_params_t;
static int
}
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
* 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);
+
+ 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(dns_zone_getfile(zone), longname);
+ assert_string_equal(buf, longname);
- dns_zone_detach(&zone);
isc_loopmgr_shutdown();
}