Commit 0ffaee88 authored by Mark Andrews's avatar Mark Andrews
Browse files

1412. [func] You can now specify servers to be tried if a nameserver

                       has IPv6 address and you only support IPv4 or the
                       reverse. See dual-stack-servers.
parent f4895668
1412. [func] You can now specify servers to be tried if a nameserver
has IPv6 address and you only support IPv4 or the
reverse. See dual-stack-servers.
1411. [bug] empty nodes should stop wildcard matches. [RT #4802]
1410. [func] handle records that live in the parent zone, e.g. DS.
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: main.c,v 1.128 2002/05/03 05:28:19 marka Exp $ */
/* $Id: main.c,v 1.129 2003/01/16 03:59:23 marka Exp $ */
#include <config.h>
......@@ -329,14 +329,31 @@ static void
parse_command_line(int argc, char *argv[]) {
int ch;
int port;
isc_boolean_t disable6 = ISC_FALSE;
isc_boolean_t disable4 = ISC_FALSE;
save_command_line(argc, argv);
isc_commandline_errprint = ISC_FALSE;
while ((ch = isc_commandline_parse(argc, argv,
"c:C:d:fgi:lm:n:N:p:P:st:u:vx:")) !=
-1) {
"46c:C:d:fgi:lm:n:N:p:P:st:u:vx:")) != -1) {
switch (ch) {
case '4':
if (disable4)
ns_main_earlyfatal("cannot specify -4 and -6");
if (isc_net_probeipv4() != ISC_R_SUCCESS)
ns_main_earlyfatal("IPv4 not supported by OS");
isc_net_disableipv6();
disable6 = ISC_TRUE;
break;
case '6':
if (disable6)
ns_main_earlyfatal("cannot specify -4 and -6");
if (isc_net_probeipv6() != ISC_R_SUCCESS)
ns_main_earlyfatal("IPv6 not supported by OS");
isc_net_disableipv4();
disable4 = ISC_TRUE;
break;
case 'c':
ns_g_conffile = isc_commandline_argument;
lwresd_g_conffile = isc_commandline_argument;
......
......@@ -16,7 +16,7 @@
- WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-->
<!-- $Id: named.docbook,v 1.5 2001/06/10 13:57:51 tale Exp $ -->
<!-- $Id: named.docbook,v 1.6 2003/01/16 03:59:23 marka Exp $ -->
<refentry>
<refentryinfo>
......@@ -37,6 +37,8 @@
<refsynopsisdiv>
<cmdsynopsis>
<command>named</command>
<arg><option>-4</option></arg>
<arg><option>-6</option></arg>
<arg><option>-c <replaceable class="parameter">config-file</replaceable></option></arg>
<arg><option>-d <replaceable class="parameter">debug-level</replaceable></option></arg>
<arg><option>-f</option></arg>
......@@ -70,6 +72,27 @@
<title>OPTIONS</title>
<variablelist>
<varlistentry>
<term>-4</term>
<listitem>
<para>
Use IPv4 only even if the host machine is capable of IPv6.
<option>-4</option> and <option>-6</option> are mutually
exclusive.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-6</term>
<listitem>
<para>
Use IPv6 only even if the host machine is capable of IPv4.
<option>-4</option> and <option>-6</option> are mutually
exclusive.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>-c <replaceable class="parameter">config-file</replaceable></term>
<listitem>
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: server.c,v 1.391 2002/11/27 09:52:45 marka Exp $ */
/* $Id: server.c,v 1.392 2003/01/16 03:59:23 marka Exp $ */
#include <config.h>
......@@ -137,6 +137,10 @@ static isc_result_t
configure_forward(cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
cfg_obj_t *forwarders, cfg_obj_t *forwardtype);
static isc_result_t
configure_alternates(cfg_obj_t *config, dns_view_t *view,
cfg_obj_t *alternates);
static isc_result_t
configure_zone(cfg_obj_t *config, cfg_obj_t *zconfig, cfg_obj_t *vconfig,
isc_mem_t *mctx, dns_view_t *view,
......@@ -558,6 +562,7 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
cfg_obj_t *voptions = NULL;
cfg_obj_t *forwardtype;
cfg_obj_t *forwarders;
cfg_obj_t *alternates;
cfg_obj_t *zonelist;
cfg_obj_t *obj;
cfg_listelt_t *element;
......@@ -748,6 +753,14 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
CHECK(configure_forward(config, view, dns_rootname,
forwarders, forwardtype));
/*
* Dual Stack Servers.
*/
alternates = NULL;
(void)ns_config_get(maps, "dual-stack-servers", &alternates);
if (alternates != NULL)
CHECK(configure_alternates(config, view, alternates));
/*
* We have default hints for class IN if we need them.
*/
......@@ -987,6 +1000,91 @@ configure_hints(dns_view_t *view, const char *filename) {
return (result);
}
static isc_result_t
configure_alternates(cfg_obj_t *config, dns_view_t *view,
cfg_obj_t *alternates)
{
cfg_obj_t *portobj;
cfg_obj_t *addresses;
cfg_listelt_t *element;
isc_result_t result = ISC_R_SUCCESS;
in_port_t port;
/*
* Determine which port to send requests to.
*/
if (ns_g_lwresdonly && ns_g_port != 0)
port = ns_g_port;
else
CHECKM(ns_config_getport(config, &port), "port");
if (alternates != NULL) {
portobj = cfg_tuple_get(alternates, "port");
if (cfg_obj_isuint32(portobj)) {
isc_uint32_t val = cfg_obj_asuint32(portobj);
if (val > ISC_UINT16_MAX) {
cfg_obj_log(portobj, ns_g_lctx, ISC_LOG_ERROR,
"port '%u' out of range", val);
return (ISC_R_RANGE);
}
port = (in_port_t) val;
}
}
addresses = NULL;
if (alternates != NULL)
addresses = cfg_tuple_get(alternates, "addresses");
for (element = cfg_list_first(addresses);
element != NULL;
element = cfg_list_next(element))
{
cfg_obj_t *alternate = cfg_listelt_value(element);
isc_sockaddr_t sa;
if (!cfg_obj_issockaddr(alternate)) {
dns_fixedname_t fixed;
dns_name_t *name;
char *str = cfg_obj_asstring(cfg_tuple_get(alternate,
"name"));
isc_buffer_t buffer;
in_port_t myport = port;
isc_buffer_init(&buffer, str, strlen(str));
isc_buffer_add(&buffer, strlen(str));
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
ISC_FALSE, NULL));
portobj = cfg_tuple_get(alternates, "port");
if (cfg_obj_isuint32(portobj)) {
isc_uint32_t val = cfg_obj_asuint32(portobj);
if (val > ISC_UINT16_MAX) {
cfg_obj_log(portobj, ns_g_lctx,
ISC_LOG_ERROR,
"port '%u' out of range",
val);
return (ISC_R_RANGE);
}
myport = (in_port_t) val;
}
CHECK(dns_resolver_addalternate(view->resolver, NULL,
name, myport));
continue;
}
sa = *cfg_obj_assockaddr(alternate);
if (isc_sockaddr_getport(&sa) == 0)
isc_sockaddr_setport(&sa, port);
CHECK(dns_resolver_addalternate(view->resolver, &sa,
NULL, 0));
}
cleanup:
return (result);
}
static isc_result_t
configure_forward(cfg_obj_t *config, dns_view_t *view, dns_name_t *origin,
cfg_obj_t *forwarders, cfg_obj_t *forwardtype)
......
......@@ -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.211 2003/01/13 04:24:27 marka Exp $ -->
<!-- File: $Id: Bv9ARM-book.xml,v 1.212 2003/01/16 03:59:24 marka Exp $ -->
<book>
<title>BIND 9 Administrator Reference Manual</title>
......@@ -2717,6 +2717,7 @@ statement in the <filename>named.conf</filename> file:</para>
<optional> maintain-ixfr-base <replaceable>yes_or_no</replaceable>; </optional>
<optional> forward ( <replaceable>only</replaceable> | <replaceable>first</replaceable> ); </optional>
<optional> forwarders { <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; <optional> <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ; ... </optional> }; </optional>
<optional> dual-stack-servers <optional>port <replaceable>ip_port</replaceable></optional> { ( <replaceable>domain_name</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> | <replaceable>ip_addr</replaceable> <optional>port <replaceable>ip_port</replaceable></optional> ) ; ... }; </optional>
<optional> check-names ( <replaceable>master</replaceable> | <replaceable>slave</replaceable> | <replaceable> response</replaceable> )( <replaceable>warn</replaceable> | <replaceable>fail</replaceable> | <replaceable>ignore</replaceable> ); </optional>
<optional> allow-notify { <replaceable>address_match_list</replaceable> }; </optional>
<optional> allow-query { <replaceable>address_match_list</replaceable> }; </optional>
......@@ -3303,6 +3304,23 @@ or have a different <command>forward only/first</command> behavior,
or not forward at all, see <xref linkend="zone_statement_grammar"/>.</para>
</sect3>
<sect3><title>6 to 4 Servers</title>
<para>6 to 4 servers are used as servers of last resort to work around
problems in reachability due the lack of support for either IPv4 or IPv6
on the host machine.</para>
<variablelist>
<varlistentry><term><command>dual-stack-servers</command></term>
<listitem><para>Specifies host names / addresses of machines with access to
both IPv4 and IPv6 transports. If a hostname is used the server must be able
to resolve the name using only the transport it has. If the machine is dual
stacked then the <command>dual-stack-servers</command> have no effect unless
access to a transport has been disabled on the command line
(e.g. <command>named -4</command>).</para></listitem>
</varlistentry>
</variablelist>
</sect3>
<sect3 id="access_control"><title>Access Control</title>
<para>Access to the server can be restricted based on the IP address
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: check.c,v 1.33 2002/04/26 00:40:28 marka Exp $ */
/* $Id: check.c,v 1.34 2003/01/16 03:59:24 marka Exp $ */
#include <config.h>
......@@ -143,6 +143,66 @@ check_order(cfg_obj_t *options, isc_log_t *logctx) {
return (result);
}
static isc_result_t
check_dual_stack(cfg_obj_t *options, isc_log_t *logctx) {
cfg_listelt_t *element;
cfg_obj_t *alternates = NULL;
cfg_obj_t *value;
cfg_obj_t *obj;
char *str;
dns_fixedname_t fixed;
dns_name_t *name;
isc_buffer_t buffer;
isc_result_t result = ISC_R_SUCCESS;
isc_result_t tresult;
(void)cfg_map_get(options, "dual-stack-servers", &alternates);
if (alternates == NULL)
return (ISC_R_SUCCESS);
obj = cfg_tuple_get(alternates, "port");
if (cfg_obj_isuint32(obj)) {
isc_uint32_t val = cfg_obj_asuint32(obj);
if (val > ISC_UINT16_MAX) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"port '%u' out of range", val);
result = ISC_R_FAILURE;
}
}
obj = cfg_tuple_get(alternates, "addresses");
for (element = cfg_list_first(obj);
element != NULL;
element = cfg_list_next(element)) {
value = cfg_listelt_value(element);
if (cfg_obj_issockaddr(value))
continue;
obj = cfg_tuple_get(value, "name");
str = cfg_obj_asstring(obj);
isc_buffer_init(&buffer, str, strlen(str));
isc_buffer_add(&buffer, strlen(str));
dns_fixedname_init(&fixed);
name = dns_fixedname_name(&fixed);
tresult = dns_name_fromtext(name, &buffer, dns_rootname,
ISC_FALSE, NULL);
if (tresult != ISC_R_SUCCESS) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"bad name '%s'", str);
result = ISC_R_FAILURE;
}
obj = cfg_tuple_get(value, "port");
if (cfg_obj_isuint32(obj)) {
isc_uint32_t val = cfg_obj_asuint32(obj);
if (val > ISC_UINT16_MAX) {
cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
"port '%u' out of range", val);
result = ISC_R_FAILURE;
}
}
}
return (result);
}
static isc_result_t
check_forward(cfg_obj_t *options, isc_log_t *logctx) {
cfg_obj_t *forward = NULL;
......@@ -697,6 +757,19 @@ check_viewconf(cfg_obj_t *config, cfg_obj_t *vconfig, dns_rdataclass_t vclass,
if (check_forward(vconfig, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
}
/*
* Check that dual-stack-servers is reasonable.
*/
if (vconfig == NULL) {
cfg_obj_t *options = NULL;
(void)cfg_map_get(config, "options", &options);
if (options != NULL)
if (check_dual_stack(options, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
} else {
if (check_dual_stack(vconfig, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
}
/*
* Check that rrset-order is reasonable.
......@@ -755,6 +828,10 @@ bind9_check_namedconf(cfg_obj_t *config, isc_log_t *logctx, isc_mem_t *mctx) {
(void)cfg_map_get(config, "view", &views);
if (views != NULL && options != NULL)
if (check_dual_stack(options, logctx) != ISC_R_SUCCESS)
result = ISC_R_FAILURE;
if (views == NULL) {
if (check_viewconf(config, NULL, dns_rdataclass_in,
logctx, mctx) != ISC_R_SUCCESS)
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: resolver.h,v 1.35 2001/10/29 19:02:46 gson Exp $ */
/* $Id: resolver.h,v 1.36 2003/01/16 03:59:25 marka Exp $ */
#ifndef DNS_RESOLVER_H
#define DNS_RESOLVER_H 1
......@@ -359,6 +359,18 @@ dns_resolver_nrunning(dns_resolver_t *resolver);
* can continue even though a fetch has been canceled.
*/
isc_result_t
dns_resolver_addalternate(dns_resolver_t *resolver, isc_sockaddr_t *alt,
dns_name_t *name, in_port_t port);
/*
* Add alternate addresses to be tried in the event that the nameservers
* for a zone are not available in the address families supported by the
* operating system.
*
* Require:
* only one of 'name' or 'alt' to be valid.
*/
ISC_LANG_ENDDECLS
#endif /* DNS_RESOLVER_H */
This diff is collapsed.
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: result.h,v 1.59 2001/11/30 01:02:17 gson Exp $ */
/* $Id: result.h,v 1.60 2003/01/16 03:59:26 marka Exp $ */
#ifndef ISC_RESULT_H
#define ISC_RESULT_H 1
......@@ -80,11 +80,12 @@
#define ISC_R_CONNECTIONRESET 54 /* connection reset */
#define ISC_R_SOFTQUOTA 55 /* soft quota reached */
#define ISC_R_BADNUMBER 56 /* not a valid number */
#define ISC_R_DISABLED 57 /* disabled */
/*
* Not a result code: the number of results.
*/
#define ISC_R_NRESULTS 57
#define ISC_R_NRESULTS 58
ISC_LANG_BEGINDECLS
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: result.c,v 1.59 2001/11/30 01:02:14 gson Exp $ */
/* $Id: result.c,v 1.60 2003/01/16 03:59:25 marka Exp $ */
#include <config.h>
......@@ -94,7 +94,8 @@ static const char *text[ISC_R_NRESULTS] = {
"operation in progress", /* 53 */
"connection reset", /* 54 */
"soft quota reached", /* 55 */
"not a valid number" /* 56 */
"not a valid number", /* 56 */
"disabled" /* 57 */
};
#define ISC_RESULT_RESULTSET 2
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: net.h,v 1.36 2002/10/29 04:40:25 marka Exp $ */
/* $Id: net.h,v 1.37 2003/01/16 03:59:27 marka Exp $ */
#ifndef ISC_NET_H
#define ISC_NET_H 1
......@@ -245,6 +245,7 @@ isc_net_probeipv4(void);
*
* ISC_R_SUCCESS IPv4 is supported.
* ISC_R_NOTFOUND IPv4 is not supported.
* ISC_R_DISABLED IPv4 is disabled.
* ISC_R_UNEXPECTED
*/
......@@ -257,6 +258,7 @@ isc_net_probeipv6(void);
*
* ISC_R_SUCCESS IPv6 is supported.
* ISC_R_NOTFOUND IPv6 is not supported.
* ISC_R_DISABLED IPv6 is disabled.
* ISC_R_UNEXPECTED
*/
......@@ -272,6 +274,18 @@ isc_net_probe_ipv6only(void);
* ISC_R_UNEXPECTED
*/
void
isc_net_disableipv4(void);
void
isc_net_disableipv6(void);
void
isc_net_enableipv4(void);
void
isc_net_enableipv6(void);
#ifdef ISC_PLATFORM_NEEDNTOP
const char *
isc_net_ntop(int af, const void *src, char *dst, size_t size);
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: net.c,v 1.27 2002/12/24 05:12:50 marka Exp $ */
/* $Id: net.c,v 1.28 2003/01/16 03:59:27 marka Exp $ */
#include <config.h>
......@@ -95,7 +95,7 @@ try_proto(int domain) {
"socket from the kernel failed.");
isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
"IPv6 support is disabled.");
"IPv6 is not supported.");
result = ISC_R_NOTFOUND;
} else {
if (len == sizeof(struct sockaddr_in6))
......@@ -111,7 +111,7 @@ try_proto(int domain) {
ISC_LOGCATEGORY_GENERAL,
ISC_LOGMODULE_SOCKET,
ISC_LOG_ERROR,
"IPv6 support is disabled.");
"IPv6 is not supported.");
result = ISC_R_NOTFOUND;
}
}
......@@ -247,3 +247,31 @@ isc_net_probe_ipv6only(void) {
#endif
return (ipv6only_result);
}
void
isc_net_disableipv4(void) {
initialize();
if (ipv4_result == ISC_R_SUCCESS)
ipv4_result = ISC_R_DISABLED;
}
void
isc_net_disableipv6(void) {
initialize();
if (ipv6_result == ISC_R_SUCCESS)
ipv6_result = ISC_R_DISABLED;
}
void
isc_net_enableipv4(void) {
initialize();
if (ipv4_result == ISC_R_DISABLED)
ipv4_result = ISC_R_SUCCESS;
}
void
isc_net_enableipv6(void) {
initialize();
if (ipv6_result == ISC_R_DISABLED)
ipv6_result = ISC_R_SUCCESS;
}
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: net.h,v 1.18 2002/10/29 04:40:26 marka Exp $ */
/* $Id: net.h,v 1.19 2003/01/16 03:59:28 marka Exp $ */
#ifndef ISC_NET_H
#define ISC_NET_H 1
......@@ -232,6 +232,7 @@ isc_net_probeipv4(void);
*
* ISC_R_SUCCESS IPv4 is supported.
* ISC_R_NOTFOUND IPv4 is not supported.
* ISC_R_DISABLED IPv4 is disabled.
* ISC_R_UNEXPECTED
*/
......@@ -244,6 +245,7 @@ isc_net_probeipv6(void);
*
* ISC_R_SUCCESS IPv6 is supported.
* ISC_R_NOTFOUND IPv6 is not supported.
* ISC_R_DISABLED IPv6 is disabled.
* ISC_R_UNEXPECTED
*/
......@@ -259,6 +261,18 @@ isc_net_probe_ipv6only(void);
* ISC_R_UNEXPECTED
*/
void
isc_net_disableipv4(void);
void
isc_net_disableipv6(void);
void
isc_net_enableipv4(void);
void
isc_net_enableipv6(void);
#ifdef ISC_PLATFORM_NEEDNTOP
const char *
isc_net_ntop(int af, const void *src, char *dst, size_t size);
......
......@@ -15,7 +15,7 @@
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id: net.c,v 1.6 2003/01/14 23:37:06 marka Exp $ */
/* $Id: net.c,v 1.7 2003/01/16 03:59:27 marka Exp $ */
#include <config.h>
......@@ -240,3 +240,31 @@ isc_net_probe_ipv6only(void) {
#endif
return (ipv6only_result);
}
void
isc_net_disableipv4(void) {
initialize();
if (ipv4_result == ISC_R_SUCCESS)
ipv4_result = ISC_R_DISABLED;
}
void
isc_net_disableipv6(void) {
initialize();
if (ipv6_result == ISC_R_SUCCESS)
ipv6_result = ISC_R_DISABLED;
}
void
isc_net_enableipv4(void) {
initialize();
if (ipv4_result == ISC_R_DISABLED)
ipv4_result = ISC_R_SUCCESS;
}
void
isc_net_enableipv6(void) {
initialize();
if (ipv6_result == ISC_R_DISABLED)