MulticastSocket(group, port) problems with bind() with IPv6 enabled
Alan Bateman
Alan.Bateman at Sun.COM
Fri Dec 5 07:10:22 PST 2008
Pekka Savola wrote:
> Hi,
>
> I've looked through the Sun bug database and AFAICS this is not
> listed. I've also looked through the latest source code to see if
> this is addressed [1], but apparently not. I'm trying to find a way
> to get this addressed.
>
> When you create a MulticastSocket(new InetSocketAddress(group, port))
> with an IPv4 address as a string in 'group' on an IPv6-enabled system,
> the socket is created as PF_INET6. This results in mapping the
> address to mapped address format (e.g. "::ffff:233.1.2.3").
>
> This also results in a bind() system call to the ipv6 mapped address.
>
> On Linux, this fails due to EADDRNOTAVAIL; the kernel does not support
> IPv4 multicast addresses through PF_INET6 socket. In any case, Java
> doing this is not very portable -- there is huge variance on how
> various implementations treat the mapped addresses; Linux kernel
> implementations are not going to change [2] and as a result,
> applications using MulticastSocket when an ipv4 group is specified on
> IPv6 systems is failing.
>
> The problems here were already identified 7+ years ago (e.g. an IETF
> discussion [3]).
>
> If you don't specify the group, this results in a PF_INET6 socket with
> wildcard bind ("::"), and works to a degree but this has other,
> already known, problems when multiple receivers exist on the saem system.
>
> What needs to, IMHO, happen is that at least when creating
> MulticastSocket with a specified group, Java implementation should
> check whether the address is IPv4 or IPv6, and create a PF_INET6 or
> PF_INET socket, instead of always creating PF_INET6 socket if IPv6 is
> enabled.
>
> Another thing that could be useful would be to modify socket creation
> mechanisms so that you could specify whether you want an ipv4 or ipv6
> socket if you know which one you need.
For the specific problem at hand then I assume that running with
-Djava.net.preferIPv4Stack=true fixes the problem.
More generally, it can be hard to develop a portable multicasting
application. Typically, one binds to the wildcard address and then joins
the multicast group. This is usually preferable because it is not
possible to receive multicast datagrams on some systems when bound to a
specific local address or a multicast address. The issues with
interference that you allude to on Linux are indeed a pain. I'm
surprised there isn't a parameter or option to configure this behavior
(Michael might want to jump in here as he was researching this specific
topic a few months ago). 4701650 also touches on this topic.
As regards the suggestion to choose the protocol family at creation time
- some of that is already in place for jdk7 as it was needed to add
multicast support to NIO (and specifically because it is not portable to
join IPv4 multicast groups with an IPv6 socket). When creating a
DatagramChannel you can specify the protocol family and this should
correspond to the address type of the multicast groups that you join.
Classic networking needs a bit of work to allow mixing of IPv4 and IPv6
sockets in the same VM. Chris or Michael might want to say more about that.
-Alan.
More information about the net-dev
mailing list