+1394. [func] It is now possible to check if a particular element is
+ in a acl. Remove duplicate entries from the localnets
+ acl.
+
+1393. [port] Bind to individual IPv6 interfaces if IPV6_IPV6ONLY
+ is not available in the kernel to prevent accidently
+ listening on IPv4 interfaces.
+
1392. [bug] named-checkzone: update usage.
1391. [func] Add support for IPv6 scoped addresses in named.
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: interfacemgr.c,v 1.72 2002/10/24 03:52:31 marka Exp $ */
+/* $Id: interfacemgr.c,v 1.73 2002/10/29 04:40:23 marka Exp $ */
#include <config.h>
isc_result_totext(result));
} else {
elt.u.ip_prefix.prefixlen = prefixlen;
- /* XXX suppress duplicates */
- result = dns_acl_appendelement(mgr->aclenv.localnets,
- &elt);
- if (result != ISC_R_SUCCESS)
- return (result);
+ if (dns_acl_elementmatch(mgr->aclenv.localnets, &elt,
+ NULL) == ISC_R_NOTFOUND) {
+ result = dns_acl_appendelement(mgr->aclenv.localnets,
+ &elt);
+ if (result != ISC_R_SUCCESS)
+ return (result);
+ }
}
return (ISC_R_SUCCESS);
isc_boolean_t scan_ipv4 = ISC_FALSE;
isc_boolean_t scan_ipv6 = ISC_FALSE;
isc_boolean_t adjusting = ISC_FALSE;
+ isc_boolean_t ipv6only = ISC_TRUE;
isc_result_t result;
isc_netaddr_t zero_address, zero_address6;
ns_listenelt_t *le;
verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
"no IPv4 interfaces found");
- /* A special, but typical case; listen-on-v6 { any; } */
- /* XXXJT fix when we probe for IPV6_V6ONLY */
- if (scan_ipv6 == ISC_TRUE) {
+ /*
+ * A special, but typical case; listen-on-v6 { any; }.
+ * When we can make the socket IPv6-only, open a single wildcard
+ * socket for IPv6 communication. Otherwise, make separate socket
+ * for each IPv6 address in order to avoid accepting IPv4 packets
+ * as the form of mapped addresses unintentionally unless explicitly
+ * allowed.
+ */
+#ifndef ISC_ALLOW_MAPPED
+ if (scan_ipv6 == ISC_TRUE &&
+ isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
+ ipv6only = ISC_FALSE;
+ isc_log_write(IFMGR_COMMON_LOGARGS,
+ verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
+ "IPv6-only option is not available."
+ " use explicit binding");
+ }
+#endif
+ if (scan_ipv6 == ISC_TRUE && ipv6only) {
for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
le != NULL;
le = ISC_LIST_NEXT(le, link)) {
* The case of "any" IPv6 address will require
* special considerations later, so remember it.
*/
- if (family == AF_INET6 && listenon_is_ip6_any(le))
+ if (family == AF_INET6 && ipv6only &&
+ listenon_is_ip6_any(le))
ipv6_wildcard = ISC_TRUE;
/*
<!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.206 2002/10/24 03:52:32 marka Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.207 2002/10/29 04:40:23 marka Exp $ -->
<book>
<title>BIND 9 Administrator Reference Manual</title>
server will listen on port 53 on all interfaces.</para>
<para>By default, the server does not bind a separate socket to each
-IPv6 interface address as it does for IPv4. Instead, it always
-listens on the IPv6 wildcard address.
-However, some particular IPv6 addresses can also be specified,
-in which case the server makes a separate socket for each specified
-address.</para>
+IPv6 interface address as it does for IPv4. Instead, it listens on the
+IPv6 wildcard address.
+Alternatively, a list of IPv6 addresses can be specified, in which case
+the server listens on a separate socket for each specified address.</para>
<para>Multiple <command>listen-on-v6</command> options can be used.
For example,</para>
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: acl.c,v 1.23 2001/05/31 10:43:37 tale Exp $ */
+/* $Id: acl.c,v 1.24 2002/10/29 04:40:23 marka Exp $ */
#include <config.h>
return (ISC_R_SUCCESS);
}
+isc_result_t
+dns_acl_elementmatch(dns_acl_t *acl,
+ dns_aclelement_t *elt,
+ dns_aclelement_t **matchelt)
+{
+ unsigned int i;
+
+ REQUIRE(elt != NULL);
+ REQUIRE(matchelt == NULL || *matchelt == NULL);
+
+ for (i = 0; i < acl->length; i++) {
+ dns_aclelement_t *e = &acl->elements[i];
+
+ if (dns_aclelement_equal(e, elt) == ISC_TRUE) {
+ if (matchelt != NULL)
+ *matchelt = e;
+ return (ISC_R_SUCCESS);
+ }
+ }
+
+ return (ISC_R_NOTFOUND);
+}
+
isc_boolean_t
dns_aclelement_match(isc_netaddr_t *reqaddr,
dns_name_t *reqsigner,
if (ea->u.ip_prefix.prefixlen !=
eb->u.ip_prefix.prefixlen)
return (ISC_FALSE);
- return (isc_netaddr_equal(&ea->u.ip_prefix.address,
- &eb->u.ip_prefix.address));
+ return (isc_netaddr_eqprefix(&ea->u.ip_prefix.address,
+ &eb->u.ip_prefix.address,
+ ea->u.ip_prefix.prefixlen));
case dns_aclelementtype_keyname:
return (dns_name_equal(&ea->u.keyname, &eb->u.keyname));
case dns_aclelementtype_nestedacl:
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: acl.h,v 1.20 2001/08/28 03:58:11 marka Exp $ */
+/* $Id: acl.h,v 1.21 2002/10/29 04:40:24 marka Exp $ */
#ifndef DNS_ACL_H
#define DNS_ACL_H 1
* returned through 'matchelt' is not necessarily 'e' itself.
*/
+isc_result_t
+dns_acl_elementmatch(dns_acl_t *acl,
+ dns_aclelement_t *elt,
+ dns_aclelement_t **matchelt);
+/*
+ * Search for an ACL element in 'acl' which is exactly the same as 'elt'.
+ * If there is one, and 'matchelt' is non NULL, then '*matchelt' will point
+ * to the entry.
+ *
+ * This function is intended to be used for avoiding duplicated ACL entries
+ * before adding an entry.
+ *
+ * Returns:
+ * ISC_R_SUCCESS Match succeeds.
+ * ISC_R_NOTFOUND Match fails.
+ */
+
ISC_LANG_ENDDECLS
#endif /* DNS_ACL_H */
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.h,v 1.35 2002/10/24 03:52:35 marka Exp $ */
+/* $Id: net.h,v 1.36 2002/10/29 04:40:25 marka Exp $ */
#ifndef ISC_NET_H
#define ISC_NET_H 1
* ISC_R_UNEXPECTED
*/
+isc_result_t
+isc_net_probe_ipv6only(void);
+/*
+ * Check if the system's kernel supports the IPV6_V6ONLY socket option.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS the option is supported for both TCP and UDP.
+ * ISC_R_NOTFOUND IPv6 itself or the option is not supported.
+ * ISC_R_UNEXPECTED
+ */
+
#ifdef ISC_PLATFORM_NEEDNTOP
const char *
isc_net_ntop(int af, const void *src, char *dst, size_t size);
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.c,v 1.25 2001/11/30 01:59:45 gson Exp $ */
+/* $Id: net.c,v 1.26 2002/10/29 04:40:25 marka Exp $ */
#include <config.h>
#endif
static isc_once_t once = ISC_ONCE_INIT;
+static isc_once_t once_ipv6only = ISC_ONCE_INIT;
static isc_result_t ipv4_result = ISC_R_NOTFOUND;
static isc_result_t ipv6_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6only_result = ISC_R_NOTFOUND;
static isc_result_t
try_proto(int domain) {
return (ipv4_result);
}
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
isc_result_t
isc_net_probeipv6(void) {
initialize();
return (ipv6_result);
}
+
+static void
+try_ipv6only(void) {
+#ifdef IPV6_V6ONLY
+ int s, on;
+ char strbuf[ISC_STRERRORSIZE];
+#endif
+ isc_result_t result;
+
+ result = isc_net_probeipv6();
+ if (result != ISC_R_SUCCESS) {
+ ipv6only_result = result;
+ return;
+ }
+
+#ifndef IPV6_V6ONLY
+ ipv6only_result = ISC_R_NOTFOUND;
+ return;
+#else
+ /* check for TCP sockets */
+ s = socket(PF_INET6, SOCK_STREAM, 0);
+ if (s == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6only_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+ ipv6only_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ close(s);
+
+ /* check for UDP sockets */
+ s = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (s == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6only_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+ ipv6only_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ close(s);
+
+ ipv6only_result = ISC_R_SUCCESS;
+
+close:
+ close(s);
+ return;
+#endif
+}
+
+static void
+initialize_ipv6only(void) {
+ RUNTIME_CHECK(isc_once_do(&once_ipv6only,
+ try_ipv6only) == ISC_R_SUCCESS);
+}
+#endif
+#endif
+
+isc_result_t
+isc_net_probe_ipv6only(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+ initialize_ipv6only();
+#else
+ ipv6only_result = ISC_R_NOTFOUND;
+#endif
+#endif
+ return (ipv6only_result);
+}
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.h,v 1.17 2002/08/01 03:56:08 mayer Exp $ */
+/* $Id: net.h,v 1.18 2002/10/29 04:40:26 marka Exp $ */
#ifndef ISC_NET_H
#define ISC_NET_H 1
* ISC_R_UNEXPECTED
*/
+isc_result_t
+isc_net_probe_ipv6only(void);
+/*
+ * Check if the system's kernel supports the IPV6_V6ONLY socket option.
+ *
+ * Returns:
+ *
+ * ISC_R_SUCCESS the option is supported for both TCP and UDP.
+ * ISC_R_NOTFOUND IPv6 itself or the option is not supported.
+ * ISC_R_UNEXPECTED
+ */
+
#ifdef ISC_PLATFORM_NEEDNTOP
const char *
isc_net_ntop(int af, const void *src, char *dst, size_t size);
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-/* $Id: net.c,v 1.4 2001/11/21 05:07:25 mayer Exp $ */
+/* $Id: net.c,v 1.5 2002/10/29 04:40:25 marka Exp $ */
#include <config.h>
#endif
static isc_once_t once = ISC_ONCE_INIT;
+static isc_once_t once_ipv6only = ISC_ONCE_INIT;
static isc_result_t ipv4_result = ISC_R_NOTFOUND;
static isc_result_t ipv6_result = ISC_R_NOTFOUND;
+static isc_result_t ipv6only_result = ISC_R_NOTFOUND;
static isc_result_t
try_proto(int domain) {
return (ipv4_result);
}
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
isc_result_t
isc_net_probeipv6(void) {
initialize();
return (ipv6_result);
}
+
+static void
+try_ipv6only(void) {
+#ifdef IPV6_V6ONLY
+ int s, on;
+ char strbuf[ISC_STRERRORSIZE];
+#endif
+ isc_result_t result;
+
+ result = isc_net_probeipv6();
+ if (result != ISC_R_SUCCESS) {
+ ipv6only_result = result;
+ return;
+ }
+
+#ifndef IPV6_V6ONLY
+ ipv6only_result = ISC_R_NOTFOUND;
+ return;
+#else
+ /* check for TCP sockets */
+ s = socket(PF_INET6, SOCK_STREAM, 0);
+ if (s == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6only_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+ ipv6only_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ close(s);
+
+ /* check for UDP sockets */
+ s = socket(PF_INET6, SOCK_DGRAM, 0);
+ if (s == -1) {
+ isc__strerror(errno, strbuf, sizeof(strbuf));
+ UNEXPECTED_ERROR(__FILE__, __LINE__,
+ "socket() %s: %s",
+ isc_msgcat_get(isc_msgcat,
+ ISC_MSGSET_GENERAL,
+ ISC_MSG_FAILED,
+ "failed"),
+ strbuf);
+ ipv6only_result = ISC_R_UNEXPECTED;
+ return;
+ }
+
+ on = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+ ipv6only_result = ISC_R_NOTFOUND;
+ goto close;
+ }
+
+ close(s);
+
+ ipv6only_result = ISC_R_SUCCESS;
+
+close:
+ close(s);
+ return;
+#endif
+}
+
+static void
+initialize_ipv6only(void) {
+ RUNTIME_CHECK(isc_once_do(&once_ipv6only,
+ try_ipv6only) == ISC_R_SUCCESS);
+}
+#endif
+#endif
+
+isc_result_t
+isc_net_probe_ipv6only(void) {
+#ifdef ISC_PLATFORM_HAVEIPV6
+#ifdef WANT_IPV6
+ initialize_ipv6only();
+#else
+ ipv6only_result = ISC_R_NOTFOUND;
+#endif
+#endif
+ return (ipv6only_result);
+}