From: Mark Andrews Date: Wed, 26 Feb 2003 06:04:03 +0000 (+0000) Subject: 1443. [func] Masters lists can now be specified and referenced X-Git-Tag: v9.2.3rc1~104^2~91 X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=888bb8bf68ba1a2b032a64122efd9125a9155ad7;p=thirdparty%2Fbind9.git 1443. [func] Masters lists can now be specified and referenced in zone masters clauses and other masters lists. developer: marka reviewer: explorer --- diff --git a/CHANGES b/CHANGES index d6c092e0972..22d805621e9 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,6 @@ +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(), diff --git a/bin/named/config.c b/bin/named/config.c index 02610d403fa..eda73be31a4 100644 --- a/bin/named/config.c +++ b/bin/named/config.c @@ -15,7 +15,7 @@ * 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 @@ -333,12 +333,40 @@ ns_config_putiplist(isc_mem_t *mctx, isc_sockaddr_t **addrsp, *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; @@ -347,12 +375,18 @@ ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx, 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); @@ -370,35 +404,126 @@ ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx, 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; @@ -416,20 +541,62 @@ ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx, 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; @@ -437,8 +604,12 @@ ns_config_getipandkeylist(cfg_obj_t *config, cfg_obj_t *list, isc_mem_t *mctx, 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); } diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index c520e1032f1..8004433455b 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -2,7 +2,7 @@ - + BIND 9 Administrator Reference Manual @@ -2021,6 +2021,11 @@ authentication and authorization using TSIG. logging specifies what the server logs, and where the log messages are sent. + + + masters + defines a named masters list for +inclusion in stub and slave zone masters clauses. options @@ -2681,6 +2686,17 @@ which are appended to relative names in queries. number of dots in a relative domain name that should result in an exact match lookup before search path elements are appended. + + <command>masters</command> Statement Grammar + +masters name port ip_port { ( masters_list | ip_addr port ip_port key key ) ; ... } ; + + + + <command>masters</command> Statement Definition and Usage +masters lists allow for a common set of masters +to be easily used by multiple stub and slave zones. + <command>options</command> Statement Grammar @@ -4407,7 +4423,7 @@ Statement Grammar ixfr-base string ; ixfr-tmp-file string ; maintain-ixfr-base yes_or_no ; - masters port ip_port { ip_addr port ip_port key key; ... } ; + masters port ip_port { ( masters_list | ip_addr port ip_port key key ) ; ... } ; max-ixfr-log-size number ; max-transfer-idle-in number ; max-transfer-idle-out number ; @@ -4451,6 +4467,7 @@ it. A slave zone is a replica of a master zone. The masters 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. diff --git a/lib/bind9/check.c b/lib/bind9/check.c index ee131074990..074c230c8f0 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -15,7 +15,7 @@ * 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 @@ -282,6 +282,126 @@ check_options(cfg_obj_t *options, isc_log_t *logctx) { 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 @@ -294,7 +414,7 @@ typedef struct { } 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; @@ -302,7 +422,6 @@ check_zoneconf(cfg_obj_t *zconfig, isc_symtab_t *symtab, 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; @@ -486,8 +605,12 @@ check_zoneconf(cfg_obj_t *zconfig, isc_symtab_t *symtab, 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); @@ -706,7 +829,8 @@ check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, dns_rdataclass_t vclass, 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; } @@ -938,5 +1062,43 @@ bind9_check_namedconf(cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) { } } + 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 = ""; + + 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); } diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index e224aa4aec2..f1ac5ebecc9 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -15,7 +15,7 @@ * 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 @@ -69,8 +69,7 @@ doc_optional_keyvalue(cfg_printer_t *pctx, const cfg_type_t *type); 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; @@ -81,8 +80,8 @@ static cfg_type_t cfg_type_logfile; 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; @@ -140,38 +139,48 @@ static cfg_tuplefielddef_t acl_fields[] = { 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 }; /* @@ -526,6 +535,7 @@ namedconf_clauses[] = { { "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 }, @@ -702,7 +712,7 @@ zone_only_clauses[] = { { "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 }, @@ -1676,7 +1686,7 @@ static cfg_type_t cfg_type_nameport = { }; 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, ""); @@ -1694,7 +1704,8 @@ doc_namesockaddr(cfg_printer_t *pctx, const cfg_type_t *type) { } 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; @@ -1719,7 +1730,7 @@ parse_namesockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) } } else { cfg_parser_error(pctx, CFG_LOG_NEAR, - "expected IP match list element"); + "expected IP address or hostname"); return (ISC_R_UNEXPECTEDTOKEN); } cleanup: @@ -1727,25 +1738,25 @@ parse_namesockaddr(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) 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 } }; @@ -1753,3 +1764,53 @@ static cfg_type_t cfg_type_nameportiplist = { "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, ""); + cfg_print_chars(pctx, " | ", 3); + cfg_print_cstr(pctx, ""); + cfg_print_chars(pctx, " ", 1); + cfg_print_cstr(pctx, "[port ]"); + cfg_print_chars(pctx, " | ", 3); + cfg_print_cstr(pctx, ""); + cfg_print_chars(pctx, " ", 1); + cfg_print_cstr(pctx, "[port ]"); + 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 +};