maintainer-feedback requested: [Bug 274964] java/openjdk21 Dual-stack IPv4/IPv6 applications no longer work with sysctl net.inet6.ip6.v6only=1

From: <bugzilla-noreply_at_freebsd.org>
Date: Wed, 08 Nov 2023 14:35:18 UTC
Bugzilla Automation <bugzilla@FreeBSD.org> has asked freebsd-java (Nobody)
<java@FreeBSD.org> for maintainer-feedback:
Bug 274964: java/openjdk21 Dual-stack IPv4/IPv6 applications no longer work
with sysctl net.inet6.ip6.v6only=1
https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=274964



--- Description ---
We have a Tomcat-based application (with Tomcat configured to use the Apache
Portable Runtime) that listens on both IPv4 and IPv6. Java is invoked with
-Djava.net.preferIPv4Stack=false to enable IPv6 support.

This application works perfectly on FreeBSD with OpenJDK 17 and accepts both
IPv4 and IPv6 connections, even though the FreeBSD 13.2-RELEASE-p3 host has the
default sysctl net.inet6.ip6.v6only=1 setting. The exact same application and
configuration fails to listen to IPv4 clients when deployed with OpenJDK 21.

We have another JVM server application, this time created using Scala HTTP4s
(https://http4s.org/), and thus not using the Apache Portable Runtime. This
application (again run with -Djava.net.preferIPv4Stack=false) exhibits the
exact same behaviour: with OpenJDK 17, both IPv4 and IPv6 clients can connect;
with OpenJDK 21, only IPv6 clients can connect. The problem is thus not
specific to the Apache Portable Runtime.

Both applications work as expected with OpenJDK 21 if the FreeBSD host has
sysctl net.inet6.ip6.v6only set to 0. However, setting sysctl
net.inet6.ip6.v6only=0 is not required using OpenJDK 17.

Both applications are running in FreeBSD jails, but I do not believe that is
likely a factor.

I am not sure whether I am looking at the relevant code or not, but the FreeBSD
OpenJDK 17 port has BSD-specific code in
src/java.base/unix/native/libnet/PlainSocketImpl.c that appears to set the
IPV6_V6ONLY flag to 0 when opening a socket if IPv4 is available. See
https://github.com/battleblow/jdk17u/blob/373026a81f5000e6df990eb9faec37f518ee7
11e/src/java.base/unix/native/libnet/PlainSocketImpl.c#L184

The networking code appears to have been re-arranged in OpenJDK 21 (relative to
OpenJDK 17), so that particular source file no longer exists. However, a search
for IPV6_V6ONLY in the jdk21u GitHub repository does not reveal any plausible
direct equivalent code. This explicit enabling of IPV6_V6ONLY when opening a
socket in OpenJDK 17 may perhaps be the reason why OpenJDK 17 works for us
without sysctl net.inet6.ip6.v6only=0 but OpenJDK 21 doesn’t.

Note that we also tested the FreeBSD OpenJDK 18, 19, and 20 ports. Like OpenJDK
21, these also fail to work with our dual-stack applications.

This issue is almost certainly related to the old OpenJDK 11 bug #239890, but I
am guessing that bug was obsolete as of OpenJDK 17, since the described
scenario does seem to work there.