<< Mein Tagebuch | Home | Warum geht es so langsam mit IPv6 vorwärts? >> | Kontakt

Java and IPv6 on BSD

Preface

More and more sites use the new internet protocol IPv6. Therefore it is also necessary to enable IPv6 on servers, written in Java language. Although current Java runtime environments claim to support IPv6 there are still errors observed. All investigations are made on FreeBSD-7.0-STABLE, but from reading the current sources I expect the same behaviour on all unix like systems. Java for Windows© has a different implementation.

IPv6 socket model (for server sockets)

In the current transition phase we have in most cases dual tcp/ip stacks able to carry IPv4 and IPv6 packets. So we distinguish between (server) sockets bound to address family AF_INET and AF_INET6. The ability to receive IPv4 packets on sockets bound to the AF_INET6 wildcard address (INADDR_ANY) is determined by socket option IPV6_V6ONLY. For details see RFC3493. The following table summarizes the influence of the mentioned socket option.
familyaddressIPV6_V6ONLYIPv4IPv6
AF_INETINADDR_ANY0X 
AF_INETIPv40X 
AF_INETINADDR_ANY1X 
AF_INETIPv41X 
AF_INET6INADDR_ANY0x (IPv4-mapped address)X
AF_INET6IPv60 X
AF_INET6INADDR_ANY1 X
AF_INET6IPv61 X

Note: The current FreeBSD versions ship with a global setting, that sets the default to IPV6_V6ONLY=1, with OpenBSD IPv6 sockets are always IPv6-only.

Using IPv6 in Java

I cite the Networking IPv6 User Guide: "Using IPv6 in Java is easy; it is transparent and automatic. Unlike in many other languages, no porting is necessary. In fact, there is no need to even recompile the source files." and further "The Java networking stack will first check whether IPv6 is supported on the underlying OS. If IPv6 is supported, it will try to use the IPv6 stack. More specifically, on dual-stack systems it will create an IPv6 socket."

A further statement made in the networking guide is "A general property of a dual-stack node is that an IPv6 socket can communicate both with an IPv4 and IPv6 peer at the transport layer (TCP or UDP)". This is wrong, because the condition is missing: , if the socket is bound to the INADDR_ANY wildcard address AND the socket option allows the use of mapped IPv4 addresses (IPV6_V6ONLY=0). The Java runtime does not set the socket option, so the behaviour is operating system dependent.

java.net.preferIPv4Stack

It is possible to set the system property java.net.preferIPv4Stack to true. In that case only IPv4 sockets are created and no IPv6 communication is possible. So in reality it does not set any preferences, it toggles between an exclusive IPv6 and an exclusive IPv4 stack.

Consequences

Please read again "on dual-stack systems it will create an IPv6 socket". That means that there is alyways an IPv6 socket created, independed from desired address family. Of course such a socket can not bind to an IPv4 address. Thats the reason for many users receiving a java.net.BindException: Can't assign requested address when enabling IPv6 on a machine.

An IPv6 enabled java application can not bind to an IPv4 address and only under the condition, that the socket is bound to INADDR_ANY and IPV6_V6ONLY=0 it is able to receive IPv4 packets!

To make it worse, it is not even possible to bind to localhost. With the default settings the name localhost is resolved to the IPv4 address and of course binding of that IPv4 address to an AF_INET6 socket fails.

My conclusion

It is very difficult or impossible to use the current (1.6.0) Java implementation for server services if they should listen on IPv4 and IPv6 addresses. With many BSD's default settings it is not even possible to bind to a combined IPv4/IPv6 wildcard address.

The current Sun Java implementation should be changed in a way, that the socket is created with the right address family after the bind address has been determined.

To use Tomcat with IPv6 the native connector can be used. It does not show the described flaws.

Test results

The statements above can be derived from official Java documentation, but I believe not everybody reads them in detail and sees immediately where the error is to search. The same happened to me, so I made some tests first. Here you can see the results for the current JDK on FreeBSD-7.0. JDK1.4.2 and diablo-JDK1.5.0 have no working IPv6 support.


version address result bound address/message bind type V6ONLY preferIPv4Stack preferIPv6Addresses
1.6.0_03-p4 INADDR_ANY OK 0.0.0.0/0.0.0.0:10101 (Inet4Address) 6 true false false
1.6.0_03-p4 127.0.0.1 ERR java.net.BindException: Can't assign requested address (/127.0.0.1) - true false false
1.6.0_03-p4 ::1 OK /0:0:0:0:0:0:0:1:10101 (Inet6Address) 6 true false false
1.6.0_03-p4 localhost ERR java.net.BindException: Can't assign requested address (localhost/127.0.0.1) - true false false
1.6.0_03-p4 INADDR_ANY OK ::/0:0:0:0:0:0:0:0:10101 (Inet6Address) 6 true false true
1.6.0_03-p4 127.0.0.1 ERR java.net.BindException: Can't assign requested address (/127.0.0.1) - true false true
1.6.0_03-p4 ::1 OK /0:0:0:0:0:0:0:1:10101 (Inet6Address) 6 true false true
1.6.0_03-p4 localhost OK localhost/0:0:0:0:0:0:0:1:10101 (Inet6Address) 6 true false true
1.6.0_03-p4 INADDR_ANY OK 0.0.0.0/0.0.0.0:10101 (Inet4Address) 4 true true false
1.6.0_03-p4 127.0.0.1 OK /127.0.0.1:10101 (Inet4Address) 4 true true false
1.6.0_03-p4 ::1 ERR java.net.SocketException: Protocol family unavailable (/0:0:0:0:0:0:0:1) - true true false
1.6.0_03-p4 localhost OK localhost/127.0.0.1:10101 (Inet4Address) 4 true true false
1.6.0_03-p4 INADDR_ANY OK 0.0.0.0/0.0.0.0:10101 (Inet4Address) 4 true true true
1.6.0_03-p4 127.0.0.1 OK /127.0.0.1:10101 (Inet4Address) 4 true true true
1.6.0_03-p4 ::1 ERR java.net.SocketException: Protocol family unavailable (/0:0:0:0:0:0:0:1) - true true true
1.6.0_03-p4 localhost OK localhost/127.0.0.1:10101 (Inet4Address) 4 true true true
1.6.0_03-p4 INADDR_ANY OK 0.0.0.0/0.0.0.0:10101 (Inet4Address) 46 false false false
1.6.0_03-p4 127.0.0.1 OK /127.0.0.1:10101 (Inet4Address) 4 false false false
1.6.0_03-p4 ::1 OK /0:0:0:0:0:0:0:1:10101 (Inet6Address) 6 false false false
1.6.0_03-p4 localhost OK localhost/127.0.0.1:10101 (Inet4Address) 4 false false false
1.6.0_03-p4 INADDR_ANY OK ::/0:0:0:0:0:0:0:0:10101 (Inet6Address) 46 false false true
1.6.0_03-p4 127.0.0.1 OK /127.0.0.1:10101 (Inet4Address) 4 false false true
1.6.0_03-p4 ::1 OK /0:0:0:0:0:0:0:1:10101 (Inet6Address) 6 false false true
1.6.0_03-p4 localhost OK localhost/0:0:0:0:0:0:0:1:10101 (Inet6Address) 6 false false true
1.6.0_03-p4 INADDR_ANY OK 0.0.0.0/0.0.0.0:10101 (Inet4Address) 4 false true false
1.6.0_03-p4 127.0.0.1 OK /127.0.0.1:10101 (Inet4Address) 4 false true false
1.6.0_03-p4 ::1 ERR java.net.SocketException: Protocol family unavailable (/0:0:0:0:0:0:0:1) - false true false
1.6.0_03-p4 localhost OK localhost/127.0.0.1:10101 (Inet4Address) 4 false true false
1.6.0_03-p4 INADDR_ANY OK 0.0.0.0/0.0.0.0:10101 (Inet4Address) 4 false true true
1.6.0_03-p4 127.0.0.1 OK /127.0.0.1:10101 (Inet4Address) 4 false true true
1.6.0_03-p4 ::1 ERR java.net.SocketException: Protocol family unavailable (/0:0:0:0:0:0:0:1) - false true true
1.6.0_03-p4 localhost OK localhost/127.0.0.1:10101 (Inet4Address) 4 false true true



Kommentar hinzufügen Trackback senden