in zone masters clauses and other masters lists.
developer: marka
reviewer: explorer
+1443. [func] Masters lists can now be specified and referenced
+ in zone masters clauses and other masters lists.
+
1442. [func] New fuctions for manipulating port lists:
dns_portlist_create(), dns_portlist_add(),
dns_portlist_remove(), dns_portlist_match(),
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: config.c,v 1.38 2003/02/26 02:03:57 marka Exp $ */
+/* $Id: config.c,v 1.39 2003/02/26 06:04:02 marka Exp $ */
#include <config.h>
*addrsp = NULL;
}
+static isc_result_t
+get_masters_def(cfg_obj_t *cctx, char *name, cfg_obj_t **ret) {
+ isc_result_t result;
+ cfg_obj_t *masters = NULL;
+ cfg_listelt_t *elt;
+
+ result = cfg_map_get(cctx, "masters", &masters);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ for (elt = cfg_list_first(masters);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ cfg_obj_t *list;
+ const char *listname;
+
+ list = cfg_listelt_value(elt);
+ listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
+
+ if (strcasecmp(listname, name) == 0) {
+ *ret = list;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return (ISC_R_NOTFOUND);
+}
+
isc_result_t
ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx,
isc_sockaddr_t **addrsp, dns_name_t ***keysp,
isc_uint32_t *countp)
{
- isc_uint32_t count, i = 0;
+ isc_uint32_t addrcount = 0, keycount = 0, i = 0;
+ isc_uint32_t listcount = 0, l = 0, j;
+ isc_uint32_t stackcount = 0, pushed = 0;
isc_result_t result;
cfg_listelt_t *element;
cfg_obj_t *addrlist;
dns_fixedname_t fname;
isc_sockaddr_t *addrs = NULL;
dns_name_t **keys = NULL;
+ char **lists = NULL;
+ struct {
+ cfg_listelt_t *element;
+ in_port_t port;
+ } *stack = NULL;
- INSIST(addrsp != NULL && *addrsp == NULL);
+ REQUIRE(addrsp != NULL && *addrsp == NULL);
+ REQUIRE(keysp != NULL && *keysp == NULL);
+ REQUIRE(countp != NULL);
+ newlist:
addrlist = cfg_tuple_get(list, "addresses");
- count = ns_config_listcount(addrlist);
-
portobj = cfg_tuple_get(list, "port");
if (cfg_obj_isuint32(portobj)) {
isc_uint32_t val = cfg_obj_asuint32(portobj);
result = ISC_R_NOMEMORY;
- addrs = isc_mem_get(mctx, count * sizeof(isc_sockaddr_t));
- if (addrs == NULL)
- goto cleanup;
-
- keys = isc_mem_get(mctx, count * sizeof(dns_name_t *));
- if (keys == NULL)
- goto cleanup;
-
- for (element = cfg_list_first(addrlist);
+ element = cfg_list_first(addrlist);
+ resume:
+ for ( ;
element != NULL;
- element = cfg_list_next(element), i++)
+ element = cfg_list_next(element))
{
cfg_obj_t *addr;
cfg_obj_t *key;
char *keystr;
isc_buffer_t b;
- INSIST(i < count);
-
- addr = cfg_tuple_get(cfg_listelt_value(element), "sockaddr");
+ addr = cfg_tuple_get(cfg_listelt_value(element),
+ "masterselement");
key = cfg_tuple_get(cfg_listelt_value(element), "key");
+ if (!cfg_obj_issockaddr(addr)) {
+ char *listname = cfg_obj_asstring(addr);
+ isc_result_t tresult;
+
+ /* Grow lists? */
+ if (listcount == l) {
+ void * new;
+ isc_uint32_t newlen = listcount + 16;
+ size_t newsize, oldsize;
+
+ newsize = newlen * sizeof(*lists);
+ oldsize = listcount * sizeof(*lists);
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ if (listcount != 0) {
+ memcpy(new, lists, oldsize);
+ isc_mem_put(mctx, lists, oldsize);
+ }
+ lists = new;
+ listcount = newlen;
+ }
+ /* Seen? */
+ for (j = 0; j < l; j++)
+ if (strcasecmp(lists[j], listname) == 0)
+ break;
+ if (j < l)
+ continue;
+ tresult = get_masters_def(config, listname, &list);
+ if (tresult == ISC_R_NOTFOUND) {
+ cfg_obj_log(addr, ns_g_lctx, ISC_LOG_ERROR,
+ "masters \"%s\" not found", listname);
+
+ result = tresult;
+ goto cleanup;
+ }
+ if (tresult != ISC_R_SUCCESS)
+ goto cleanup;
+ lists[l++] = listname;
+ /* Grow stack? */
+ if (stackcount == pushed) {
+ void * new;
+ isc_uint32_t newlen = stackcount + 16;
+ size_t newsize, oldsize;
+
+ newsize = newlen * sizeof(*stack);
+ oldsize = stackcount * sizeof(*stack);
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ if (stackcount != 0) {
+ memcpy(new, stack, oldsize);
+ isc_mem_put(mctx, stack, oldsize);
+ }
+ stack = new;
+ stackcount = newlen;
+ }
+ /*
+ * We want to resume processing this list on the
+ * next element.
+ */
+ stack[pushed].element = cfg_list_next(element);
+ stack[pushed].port = port;
+ pushed++;
+ goto newlist;
+ }
+
+ if (i == addrcount) {
+ void * new;
+ isc_uint32_t newlen = addrcount + 16;
+ size_t newsize, oldsize;
+
+ newsize = newlen * sizeof(isc_sockaddr_t);
+ oldsize = addrcount * sizeof(isc_sockaddr_t);
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ if (addrcount != 0) {
+ memcpy(new, addrs, oldsize);
+ isc_mem_put(mctx, addrs, oldsize);
+ }
+ addrs = new;
+ addrcount = newlen;
+
+ newsize = newlen * sizeof(dns_name_t *);
+ oldsize = keycount * sizeof(dns_name_t *);
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ if (keycount != 0) {
+ memcpy(new, keys, newsize);
+ isc_mem_put(mctx, keys, newsize);
+ }
+ keys = new;
+ keycount = newlen;
+ }
+
addrs[i] = *cfg_obj_assockaddr(addr);
if (isc_sockaddr_getport(&addrs[i]) == 0)
isc_sockaddr_setport(&addrs[i], port);
-
keys[i] = NULL;
- if (!cfg_obj_isstring(key))
+ if (!cfg_obj_isstring(key)) {
+ i++;
continue;
+ }
keys[i] = isc_mem_get(mctx, sizeof(dns_name_t));
if (keys[i] == NULL)
goto cleanup;
keys[i]);
if (result != ISC_R_SUCCESS)
goto cleanup;
+ i++;
+ }
+ if (pushed != 0) {
+ pushed--;
+ element = stack[pushed].element;
+ port = stack[pushed].port;
+ goto resume;
+ }
+ if (i < addrcount) {
+ void * new;
+ size_t newsize, oldsize;
+
+ newsize = i * sizeof(isc_sockaddr_t);
+ oldsize = addrcount * sizeof(isc_sockaddr_t);
+ if (i != 0) {
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ memcpy(new, addrs, newsize);
+ isc_mem_put(mctx, addrs, oldsize);
+ } else
+ new = NULL;
+ addrs = new;
+ addrcount = i;
+
+ newsize = i * sizeof(dns_name_t *);
+ oldsize = keycount * sizeof(dns_name_t *);
+ if (i != 0) {
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ memcpy(new, keys, newsize);
+ isc_mem_put(mctx, keys, oldsize);
+ } else
+ new = NULL;
+ keys = new;
+ keycount = i;
}
- INSIST(i == count);
+
+ if (lists != NULL)
+ isc_mem_put(mctx, lists, listcount * sizeof(*lists));
+ if (stack != NULL)
+ isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
+
+ INSIST(keycount == addrcount);
*addrsp = addrs;
*keysp = keys;
- *countp = count;
+ *countp = addrcount;
return (ISC_R_SUCCESS);
cleanup:
if (addrs != NULL)
- isc_mem_put(mctx, addrs, count * sizeof(isc_sockaddr_t));
+ isc_mem_put(mctx, addrs, addrcount * sizeof(isc_sockaddr_t));
if (keys != NULL) {
- unsigned int j;
for (j = 0; j <= i; j++) {
if (keys[j] == NULL)
continue;
dns_name_free(keys[j], mctx);
isc_mem_put(mctx, keys[j], sizeof(dns_name_t));
}
- isc_mem_put(mctx, keys, count * sizeof(dns_name_t *));
+ isc_mem_put(mctx, keys, keycount * sizeof(dns_name_t *));
}
+ if (lists != NULL)
+ isc_mem_put(mctx, lists, listcount * sizeof(*lists));
+ if (stack != NULL)
+ isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
return (result);
}
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.0//EN"
"http://www.oasis-open.org/docbook/xml/4.0/docbookx.dtd">
-<!-- File: $Id: Bv9ARM-book.xml,v 1.216 2003/02/26 05:05:14 marka Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.217 2003/02/26 06:04:03 marka Exp $ -->
<book>
<title>BIND 9 Administrator Reference Manual</title>
<entry colname = "1"><para><command>logging</command></para></entry>
<entry colname = "2"><para>specifies what the server logs, and where
the log messages are sent.</para></entry>
+ </row>
+ <row rowsep = "0">
+ <entry colname = "1"><para><command>masters</command></para></entry>
+ <entry colname = "2"><para>defines a named masters list for
+inclusion in stub and slave zone masters clauses.</para></entry>
</row>
<row rowsep = "0">
<entry colname = "1"><para><command>options</command></para></entry>
number of dots in a relative domain name that should result in an
exact match lookup before search path elements are appended.</para>
</sect2>
+<sect2>
+ <title><command>masters</command> Statement Grammar</title>
+<programlisting>
+<command>masters</command> <replaceable>name</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> } ;
+</programlisting>
+</sect2>
+<sect2>
+ <title><command>masters</command> Statement Definition and Usage </title>
+<para><command>masters</command> lists allow for a common set of masters
+to be easily used by multiple stub and slave zones.
+</sect2>
<sect2>
<title><command>options</command> Statement Grammar</title>
<optional> ixfr-base <replaceable>string</replaceable> ; </optional>
<optional> ixfr-tmp-file <replaceable>string</replaceable> ; </optional>
<optional> maintain-ixfr-base <replaceable>yes_or_no</replaceable> ; </optional>
- <optional> masters <optional>port <replaceable>ip_port</replaceable></optional> { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>key</replaceable></optional>; <optional>...</optional> } ; </optional>
+ <optional> masters <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>masters_list</replaceable> | <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> <optional>key <replaceable>key</replaceable></optional> ) ; <optional>...</optional> } ; </optional>
<optional> max-ixfr-log-size <replaceable>number</replaceable> ; </optional>
<optional> max-transfer-idle-in <replaceable>number</replaceable> ; </optional>
<optional> max-transfer-idle-out <replaceable>number</replaceable> ; </optional>
<entry colname = "2"><para>A slave zone is a replica of a master
zone. The <command>masters</command> list specifies one or more IP addresses
of master servers that the slave contacts to update its copy of the zone.
+Masters list elements can also be names of other masters lists.
By default, transfers are made from port 53 on the servers; this can
be changed for all servers by specifying a port number before the
list of IP addresses, or on a per-server basis after the IP address.
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: check.c,v 1.34 2003/01/16 03:59:24 marka Exp $ */
+/* $Id: check.c,v 1.35 2003/02/26 06:04:03 marka Exp $ */
#include <config.h>
return (result);
}
+static isc_result_t
+get_masters_def(cfg_obj_t *cctx, char *name, cfg_obj_t **ret) {
+ isc_result_t result;
+ cfg_obj_t *masters = NULL;
+ cfg_listelt_t *elt;
+
+ result = cfg_map_get(cctx, "masters", &masters);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ for (elt = cfg_list_first(masters);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ cfg_obj_t *list;
+ const char *listname;
+
+ list = cfg_listelt_value(elt);
+ listname = cfg_obj_asstring(cfg_tuple_get(list, "name"));
+
+ if (strcasecmp(listname, name) == 0) {
+ *ret = list;
+ return (ISC_R_SUCCESS);
+ }
+ }
+ return (ISC_R_NOTFOUND);
+}
+
+static isc_result_t
+validate_masters(cfg_obj_t *obj, cfg_obj_t *config, isc_uint32_t *countp,
+ isc_log_t *logctx, isc_mem_t *mctx)
+{
+ isc_result_t result = ISC_R_SUCCESS;
+ isc_result_t tresult;
+ isc_uint32_t count = 0;
+ isc_symtab_t *symtab = NULL;
+ isc_symvalue_t symvalue;
+ cfg_listelt_t *element;
+ cfg_listelt_t **stack = NULL;
+ isc_uint32_t stackcount = 0, pushed = 0;
+ cfg_obj_t *list;
+
+ REQUIRE(countp != NULL);
+ result = isc_symtab_create(mctx, 100, NULL, NULL, ISC_FALSE, &symtab);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+
+ newlist:
+ list = cfg_tuple_get(obj, "addresses");
+ element = cfg_list_first(list);
+ resume:
+ for ( ;
+ element != NULL;
+ element = cfg_list_next(element))
+ {
+ char *listname;
+ cfg_obj_t *addr;
+ cfg_obj_t *key;
+
+ addr = cfg_tuple_get(cfg_listelt_value(element),
+ "masterselement");
+ key = cfg_tuple_get(cfg_listelt_value(element), "key");
+
+ if (cfg_obj_issockaddr(addr)) {
+ count++;
+ continue;
+ }
+ if (!cfg_obj_isvoid(key)) {
+ cfg_obj_log(key, logctx, ISC_LOG_ERROR,
+ "unexpected token '%s'",
+ cfg_obj_asstring(key));
+ if (result == ISC_R_SUCCESS)
+ result = ISC_R_FAILURE;
+ }
+ listname = cfg_obj_asstring(addr);
+ symvalue.as_pointer = addr;
+ tresult = isc_symtab_define(symtab, listname, 1, symvalue,
+ isc_symexists_reject);
+ if (tresult == ISC_R_EXISTS)
+ continue;
+ tresult = get_masters_def(config, listname, &obj);
+ if (tresult != ISC_R_SUCCESS) {
+ if (result == ISC_R_SUCCESS)
+ result = tresult;
+ cfg_obj_log(addr, logctx, ISC_LOG_ERROR,
+ "unable to find masters list '%s'",
+ listname);
+ continue;
+ }
+ /* Grow stack? */
+ if (stackcount == pushed) {
+ void * new;
+ isc_uint32_t newlen = stackcount + 16;
+ size_t newsize, oldsize;
+
+ newsize = newlen * sizeof(*stack);
+ oldsize = stackcount * sizeof(*stack);
+ new = isc_mem_get(mctx, newsize);
+ if (new == NULL)
+ goto cleanup;
+ if (stackcount != 0) {
+ memcpy(new, stack, oldsize);
+ isc_mem_put(mctx, stack, oldsize);
+ }
+ stack = new;
+ stackcount = newlen;
+ }
+ stack[pushed++] = cfg_list_next(element);
+ goto newlist;
+ }
+ if (pushed != 0) {
+ element = stack[--pushed];
+ goto resume;
+ }
+ cleanup:
+ if (stack != NULL)
+ isc_mem_put(mctx, stack, stackcount * sizeof(*stack));
+ isc_symtab_destroy(&symtab);
+ *countp = count;
+ return (result);
+}
+
#define MASTERZONE 1
#define SLAVEZONE 2
#define STUBZONE 4
} optionstable;
static isc_result_t
-check_zoneconf(cfg_obj_t *zconfig, isc_symtab_t *symtab,
+check_zoneconf(cfg_obj_t *zconfig, cfg_obj_t *config, isc_symtab_t *symtab,
dns_rdataclass_t defclass, isc_log_t *logctx, isc_mem_t *mctx)
{
const char *zname;
unsigned int ztype;
cfg_obj_t *zoptions;
cfg_obj_t *obj = NULL;
- cfg_obj_t *addrlist = NULL;
isc_symvalue_t symvalue;
isc_result_t result = ISC_R_SUCCESS;
isc_result_t tresult;
zname);
result = ISC_R_FAILURE;
} else {
- addrlist = cfg_tuple_get(obj, "addresses");
- if (cfg_list_first(addrlist) == NULL) {
+ isc_uint32_t count;
+ tresult = validate_masters(obj, config, &count,
+ logctx, mctx);
+ if (tresult != ISC_R_SUCCESS && result == ISC_R_SUCCESS)
+ result = tresult;
+ if (tresult == ISC_R_SUCCESS && count == 0) {
cfg_obj_log(zoptions, logctx, ISC_LOG_ERROR,
"zone '%s': empty 'masters' entry",
zname);
isc_result_t tresult;
cfg_obj_t *zone = cfg_listelt_value(element);
- tresult = check_zoneconf(zone, symtab, vclass, logctx, mctx);
+ tresult = check_zoneconf(zone, config, symtab, vclass,
+ logctx, mctx);
if (tresult != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
}
}
}
+ tresult = cfg_map_get(config, "kal", &acls);
+ if (tresult == ISC_R_SUCCESS) {
+ cfg_listelt_t *elt;
+ cfg_listelt_t *elt2;
+ const char *aclname;
+
+ for (elt = cfg_list_first(acls);
+ elt != NULL;
+ elt = cfg_list_next(elt)) {
+ cfg_obj_t *acl = cfg_listelt_value(elt);
+
+ aclname = cfg_obj_asstring(cfg_tuple_get(acl, "name"));
+
+ for (elt2 = cfg_list_next(elt);
+ elt2 != NULL;
+ elt2 = cfg_list_next(elt2)) {
+ cfg_obj_t *acl2 = cfg_listelt_value(elt2);
+ const char *name;
+ name = cfg_obj_asstring(cfg_tuple_get(acl2,
+ "name"));
+ if (strcasecmp(aclname, name) == 0) {
+ const char *file = cfg_obj_file(acl);
+ unsigned int line = cfg_obj_line(acl);
+
+ if (file == NULL)
+ file = "<unknown file>";
+
+ cfg_obj_log(acl2, logctx, ISC_LOG_ERROR,
+ "attempt to redefine "
+ "kal '%s' previous "
+ "definition: %s:%u",
+ name, file, line);
+ result = ISC_R_FAILURE;
+ }
+ }
+ }
+ }
+
return (result);
}
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: namedconf.c,v 1.17 2003/02/26 05:05:16 marka Exp $ */
+/* $Id: namedconf.c,v 1.18 2003/02/26 06:04:03 marka Exp $ */
#include <config.h>
static cfg_type_t cfg_type_acl;
static cfg_type_t cfg_type_addrmatchelt;
static cfg_type_t cfg_type_bracketed_aml;
-static cfg_type_t cfg_type_bracketed_namesockaddrlist;
-static cfg_type_t cfg_type_bracketed_sockaddrkeylist;
+static cfg_type_t cfg_type_bracketed_namesockaddrkeylist;
static cfg_type_t cfg_type_bracketed_sockaddrlist;
static cfg_type_t cfg_type_controls;
static cfg_type_t cfg_type_controls_sockaddr;
static cfg_type_t cfg_type_logging;
static cfg_type_t cfg_type_logseverity;
static cfg_type_t cfg_type_lwres;
+static cfg_type_t cfg_type_masterselement;
static cfg_type_t cfg_type_nameportiplist;
-static cfg_type_t cfg_type_namesockaddr;
static cfg_type_t cfg_type_negated;
static cfg_type_t cfg_type_notifytype;
static cfg_type_t cfg_type_optional_class;
static cfg_type_t cfg_type_acl = {
"acl", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, acl_fields };
+/* masters */
+static cfg_tuplefielddef_t masters_fields[] = {
+ { "name", &cfg_type_astring, 0 },
+ { "port", &cfg_type_optional_port, 0 },
+ { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
+ { NULL, NULL, 0 }
+};
+
+static cfg_type_t cfg_type_masters = {
+ "masters", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple, masters_fields };
/*
* "sockaddrkeylist", a list of socket addresses with optional keys
* and an optional default port, as used in the masters option.
* E.g.,
- * "port 1234 { 10.0.0.1 key foo; 1::2 port 69; }"
+ * "port 1234 { mymasters; 10.0.0.1 key foo; 1::2 port 69; }"
*/
-static cfg_tuplefielddef_t sockaddrkey_fields[] = {
- { "sockaddr", &cfg_type_sockaddr, 0 },
+static cfg_tuplefielddef_t namesockaddrkey_fields[] = {
+ { "masterselement", &cfg_type_masterselement, 0 },
{ "key", &cfg_type_optional_keyref, 0 },
{ NULL, NULL, 0 },
};
-static cfg_type_t cfg_type_sockaddrkey = {
- "sockaddrkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
- sockaddrkey_fields
+static cfg_type_t cfg_type_namesockaddrkey = {
+ "namesockaddrkey", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
+ namesockaddrkey_fields
};
-static cfg_type_t cfg_type_bracketed_sockaddrkeylist = {
- "bracketed_sockaddrkeylist", cfg_parse_bracketed_list,
- cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_sockaddrkey
+static cfg_type_t cfg_type_bracketed_namesockaddrkeylist = {
+ "bracketed_namesockaddrkeylist", cfg_parse_bracketed_list,
+ cfg_print_bracketed_list, cfg_doc_bracketed_list, &cfg_rep_list, &cfg_type_namesockaddrkey
};
-static cfg_tuplefielddef_t sockaddrkeylist_fields[] = {
+static cfg_tuplefielddef_t namesockaddrkeylist_fields[] = {
{ "port", &cfg_type_optional_port, 0 },
- { "addresses", &cfg_type_bracketed_sockaddrkeylist, 0 },
+ { "addresses", &cfg_type_bracketed_namesockaddrkeylist, 0 },
{ NULL, NULL, 0 }
};
-static cfg_type_t cfg_type_sockaddrkeylist = {
+static cfg_type_t cfg_type_namesockaddrkeylist = {
"sockaddrkeylist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple, &cfg_rep_tuple,
- sockaddrkeylist_fields
+ namesockaddrkeylist_fields
};
/*
{ "options", &cfg_type_options, 0 },
{ "controls", &cfg_type_controls, CFG_CLAUSEFLAG_MULTI },
{ "acl", &cfg_type_acl, CFG_CLAUSEFLAG_MULTI },
+ { "masters", &cfg_type_masters, CFG_CLAUSEFLAG_MULTI },
{ "logging", &cfg_type_logging, 0 },
{ "view", &cfg_type_view, CFG_CLAUSEFLAG_MULTI },
{ "lwres", &cfg_type_lwres, CFG_CLAUSEFLAG_MULTI },
{ "file", &cfg_type_qstring, 0 },
{ "ixfr-base", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
{ "ixfr-tmp-file", &cfg_type_qstring, CFG_CLAUSEFLAG_OBSOLETE },
- { "masters", &cfg_type_sockaddrkeylist, 0 },
+ { "masters", &cfg_type_namesockaddrkeylist, 0 },
{ "pubkey", &cfg_type_pubkey,
CFG_CLAUSEFLAG_MULTI | CFG_CLAUSEFLAG_OBSOLETE },
{ "update-policy", &cfg_type_updatepolicy, 0 },
};
static void
-doc_namesockaddr(cfg_printer_t *pctx, const cfg_type_t *type) {
+doc_sockaddrnameport(cfg_printer_t *pctx, const cfg_type_t *type) {
UNUSED(type);
cfg_print_chars(pctx, "( ", 2);
cfg_print_cstr(pctx, "<quoted_string>");
}
static isc_result_t
-parse_namesockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret)
+parse_sockaddrnameport(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
{
isc_result_t result;
cfg_obj_t *obj = NULL;
}
} else {
cfg_parser_error(pctx, CFG_LOG_NEAR,
- "expected IP match list element");
+ "expected IP address or hostname");
return (ISC_R_UNEXPECTEDTOKEN);
}
cleanup:
return (result);
}
-static cfg_type_t cfg_type_namesockaddr = {
- "namesockaddr_element", parse_namesockaddr, NULL, doc_namesockaddr,
- NULL, NULL
+static cfg_type_t cfg_type_sockaddrnameport = {
+ "sockaddrnameport_element", parse_sockaddrnameport, NULL,
+ doc_sockaddrnameport, NULL, NULL
};
-static cfg_type_t cfg_type_bracketed_namesockaddrlist = {
- "bracketed_namesockaddrlist", cfg_parse_bracketed_list,
+static cfg_type_t cfg_type_bracketed_sockaddrnameportlist = {
+ "bracketed_sockaddrnameportlist", cfg_parse_bracketed_list,
cfg_print_bracketed_list, cfg_doc_bracketed_list,
- &cfg_rep_list, &cfg_type_namesockaddr
+ &cfg_rep_list, &cfg_type_sockaddrnameport
};
/*
- * A list of socket addresses or named with an optional default port,
+ * A list of socket addresses or name with an optional default port,
* as used in the dual-stack-servers option. E.g.,
* "port 1234 { dual-stack-servers.net; 10.0.0.1; 1::2 port 69; }"
*/
static cfg_tuplefielddef_t nameportiplist_fields[] = {
{ "port", &cfg_type_optional_port, 0 },
- { "addresses", &cfg_type_bracketed_namesockaddrlist, 0 },
+ { "addresses", &cfg_type_bracketed_sockaddrnameportlist, 0 },
{ NULL, NULL, 0 }
};
"nameportiplist", cfg_parse_tuple, cfg_print_tuple, cfg_doc_tuple,
&cfg_rep_tuple, nameportiplist_fields
};
+
+/*
+ * masters element.
+ */
+
+static void
+doc_masterselement(cfg_printer_t *pctx, const cfg_type_t *type) {
+ UNUSED(type);
+ cfg_print_chars(pctx, "( ", 2);
+ cfg_print_cstr(pctx, "<masters>");
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_cstr(pctx, "<ipv4_address>");
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_cstr(pctx, "[port <integer>]");
+ cfg_print_chars(pctx, " | ", 3);
+ cfg_print_cstr(pctx, "<ipv6_address>");
+ cfg_print_chars(pctx, " ", 1);
+ cfg_print_cstr(pctx, "[port <integer>]");
+ cfg_print_chars(pctx, " )", 2);
+}
+
+static isc_result_t
+parse_masterselement(cfg_parser_t *pctx, const cfg_type_t *type,
+ cfg_obj_t **ret)
+{
+ isc_result_t result;
+ cfg_obj_t *obj = NULL;
+ UNUSED(type);
+
+ CHECK(cfg_peektoken(pctx, CFG_LEXOPT_QSTRING));
+ if (pctx->token.type == isc_tokentype_string ||
+ pctx->token.type == isc_tokentype_qstring) {
+ if (cfg_lookingat_netaddr(pctx, CFG_ADDR_V4OK | CFG_ADDR_V6OK))
+ CHECK(cfg_parse_sockaddr(pctx, &cfg_type_sockaddr, ret));
+ else
+ CHECK(cfg_parse_astring(pctx, &cfg_type_astring, ret));
+ } else {
+ cfg_parser_error(pctx, CFG_LOG_NEAR,
+ "expected IP address or masters name");
+ return (ISC_R_UNEXPECTEDTOKEN);
+ }
+ cleanup:
+ CLEANUP_OBJ(obj);
+ return (result);
+}
+
+static cfg_type_t cfg_type_masterselement = {
+ "masters_element", parse_masterselement, NULL,
+ doc_masterselement, NULL, NULL
+};