Alan Bateman wrote:
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.
Are you referring to the Linux behaviour where all applications bound to
the same port number (and interface)
receive packets from all groups that have been joined on the same
interface? That is certainly a good example
of an implementation choice, that Java cannot work-around or hide, in
the goal towards transparency.
On the general question of IPv4 mapped addresses, obviously the
intention was that applications (and
particularly Java applications) should be able to handle IPv4 and IPv6
sockets transparently,
and it's a real pity that some OS implementations haven't fully
supported this.
In general, I guess our first preference would always be to try and
workaround these inconsistencies
in the Java "glue" layer, but if that isn't possible, then we have to
find some way to create or establish
sockets as being IPv4 only, or IPv6 only.
- Michael.