From 4844ed026a9b5a91044e76399cee80a6514cbf0d Mon Sep 17 00:00:00 2001 From: Mark Andrews Date: Mon, 17 Jan 2005 00:46:05 +0000 Subject: [PATCH] 1798. [func] The server syntax has been extended to support a range of servers. [RT #11132] --- CHANGES | 3 ++- bin/named/named.conf.docbook | 6 ++--- bin/named/server.c | 9 +++---- doc/arm/Bv9ARM-book.xml | 9 ++++--- lib/bind9/check.c | 41 ++++++++++++++++++---------- lib/dns/include/dns/peer.h | 7 ++++- lib/dns/peer.c | 42 ++++++++++++++++++++++++++--- lib/isc/include/isc/netaddr.h | 15 ++++++++++- lib/isc/netaddr.c | 38 +++++++++++++++++++++++++- lib/isccfg/include/isccfg/grammar.h | 6 ++++- lib/isccfg/namedconf.c | 4 +-- lib/isccfg/parser.c | 16 +++++++++-- 12 files changed, 159 insertions(+), 37 deletions(-) diff --git a/CHANGES b/CHANGES index e419b2afc0..17ec86e495 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,5 @@ -1798. [placeholder] rt11132 +1798. [func] The server syntax has been extended to support a + range of servers. [RT #11132] 1797. [func] named-checkconf now check acls to verify that they only refer to existing acls. [RT #13101] diff --git a/bin/named/named.conf.docbook b/bin/named/named.conf.docbook index 58dd5889a1..f054724700 100644 --- a/bin/named/named.conf.docbook +++ b/bin/named/named.conf.docbook @@ -15,7 +15,7 @@ - PERFORMANCE OF THIS SOFTWARE. --> - + @@ -90,7 +90,7 @@ masters string port integer SERVER -server ( ipv4_address | ipv6_address ) { +server ( ipv4_address/prefixlen | ipv6_address/prefixlen ) { bogus boolean; edns boolean; provide-ixfr boolean; @@ -327,7 +327,7 @@ view string optional_class ... }; - server ( ipv4_address | ipv6_address ) { + server ( ipv4_address/prefixlen | ipv6_address/prefixlen ) { ... }; diff --git a/bin/named/server.c b/bin/named/server.c index b2a6e4ad6b..62394c121b 100644 --- a/bin/named/server.c +++ b/bin/named/server.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: server.c,v 1.437 2005/01/14 03:28:07 marka Exp $ */ +/* $Id: server.c,v 1.438 2005/01/17 00:46:01 marka Exp $ */ #include @@ -580,15 +580,14 @@ configure_order(dns_order_t *order, cfg_obj_t *ent) { static isc_result_t configure_peer(cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { - isc_sockaddr_t *sa; isc_netaddr_t na; dns_peer_t *peer; cfg_obj_t *obj; char *str; isc_result_t result; + unsigned int prefixlen; - sa = cfg_obj_assockaddr(cfg_map_getname(cpeer)); - isc_netaddr_fromsockaddr(&na, sa); + cfg_obj_asnetprefix(cfg_map_getname(cpeer), &na, &prefixlen); peer = NULL; result = dns_peer_new(mctx, &na, &peer); @@ -643,7 +642,7 @@ configure_peer(cfg_obj_t *cpeer, isc_mem_t *mctx, dns_peer_t **peerp) { } obj = NULL; - if (isc_sockaddr_pf(sa) == AF_INET) + if (na.family == AF_INET) (void)cfg_map_get(cpeer, "transfer-source", &obj); else (void)cfg_map_get(cpeer, "transfer-source-v6", &obj); diff --git a/doc/arm/Bv9ARM-book.xml b/doc/arm/Bv9ARM-book.xml index 45194af34c..c582510517 100644 --- a/doc/arm/Bv9ARM-book.xml +++ b/doc/arm/Bv9ARM-book.xml @@ -2,7 +2,7 @@ - + BIND 9 Administrator Reference Manual @@ -4463,7 +4463,7 @@ entries are purged from acache only at the periodic cleaning time. <command>server</command> Statement Grammar -server ip_addr { +server ip_addr/prefixlen { bogus yes_or_no ; provide-ixfr yes_or_no ; request-ixfr yes_or_no ; @@ -4482,7 +4482,10 @@ entries are purged from acache only at the periodic cleaning time. <command>server</command> Statement Definition and Usage The server statement defines characteristics -to be associated with a remote name server. +to be associated with a remote name server. If a prefix length is +specified then a range of servers is covered. Only the most specific +server clause applies regardless of the order in +named.conf. The server statement can occur at the top level of the diff --git a/lib/bind9/check.c b/lib/bind9/check.c index aa2af9021e..5f45ea4de4 100644 --- a/lib/bind9/check.c +++ b/lib/bind9/check.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: check.c,v 1.54 2005/01/11 03:46:10 marka Exp $ */ +/* $Id: check.c,v 1.55 2005/01/17 00:46:02 marka Exp $ */ #include @@ -1101,8 +1101,8 @@ check_servers(cfg_obj_t *servers, isc_log_t *logctx) { isc_result_t result = ISC_R_SUCCESS; cfg_listelt_t *e1, *e2; cfg_obj_t *v1, *v2; - isc_sockaddr_t *s1, *s2; - isc_netaddr_t na; + isc_netaddr_t n1, n2; + unsigned int p1, p2; cfg_obj_t *ts; char buf[128]; const char *xfr; @@ -1110,44 +1110,57 @@ check_servers(cfg_obj_t *servers, isc_log_t *logctx) { for (e1 = cfg_list_first(servers); e1 != NULL; e1 = cfg_list_next(e1)) { v1 = cfg_listelt_value(e1); - s1 = cfg_obj_assockaddr(cfg_map_getname(v1)); + cfg_obj_asnetprefix(cfg_map_getname(v1), &n1, &p1); + /* + * Check that unused bits are zero. + */ + result = isc_netaddr_prefixok(&n1, p1); + if (result != ISC_R_SUCCESS) { + INSIST(result == ISC_R_FAILURE); + isc_buffer_init(&target, buf, sizeof(buf) - 1); + RUNTIME_CHECK(isc_netaddr_totext(&n1, &target) + == ISC_R_SUCCESS); + buf[isc_buffer_usedlength(&target)] = '\0'; + cfg_obj_log(v1, logctx, ISC_LOG_ERROR, + "server '%s/%u': invalid prefix " + "(extra bits specified)", buf, p1); + } ts = NULL; - if (isc_sockaddr_pf(s1) == AF_INET) + if (n1.family == AF_INET) xfr = "transfer-source-v6"; else xfr = "transfer-source"; (void)cfg_map_get(v1, xfr, &ts); if (ts != NULL) { - isc_netaddr_fromsockaddr(&na, s1); isc_buffer_init(&target, buf, sizeof(buf) - 1); - RUNTIME_CHECK(isc_netaddr_totext(&na, &target) + RUNTIME_CHECK(isc_netaddr_totext(&n1, &target) == ISC_R_SUCCESS); buf[isc_buffer_usedlength(&target)] = '\0'; cfg_obj_log(v1, logctx, ISC_LOG_ERROR, - "server '%s': %s not valid", buf, xfr); + "server '%s/%u': %s not valid", + buf, p1, xfr); result = ISC_R_FAILURE; } e2 = e1; while ((e2 = cfg_list_next(e2)) != NULL) { v2 = cfg_listelt_value(e2); - s2 = cfg_obj_assockaddr(cfg_map_getname(v2)); - if (isc_sockaddr_eqaddr(s1, s2)) { + cfg_obj_asnetprefix(cfg_map_getname(v2), &n2, &p2); + if (p1 == p2 && isc_netaddr_equal(&n1, &n2)) { const char *file = cfg_obj_file(v1); unsigned int line = cfg_obj_line(v1); if (file == NULL) file = ""; - isc_netaddr_fromsockaddr(&na, s2); isc_buffer_init(&target, buf, sizeof(buf) - 1); - RUNTIME_CHECK(isc_netaddr_totext(&na, &target) + RUNTIME_CHECK(isc_netaddr_totext(&n2, &target) == ISC_R_SUCCESS); buf[isc_buffer_usedlength(&target)] = '\0'; cfg_obj_log(v2, logctx, ISC_LOG_ERROR, - "server '%s': already exists " + "server '%s/%u': already exists " "previous definition: %s:%u", - buf, file, line); + buf, p2, file, line); result = ISC_R_FAILURE; } } diff --git a/lib/dns/include/dns/peer.h b/lib/dns/include/dns/peer.h index 78be7a99d2..5dffcc4b30 100644 --- a/lib/dns/include/dns/peer.h +++ b/lib/dns/include/dns/peer.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: peer.h,v 1.20 2004/03/05 05:09:45 marka Exp $ */ +/* $Id: peer.h,v 1.21 2005/01/17 00:46:03 marka Exp $ */ #ifndef DNS_PEER_H #define DNS_PEER_H 1 @@ -64,6 +64,7 @@ struct dns_peer { isc_mem_t *mem; isc_netaddr_t address; + unsigned int prefixlen; isc_boolean_t bogus; dns_transfer_format_t transfer_format; isc_uint32_t transfers; @@ -115,6 +116,10 @@ dns_peerlist_currpeer(dns_peerlist_t *peers, dns_peer_t **retval); isc_result_t dns_peer_new(isc_mem_t *mem, isc_netaddr_t *ipaddr, dns_peer_t **peer); +isc_result_t +dns_peer_newprefix(isc_mem_t *mem, isc_netaddr_t *ipaddr, + unsigned int prefixlen, dns_peer_t **peer); + void dns_peer_attach(dns_peer_t *source, dns_peer_t **target); diff --git a/lib/dns/peer.c b/lib/dns/peer.c index 39fdf2b3d2..a1204c6091 100644 --- a/lib/dns/peer.c +++ b/lib/dns/peer.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: peer.c,v 1.19 2004/03/05 05:09:22 marka Exp $ */ +/* $Id: peer.c,v 1.20 2005/01/17 00:46:03 marka Exp $ */ #include @@ -130,7 +130,20 @@ dns_peerlist_addpeer(dns_peerlist_t *peers, dns_peer_t *peer) { dns_peer_attach(peer, &p); - ISC_LIST_APPEND(peers->elements, peer, next); + /* + * More specifics to front of list. + */ + for (p = ISC_LIST_HEAD(peers->elements); + p != NULL; + p = ISC_LIST_NEXT(p, next)) + if (p->prefixlen < peer->prefixlen) + break; + + if (p != NULL) + ISC_LIST_INSERTBEFORE(peers->elements, p, peer, next); + else + ISC_LIST_APPEND(peers->elements, peer, next); + } isc_result_t @@ -145,7 +158,8 @@ dns_peerlist_peerbyaddr(dns_peerlist_t *servers, server = ISC_LIST_HEAD(servers->elements); while (server != NULL) { - if (isc_netaddr_equal(addr, &server->address)) + if (isc_netaddr_eqprefix(addr, &server->address, + server->prefixlen)) break; server = ISC_LIST_NEXT(server, next); @@ -176,6 +190,27 @@ dns_peerlist_currpeer(dns_peerlist_t *peers, dns_peer_t **retval) { isc_result_t dns_peer_new(isc_mem_t *mem, isc_netaddr_t *addr, dns_peer_t **peerptr) { + unsigned int prefixlen = 0; + + REQUIRE(peerptr != NULL); + switch(addr->family) { + case AF_INET: + prefixlen = 32; + break; + case AF_INET6: + prefixlen = 128; + break; + default: + INSIST(0); + } + + return (dns_peer_newprefix(mem, addr, prefixlen, peerptr)); +} + +isc_result_t +dns_peer_newprefix(isc_mem_t *mem, isc_netaddr_t *addr, unsigned int prefixlen, + dns_peer_t **peerptr) +{ dns_peer_t *peer; REQUIRE(peerptr != NULL); @@ -186,6 +221,7 @@ dns_peer_new(isc_mem_t *mem, isc_netaddr_t *addr, dns_peer_t **peerptr) { peer->magic = DNS_PEER_MAGIC; peer->address = *addr; + peer->prefixlen = prefixlen; peer->mem = mem; peer->bogus = ISC_FALSE; peer->transfer_format = dns_one_answer; diff --git a/lib/isc/include/isc/netaddr.h b/lib/isc/include/isc/netaddr.h index 5c399bb02d..b92335505f 100644 --- a/lib/isc/include/isc/netaddr.h +++ b/lib/isc/include/isc/netaddr.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: netaddr.h,v 1.25 2004/03/05 05:10:59 marka Exp $ */ +/* $Id: netaddr.h,v 1.26 2005/01/17 00:46:04 marka Exp $ */ #ifndef ISC_NETADDR_H #define ISC_NETADDR_H 1 @@ -143,6 +143,19 @@ isc_netaddr_fromv4mapped(isc_netaddr_t *t, const isc_netaddr_t *s); * Convert an IPv6 v4mapped address into an IPv4 address. */ +isc_result_t +isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen); +/* + * Test whether the netaddr 'na' and 'prefixlen' are consistant. + * e.g. prefixlen within range. + * na does not have bits set which are not covered by the prefixlen. + * + * Returns: + * ISC_R_SUCCESS + * ISC_R_RANGE prefixlen out of range + * ISC_R_NOTIMPLENTED unsupported family + * ISC_R_FAILURE extra bits. + */ ISC_LANG_ENDDECLS diff --git a/lib/isc/netaddr.c b/lib/isc/netaddr.c index 74cd159535..40fece183d 100644 --- a/lib/isc/netaddr.c +++ b/lib/isc/netaddr.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: netaddr.c,v 1.28 2004/05/15 03:37:33 jinmei Exp $ */ +/* $Id: netaddr.c,v 1.29 2005/01/17 00:46:04 marka Exp $ */ #include @@ -190,6 +190,42 @@ isc_netaddr_format(const isc_netaddr_t *na, char *array, unsigned int size) { } } + +isc_result_t +isc_netaddr_prefixok(const isc_netaddr_t *na, unsigned int prefixlen) { + static const unsigned char zeros[16]; + unsigned int nbits, nbytes, ipbytes, i; + const unsigned char *p; + + switch (na->family) { + case AF_INET: + p = (const unsigned char *) &na->type.in; + ipbytes = 4; + if (prefixlen > 32) + return (ISC_R_RANGE); + break; + case AF_INET6: + p = (const unsigned char *) &na->type.in6; + ipbytes = 16; + if (prefixlen > 128) + return (ISC_R_RANGE); + break; + default: + ipbytes = 0; + return (ISC_R_NOTIMPLEMENTED); + } + nbytes = prefixlen / 8; + nbits = prefixlen % 8; + if (nbits != 0) { + if ((p[nbytes] & (0xff>>nbits)) != 0U) + return (ISC_R_FAILURE); + nbytes++; + } + if (memcmp(p + nbytes, zeros, ipbytes - nbytes) != 0) + return (ISC_R_FAILURE); + return (ISC_R_SUCCESS); +} + isc_result_t isc_netaddr_masktoprefixlen(const isc_netaddr_t *s, unsigned int *lenp) { unsigned int nbits, nbytes, ipbytes, i; diff --git a/lib/isccfg/include/isccfg/grammar.h b/lib/isccfg/include/isccfg/grammar.h index 230f346ac8..32bf863f40 100644 --- a/lib/isccfg/include/isccfg/grammar.h +++ b/lib/isccfg/include/isccfg/grammar.h @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: grammar.h,v 1.6 2004/11/30 01:08:52 marka Exp $ */ +/* $Id: grammar.h,v 1.7 2005/01/17 00:46:05 marka Exp $ */ #ifndef ISCCFG_GRAMMAR_H #define ISCCFG_GRAMMAR_H 1 @@ -377,6 +377,10 @@ cfg_parse_named_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) isc_result_t cfg_parse_addressed_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret); +isc_result_t +cfg_parse_netprefix_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t ** +ret); + void cfg_print_map(cfg_printer_t *pctx, cfg_obj_t *obj); diff --git a/lib/isccfg/namedconf.c b/lib/isccfg/namedconf.c index 4d7b88c82f..52e86a2851 100644 --- a/lib/isccfg/namedconf.c +++ b/lib/isccfg/namedconf.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: namedconf.c,v 1.45 2005/01/11 23:10:06 marka Exp $ */ +/* $Id: namedconf.c,v 1.46 2005/01/17 00:46:04 marka Exp $ */ #include @@ -912,7 +912,7 @@ server_clausesets[] = { NULL }; static cfg_type_t cfg_type_server = { - "server", cfg_parse_addressed_map, cfg_print_map, cfg_doc_map, &cfg_rep_map, + "server", cfg_parse_netprefix_map, cfg_print_map, cfg_doc_map, &cfg_rep_map, server_clausesets }; diff --git a/lib/isccfg/parser.c b/lib/isccfg/parser.c index 3fbda9bff4..4d22ace0a9 100644 --- a/lib/isccfg/parser.c +++ b/lib/isccfg/parser.c @@ -15,7 +15,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: parser.c,v 1.114 2004/07/23 04:15:26 marka Exp $ */ +/* $Id: parser.c,v 1.115 2005/01/17 00:46:04 marka Exp $ */ #include @@ -1358,13 +1358,22 @@ cfg_parse_named_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) /* * Parse a map identified by a network address. - * Used for the "server" statement. + * Used to be used for the "server" statement. */ isc_result_t cfg_parse_addressed_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { return (parse_any_named_map(pctx, &cfg_type_netaddr, type, ret)); } +/* + * Parse a map identified by a network prefix. + * Used for the "server" statement. + */ +isc_result_t +cfg_parse_netprefix_map(cfg_parser_t *pctx, const cfg_type_t *type, cfg_obj_t **ret) { + return (parse_any_named_map(pctx, &cfg_type_netprefix, type, ret)); +} + void cfg_print_mapbody(cfg_printer_t *pctx, cfg_obj_t *obj) { isc_result_t result = ISC_R_SUCCESS; @@ -1483,6 +1492,9 @@ cfg_doc_map(cfg_printer_t *pctx, const cfg_type_t *type) { } else if (type->parse == cfg_parse_addressed_map) { cfg_doc_obj(pctx, &cfg_type_netaddr); cfg_print_chars(pctx, " ", 1); + } else if (type->parse == cfg_parse_netprefix_map) { + cfg_doc_obj(pctx, &cfg_type_netprefix); + cfg_print_chars(pctx, " ", 1); } print_open(pctx);