2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-08-31 14:35:26 +00:00

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.
developer: jinmei
reviewer: marka
This commit is contained in:
Mark Andrews
2002-10-29 04:40:26 +00:00
parent 2357adb0d4
commit aa39170da8
9 changed files with 308 additions and 24 deletions

View File

@@ -1,3 +1,11 @@
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.

View File

@@ -15,7 +15,7 @@
* 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>
@@ -524,11 +524,13 @@ setup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) {
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);
@@ -542,6 +544,7 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
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;
@@ -567,9 +570,25 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
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)) {
@@ -702,7 +721,8 @@ do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
* 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;
/*

View File

@@ -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.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>
@@ -3549,11 +3549,10 @@ listen-on port 1234 { !1.2.3.4; 1.2/16; };
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>

View File

@@ -15,7 +15,7 @@
* 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>
@@ -149,6 +149,29 @@ dns_acl_match(isc_netaddr_t *reqaddr,
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,
@@ -297,8 +320,9 @@ dns_aclelement_equal(dns_aclelement_t *ea, dns_aclelement_t *eb) {
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:

View File

@@ -15,7 +15,7 @@
* 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
@@ -199,6 +199,23 @@ dns_aclelement_match(isc_netaddr_t *reqaddr,
* 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 */

View File

@@ -15,7 +15,7 @@
* 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
@@ -260,6 +260,18 @@ isc_net_probeipv6(void);
* 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);

View File

@@ -15,7 +15,7 @@
* 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>
@@ -39,8 +39,10 @@ const struct in6_addr isc_net_in6addrloop = IN6ADDR_LOOPBACK_INIT;
#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) {
@@ -146,8 +148,102 @@ isc_net_probeipv4(void) {
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);
}

View File

@@ -15,7 +15,7 @@
* 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
@@ -247,6 +247,18 @@ isc_net_probeipv6(void);
* 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);

View File

@@ -15,7 +15,7 @@
* 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>
@@ -35,8 +35,10 @@ const struct in6_addr isc_net_in6addrany = IN6ADDR_ANY_INIT;
#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) {
@@ -140,8 +142,102 @@ isc_net_probeipv4(void) {
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);
}