diff --git a/lib/isc/include/isc/net.h b/lib/isc/include/isc/net.h index eda799c60d..7d7ad6b7e1 100644 --- a/lib/isc/include/isc/net.h +++ b/lib/isc/include/isc/net.h @@ -188,52 +188,23 @@ ISC_LANG_BEGINDECLS isc_result_t isc_net_probeipv4(void); /*%< - * Check if the system's kernel supports IPv4. + * Check if the IPv4 has been disabled. * * Returns: * *\li #ISC_R_SUCCESS IPv4 is supported. - *\li #ISC_R_NOTFOUND IPv4 is not supported. *\li #ISC_R_DISABLED IPv4 is disabled. - *\li #ISC_R_UNEXPECTED */ isc_result_t isc_net_probeipv6(void); /*%< - * Check if the system's kernel supports IPv6. + * Check if the IPv6 has been disabled. * * Returns: * *\li #ISC_R_SUCCESS IPv6 is supported. - *\li #ISC_R_NOTFOUND IPv6 is not supported. *\li #ISC_R_DISABLED IPv6 is disabled. - *\li #ISC_R_UNEXPECTED - */ - -isc_result_t -isc_net_probe_ipv6only(void); -/*%< - * Check if the system's kernel supports the IPV6_V6ONLY socket option. - * - * Returns: - * - *\li #ISC_R_SUCCESS the option is supported for both TCP and UDP. - *\li #ISC_R_NOTFOUND IPv6 itself or the option is not supported. - *\li #ISC_R_UNEXPECTED - */ - -isc_result_t -isc_net_probe_ipv6pktinfo(void); -/* - * Check if the system's kernel supports the IPV6_(RECV)PKTINFO socket option - * for UDP sockets. - * - * Returns: - * - * \li #ISC_R_SUCCESS the option is supported. - * \li #ISC_R_NOTFOUND IPv6 itself or the option is not supported. - * \li #ISC_R_UNEXPECTED */ void diff --git a/lib/isc/net.c b/lib/isc/net.c index adae0fef83..d30072b7f0 100644 --- a/lib/isc/net.c +++ b/lib/isc/net.c @@ -31,10 +31,6 @@ #include #include -#ifndef socklen_t -#define socklen_t unsigned int -#endif /* ifndef socklen_t */ - /*% * Definitions about UDP port range specification. This is a total mess of * portability variants: some use sysctl (but the sysctl names vary), some use @@ -89,245 +85,19 @@ #endif /* HAVE_SYSCTLBYNAME */ -static isc_once_t once_ipv6only = ISC_ONCE_INIT; -#ifdef __notyet__ -static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT; -#endif /* ifdef __notyet__ */ - -#ifndef ISC_CMSG_IP_TOS -#ifdef __APPLE__ -#define ISC_CMSG_IP_TOS 0 /* As of 10.8.2. */ -#else /* ! __APPLE__ */ -#define ISC_CMSG_IP_TOS 1 -#endif /* ! __APPLE__ */ -#endif /* ! ISC_CMSG_IP_TOS */ - -static isc_once_t once = 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 ipv6pktinfo_result = ISC_R_NOTFOUND; - -static isc_result_t -try_proto(int domain) { - int s; - isc_result_t result = ISC_R_SUCCESS; - - s = socket(domain, SOCK_STREAM, 0); - if (s == -1) { - switch (errno) { -#ifdef EAFNOSUPPORT - case EAFNOSUPPORT: -#endif /* ifdef EAFNOSUPPORT */ -#ifdef EPFNOSUPPORT - case EPFNOSUPPORT: -#endif /* ifdef EPFNOSUPPORT */ -#ifdef EPROTONOSUPPORT - case EPROTONOSUPPORT: -#endif /* ifdef EPROTONOSUPPORT */ -#ifdef EINVAL - case EINVAL: -#endif /* ifdef EINVAL */ - return ISC_R_NOTFOUND; - default: - UNEXPECTED_SYSERROR(errno, "socket()"); - return ISC_R_UNEXPECTED; - } - } - - if (domain == PF_INET6) { - struct sockaddr_in6 sin6; - unsigned int len; - - /* - * Check to see if IPv6 is broken, as is common on Linux. - */ - len = sizeof(sin6); - if (getsockname(s, (struct sockaddr *)&sin6, (void *)&len) < 0) - { - isc_log_write(ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - "retrieving the address of an IPv6 " - "socket from the kernel failed."); - isc_log_write(ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR, - "IPv6 is not supported."); - result = ISC_R_NOTFOUND; - } else { - if (len == sizeof(struct sockaddr_in6)) { - result = ISC_R_SUCCESS; - } else { - isc_log_write(ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, - ISC_LOG_ERROR, - "IPv6 structures in kernel and " - "user space do not match."); - isc_log_write(ISC_LOGCATEGORY_GENERAL, - ISC_LOGMODULE_SOCKET, - ISC_LOG_ERROR, - "IPv6 is not supported."); - result = ISC_R_NOTFOUND; - } - } - } - - (void)close(s); - - return result; -} - -static void -initialize_action(void) { - ipv4_result = try_proto(PF_INET); - ipv6_result = try_proto(PF_INET6); -} - -static void -initialize(void) { - isc_once_do(&once, initialize_action); -} +static isc_result_t ipv4_result = ISC_R_SUCCESS; +static isc_result_t ipv6_result = ISC_R_SUCCESS; isc_result_t isc_net_probeipv4(void) { - initialize(); return ipv4_result; } isc_result_t isc_net_probeipv6(void) { - initialize(); return ipv6_result; } -static void -try_ipv6only(void) { -#ifdef IPV6_V6ONLY - int s, on; -#endif /* ifdef IPV6_V6ONLY */ - 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 /* ifndef IPV6_V6ONLY */ - /* check for TCP sockets */ - s = socket(PF_INET6, SOCK_STREAM, 0); - if (s == -1) { - UNEXPECTED_SYSERROR(errno, "socket()"); - 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) { - UNEXPECTED_SYSERROR(errno, "socket()"); - 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; - } - - ipv6only_result = ISC_R_SUCCESS; - -close: - close(s); - return; -#endif /* IPV6_V6ONLY */ -} - -static void -initialize_ipv6only(void) { - isc_once_do(&once_ipv6only, try_ipv6only); -} - -#ifdef __notyet__ -static void -try_ipv6pktinfo(void) { - int s, on; - isc_result_t result; - int optname; - - result = isc_net_probeipv6(); - if (result != ISC_R_SUCCESS) { - ipv6pktinfo_result = result; - return; - } - - /* we only use this for UDP sockets */ - s = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); - if (s == -1) { - UNEXPECTED_SYSERROR(errno, "socket()"); - ipv6pktinfo_result = ISC_R_UNEXPECTED; - return; - } - -#ifdef IPV6_RECVPKTINFO - optname = IPV6_RECVPKTINFO; -#else /* ifdef IPV6_RECVPKTINFO */ - optname = IPV6_PKTINFO; -#endif /* ifdef IPV6_RECVPKTINFO */ - on = 1; - if (setsockopt(s, IPPROTO_IPV6, optname, &on, sizeof(on)) < 0) { - ipv6pktinfo_result = ISC_R_NOTFOUND; - goto close; - } - - ipv6pktinfo_result = ISC_R_SUCCESS; - -close: - close(s); - return; -} - -static void -initialize_ipv6pktinfo(void) { - isc_once_do(&once_ipv6pktinfo, try_ipv6pktinfo); -} -#endif /* ifdef __notyet__ */ - -isc_result_t -isc_net_probe_ipv6only(void) { - initialize_ipv6only(); - return ipv6only_result; -} - -isc_result_t -isc_net_probe_ipv6pktinfo(void) { -/* - * XXXWPK if pktinfo were supported then we could listen on :: for ipv6 and get - * the information about the destination address from pktinfo structure passed - * in recvmsg but this method is not portable and libuv doesn't support it - so - * we need to listen on all interfaces. - * We should verify that this doesn't impact performance (we already do it for - * ipv4) and either remove all the ipv6pktinfo detection code from above - * or think of fixing libuv. - */ -#ifdef __notyet__ - initialize_ipv6pktinfo(); -#endif /* ifdef __notyet__ */ - return ipv6pktinfo_result; -} - #if defined(USE_SYSCTL_PORTRANGE) #if defined(HAVE_SYSCTLBYNAME) static isc_result_t @@ -450,7 +220,6 @@ isc_net_getudpportrange(int af, in_port_t *low, in_port_t *high) { void isc_net_disableipv4(void) { - initialize(); if (ipv4_result == ISC_R_SUCCESS) { ipv4_result = ISC_R_DISABLED; } @@ -458,7 +227,6 @@ isc_net_disableipv4(void) { void isc_net_disableipv6(void) { - initialize(); if (ipv6_result == ISC_R_SUCCESS) { ipv6_result = ISC_R_DISABLED; } @@ -466,7 +234,6 @@ isc_net_disableipv6(void) { void isc_net_enableipv4(void) { - initialize(); if (ipv4_result == ISC_R_DISABLED) { ipv4_result = ISC_R_SUCCESS; } @@ -474,7 +241,6 @@ isc_net_enableipv4(void) { void isc_net_enableipv6(void) { - initialize(); if (ipv6_result == ISC_R_DISABLED) { ipv6_result = ISC_R_SUCCESS; } diff --git a/lib/ns/interfacemgr.c b/lib/ns/interfacemgr.c index 836ee05a85..5569cf3029 100644 --- a/lib/ns/interfacemgr.c +++ b/lib/ns/interfacemgr.c @@ -1085,12 +1085,9 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) { isc_interfaceiter_t *iter = NULL; bool scan_ipv4 = false; bool scan_ipv6 = false; - bool ipv6only = true; - bool ipv6pktinfo = true; isc_result_t result; isc_netaddr_t zero_address, zero_address6; ns_listenelt_t *le = NULL; - isc_sockaddr_t listen_addr; ns_interface_t *ifp = NULL; bool log_explicit = false; bool dolistenon; @@ -1116,64 +1113,6 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) { "no IPv4 interfaces found"); } - /* - * 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. - */ - if (scan_ipv6 && isc_net_probe_ipv6only() != ISC_R_SUCCESS) { - ipv6only = false; - log_explicit = true; - } - if (scan_ipv6 && isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) { - ipv6pktinfo = false; - log_explicit = true; - } - if (scan_ipv6 && ipv6only && ipv6pktinfo) { - for (le = ISC_LIST_HEAD(mgr->listenon6->elts); le != NULL; - le = ISC_LIST_NEXT(le, link)) - { - struct in6_addr in6a; - - if (!listenon_is_ip6_any(le)) { - continue; - } - - in6a = in6addr_any; - isc_sockaddr_fromin6(&listen_addr, &in6a, le->port); - - ifp = find_matching_interface(mgr, &listen_addr); - if (ifp != NULL) { - bool cont = interface_update_or_shutdown( - mgr, ifp, le, config); - if (cont) { - continue; - } - } - - isc_log_write(NS_LOGCATEGORY_NETWORK, - NS_LOGMODULE_INTERFACEMGR, ISC_LOG_INFO, - "listening on IPv6 " - "interfaces, port %u", - le->port); - result = interface_setup(mgr, &listen_addr, "", - &ifp, le, NULL); - if (result == ISC_R_SUCCESS) { - ifp->flags |= NS_INTERFACEFLAG_ANYADDR; - } else { - isc_log_write(NS_LOGCATEGORY_NETWORK, - NS_LOGMODULE_INTERFACEMGR, - ISC_LOG_ERROR, - "listening on all IPv6 " - "interfaces failed"); - } - /* Continue. */ - } - } - isc_netaddr_any(&zero_address); isc_netaddr_any6(&zero_address6); @@ -1253,7 +1192,6 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) { { int match; bool addr_in_use = false; - bool ipv6_wildcard = false; isc_sockaddr_t listen_sockaddr; isc_sockaddr_fromnetaddr(&listen_sockaddr, @@ -1279,16 +1217,6 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) { dolistenon = false; } - /* - * The case of "any" IPv6 address will require - * special considerations later, so remember it. - */ - if (family == AF_INET6 && ipv6only && ipv6pktinfo && - listenon_is_ip6_any(le)) - { - ipv6_wildcard = true; - } - ifp = find_matching_interface(mgr, &listen_sockaddr); if (ifp != NULL) { bool cont = interface_update_or_shutdown( @@ -1298,10 +1226,6 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) { } } - if (ipv6_wildcard) { - continue; - } - if (log_explicit && family == AF_INET6 && listenon_is_ip6_any(le)) {