mirror of
https://github.com/isc-projects/bind9.git
synced 2026-04-15 22:09:31 -04:00
1443. [func] Masters lists can now be specified and referenced
in zone masters clauses and other masters lists. developer: marka reviewer: explorer
This commit is contained in:
parent
b312748a11
commit
888bb8bf68
5 changed files with 476 additions and 62 deletions
3
CHANGES
3
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(),
|
||||
|
|
|
|||
|
|
@ -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 <config.h>
|
||||
|
||||
|
|
@ -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++;
|
||||
}
|
||||
INSIST(i == count);
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<!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>
|
||||
|
|
@ -2021,6 +2021,11 @@ authentication and authorization using TSIG.</para></entry>
|
|||
<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>
|
||||
|
|
@ -2681,6 +2686,17 @@ which are appended to relative names in queries.</para>
|
|||
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>
|
||||
|
||||
|
|
@ -4407,7 +4423,7 @@ 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>
|
||||
|
|
@ -4451,6 +4467,7 @@ it.</para></entry>
|
|||
<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.
|
||||
|
|
|
|||
|
|
@ -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 <config.h>
|
||||
|
||||
|
|
@ -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 = "<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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 <config.h>
|
||||
|
||||
|
|
@ -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, "<quoted_string>");
|
||||
|
|
@ -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, "<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
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue