From 5b273b5726d98d98d53420fdd6d7b899ca92c0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 20 Aug 2024 11:48:04 +0200 Subject: [PATCH 1/5] Assume IPV6_V6ONLY is universally available In 2024, IPV6_V6ONLY socket option is either available or the operating system is just not going to be supported. --- lib/isc/include/isc/net.h | 12 ------- lib/isc/net.c | 68 --------------------------------------- lib/ns/interfacemgr.c | 9 ++---- 3 files changed, 2 insertions(+), 87 deletions(-) diff --git a/lib/isc/include/isc/net.h b/lib/isc/include/isc/net.h index eda799c60d..322584c3af 100644 --- a/lib/isc/include/isc/net.h +++ b/lib/isc/include/isc/net.h @@ -211,18 +211,6 @@ isc_net_probeipv6(void); *\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); /* diff --git a/lib/isc/net.c b/lib/isc/net.c index adae0fef83..d0ab37316b 100644 --- a/lib/isc/net.c +++ b/lib/isc/net.c @@ -89,7 +89,6 @@ #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__ */ @@ -106,7 +105,6 @@ 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 @@ -200,66 +198,6 @@ isc_net_probeipv6(void) { 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) { @@ -305,12 +243,6 @@ initialize_ipv6pktinfo(void) { } #endif /* ifdef __notyet__ */ -isc_result_t -isc_net_probe_ipv6only(void) { - initialize_ipv6only(); - return ipv6only_result; -} - isc_result_t isc_net_probe_ipv6pktinfo(void) { /* diff --git a/lib/ns/interfacemgr.c b/lib/ns/interfacemgr.c index 836ee05a85..7902b1a0da 100644 --- a/lib/ns/interfacemgr.c +++ b/lib/ns/interfacemgr.c @@ -1085,7 +1085,6 @@ 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; @@ -1124,15 +1123,11 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) { * 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) { + if (scan_ipv6 && ipv6pktinfo) { for (le = ISC_LIST_HEAD(mgr->listenon6->elts); le != NULL; le = ISC_LIST_NEXT(le, link)) { @@ -1283,7 +1278,7 @@ do_scan(ns_interfacemgr_t *mgr, bool verbose, bool config) { * The case of "any" IPv6 address will require * special considerations later, so remember it. */ - if (family == AF_INET6 && ipv6only && ipv6pktinfo && + if (family == AF_INET6 && ipv6pktinfo && listenon_is_ip6_any(le)) { ipv6_wildcard = true; From e85399b1c0a355e7b68a9b2b38a2fdf7b969e5bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 20 Aug 2024 11:53:07 +0200 Subject: [PATCH 2/5] Assume that IPv4 and IPv6 is always available In 2024, it is reasonable to assume that IPv4 and IPv6 is always available on a socket() level. We still keep the option to enable or disable each IP version individually, as the routing might be broken or undesirable for one of the versions. --- lib/isc/include/isc/net.h | 8 +--- lib/isc/net.c | 91 +-------------------------------------- 2 files changed, 4 insertions(+), 95 deletions(-) diff --git a/lib/isc/include/isc/net.h b/lib/isc/include/isc/net.h index 322584c3af..7d04bfe6b0 100644 --- a/lib/isc/include/isc/net.h +++ b/lib/isc/include/isc/net.h @@ -188,27 +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 diff --git a/lib/isc/net.c b/lib/isc/net.c index d0ab37316b..8f73185696 100644 --- a/lib/isc/net.c +++ b/lib/isc/net.c @@ -101,100 +101,17 @@ static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT; #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 ipv4_result = ISC_R_SUCCESS; +static isc_result_t ipv6_result = ISC_R_SUCCESS; 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); -} - isc_result_t isc_net_probeipv4(void) { - initialize(); return ipv4_result; } isc_result_t isc_net_probeipv6(void) { - initialize(); return ipv6_result; } @@ -382,7 +299,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; } @@ -390,7 +306,6 @@ isc_net_disableipv4(void) { void isc_net_disableipv6(void) { - initialize(); if (ipv6_result == ISC_R_SUCCESS) { ipv6_result = ISC_R_DISABLED; } @@ -398,7 +313,6 @@ isc_net_disableipv6(void) { void isc_net_enableipv4(void) { - initialize(); if (ipv4_result == ISC_R_DISABLED) { ipv4_result = ISC_R_SUCCESS; } @@ -406,7 +320,6 @@ isc_net_enableipv4(void) { void isc_net_enableipv6(void) { - initialize(); if (ipv6_result == ISC_R_DISABLED) { ipv6_result = ISC_R_SUCCESS; } From 34a9a9a6be96ab089a909d943a623f73ead4ccf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 20 Aug 2024 11:57:35 +0200 Subject: [PATCH 3/5] Assume universal availability of socklen_t The SUSv2 defines accept(..., socklen_t), so we can safely require socklen_t to be universally available. --- lib/isc/net.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/isc/net.c b/lib/isc/net.c index 8f73185696..90989e08f3 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 From 95a7419c2a8f31f020c57a0883aa08456dae3ccf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 20 Aug 2024 12:12:47 +0200 Subject: [PATCH 4/5] Remove the incomplete code for IPv6 pktinfo The code that listens on individual interfaces is now stable and doesn't require any changes. The code that would bind to IPv6 wildcard address and then use IPv6 pktinfo structure to get the source address is not going to be completed, so it's better to just remove the dead cruft. --- lib/isc/include/isc/net.h | 13 ------- lib/isc/net.c | 67 ------------------------------------ lib/ns/interfacemgr.c | 71 --------------------------------------- 3 files changed, 151 deletions(-) diff --git a/lib/isc/include/isc/net.h b/lib/isc/include/isc/net.h index 7d04bfe6b0..7d7ad6b7e1 100644 --- a/lib/isc/include/isc/net.h +++ b/lib/isc/include/isc/net.h @@ -207,19 +207,6 @@ isc_net_probeipv6(void); *\li #ISC_R_DISABLED IPv6 is disabled. */ -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 isc_net_disableipv4(void); diff --git a/lib/isc/net.c b/lib/isc/net.c index 90989e08f3..8d65e1bb98 100644 --- a/lib/isc/net.c +++ b/lib/isc/net.c @@ -85,10 +85,6 @@ #endif /* HAVE_SYSCTLBYNAME */ -#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. */ @@ -99,7 +95,6 @@ static isc_once_t once_ipv6pktinfo = ISC_ONCE_INIT; static isc_result_t ipv4_result = ISC_R_SUCCESS; static isc_result_t ipv6_result = ISC_R_SUCCESS; -static isc_result_t ipv6pktinfo_result = ISC_R_NOTFOUND; isc_result_t isc_net_probeipv4(void) { @@ -111,68 +106,6 @@ isc_net_probeipv6(void) { return ipv6_result; } -#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_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 diff --git a/lib/ns/interfacemgr.c b/lib/ns/interfacemgr.c index 7902b1a0da..5569cf3029 100644 --- a/lib/ns/interfacemgr.c +++ b/lib/ns/interfacemgr.c @@ -1085,11 +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 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; @@ -1115,60 +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_ipv6pktinfo() != ISC_R_SUCCESS) { - ipv6pktinfo = false; - log_explicit = true; - } - if (scan_ipv6 && 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); @@ -1248,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, @@ -1274,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 && 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( @@ -1293,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)) { From c18bb5f1f22bdff97e2f292ff6039fb453f53073 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Sur=C3=BD?= Date: Tue, 20 Aug 2024 12:15:05 +0200 Subject: [PATCH 5/5] Remove unused definition of ISC_CMSG_IP_TOS The #define was used before, but we forgot to clean it up when we removed support for dscp. --- lib/isc/net.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/lib/isc/net.c b/lib/isc/net.c index 8d65e1bb98..d30072b7f0 100644 --- a/lib/isc/net.c +++ b/lib/isc/net.c @@ -85,14 +85,6 @@ #endif /* HAVE_SYSCTLBYNAME */ -#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_result_t ipv4_result = ISC_R_SUCCESS; static isc_result_t ipv6_result = ISC_R_SUCCESS;