Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Re: IPv4 socket bind using IPv6 socket on openjdk6 breaks udp send

3 views
Skip to first unread message

Matthias Andree

unread,
Jun 27, 2011, 7:17:01 AM6/27/11
to
Am 25.06.2011 13:28, schrieb Steven Hartland:
>
> ----- Original Message ----- From: "Matthias Andree"
> <matthia...@gmx.de>
>
> I'm adding back in -java as based on you comments it may well be
> something in the jdk passing invalid values down to the kernel
> syscall.
>
>>> The socket bind works fine and the packets sent to the server arrive
>>> and are processed by the app but when it tries to reply using
>>> send the result is:-
>>> java.io.IOException: Invalid argument
>>> at java.net.PlainDatagramSocketImpl.send(Native Method)
>>> at java.net.DatagramSocket.send(DatagramSocket.java:629)
>>>
>>> using truss we see the following:-
>>> socket(PF_INET6,SOCK_DGRAM,0) = 20 (0x14)
>>> setsockopt(0x14,0x29,0x1b,0x7ffffedf0318,0x4,0x0) = 0 (0x0)
>>> setsockopt(0x14,0xffff,0x20,0x7ffffedf031c,0x4,0x0) = 0 (0x0)
>>> bind(20,{ AF_INET6 [3800::10:0:0:0]:20736 },28) = 0 (0x0)
>>> ..
>>> sendto(20,"\M^?\M^?\M^?\M^?I\aMultiplay :: "...,82,0x0,{ AF_INET6
>>> [3800::10:0:0:0]:20736 },0x1c) ERR#22 'Invalid argument'
>>
>> You're trying to send to your own address, but you're likely not using
>> the loopback interface for that. Is that permitted by your firewall
>> configuration and routing?
>
> No I'm not its replying to the sender.

Yes you are, check your trace: The sendto address and port are the same
as the bound address.

> In the java code we have:-
> socket.send( new DatagramPacket( data, data.length,
> src.getSocketAddress() ) );
> Where src is the src packet. This works fine on IPv4 only machines and
> when the jdk is told to use only IPv4 stack. So its not a problem with
> the java code itself but could well be an issue with the

What data type is it?

>
>>
>>> sockstat shows it binding correctly
>>> root java 894 21 tcp4 85.236.109.212:25675 *:*
>>
>> This is unrelated, as it has fd #21 not #20 as in the socket/bind/sendto
>> calls. You've quoted the wrong line from sockstat output.
>
> Oops sorry cut and paste error (wrong line) heres the correct line.
> root java 894 20 udp4 85.236.109.212:25675 *:*

While a datagram socket, it does not match the socket()/bind() above.

An INET6-domain datagram socket would be listed as udp6 here. Are you
sure you're tracing the right VM and are looking at the right thread?

If so, is the incriminated traffic actually going through socket #20?

Is src.getSocketAddress() actually returning an IPv6 address?
SocketAddress is an abstract class. For my lack of Java knowledge: are
there any automatic type promotions on the Java side?

What's the Java code for binding to the socket and fetching the query
packet?

> The jvm automatically sets this on all sockets for compatibility for
> this exact reason. I'm not rulling out an issue with the IPv6 -> v4
> routing in the kernel though.

That is prohibited, so there isn't IPv6 -> IPv4 routing. All IPv6
traffic remains in the IPv6 domain.

>> Are you sure that's what you seeing? It's not a match for what you give
>> above, but anyways it's an implementation artifact because the tcp code
>> for v4 and v6 used to be shared and the udp code separate.
>
> Thats not how the jdk works, its ment to be 100% transparent but isn't.

You mean the JRE.

>> It is best to set up one IPv4 and one IPv6 listening socket.
>
> I don't believe there is any way to do this in java it either uses the
> IPv4 stack only or the IPv6 stack only hence relies on the kernel
> routing IPv4 packets through the IPv6 stack.
>
> Thats the reason the jdk explicitly enables this for all the ports it
> creates, which was added as a back port of the jdk7 fixes which can
> be seen here:-
> http://www.freebsd.org/cgi/cvsweb.cgi/ports/java/openjdk6/files/patch-set
>
>> Check the URL above, perhaps that helps your understanding a bit. I
>> presume 3800::10:0:0:0 is your server?
>
> Not that I'm aware of, here's the output from ifconfig if anyone can
> tell me different, as I'm new to IPv6 and don't follow how its mapped
> yet.
>
> ifconfig
> igb0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
>
> options=1bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4>
>
> ether 00:25:90:2c:3c:b0
> inet 85.236.109.212 netmask 0xffffff00 broadcast 85.236.109.255
> inet6 fe80::225:90ff:fe2c:3cb0%igb0 prefixlen 64 scopeid 0x1
> inet6 2001:4db0:20:2::1337 prefixlen 64 nd6

The 2001:something is your local address. If you bind to 3800::
something that won't work. You couldn't bind an IPv4 address of
10.9.8.7 on this interface either.

> igb1: flags=8802<BROADCAST,SIMPLEX,MULTICAST> metric 0 mtu 1500
>
> options=1bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4>
>
> ether 00:25:90:2c:3c:b1
> media: Ethernet autoselect (1000baseSX <full-duplex>)
> status: active

This iface has no addresses at IP level at all.

> lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
> options=3<RXCSUM,TXCSUM>
> inet 127.0.0.1 netmask 0xff000000
> inet6 ::1 prefixlen 128
> inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3 nd6
> options=3<PERFORMNUD,ACCEPT_RTADV>

Other than that, looks reasonable. There are link-local IPv6 addresses
on igb0 and lo0, and there is a global IPv6 address on igb0. There is a
routable IPv4 address on igb0, and the loopback address on lo0. That's
OK, but an IPv6 bind could only ever use an address from
2001:4db0:20:2::/64, not 3800.

Are you sure you're using the right address in bind()? It specifies the
local sender address for transmitted datagrams...


_______________________________________________
freebs...@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-java
To unsubscribe, send any mail to "freebsd-java...@freebsd.org"

Steven Hartland

unread,
Jun 27, 2011, 7:34:57 AM6/27/11
to
----- Original Message -----
From: "Matthias Andree" <matthia...@gmx.de>
>> No I'm not its replying to the sender.
>
> Yes you are, check your trace: The sendto address and port are the same
> as the bound address.

This is a bug in truss it seems, Bjoern said he's gonna have a look at
it. Doesn't matter what you bind to it always reports this value in the
truss output.

>> In the java code we have:-
>> socket.send( new DatagramPacket( data, data.length,
>> src.getSocketAddress() ) );
>> Where src is the src packet. This works fine on IPv4 only machines and
>> when the jdk is told to use only IPv4 stack. So its not a problem with
>> the java code itself but could well be an issue with the
>
> What data type is it?

All mute as the Bjoern found and fixed the issue, it was a bug in the
kernel fixed by:-
http://svnweb.freebsd.org/base?view=revision&revision=220463

>> Oops sorry cut and paste error (wrong line) heres the correct line.
>> root java 894 20 udp4 85.236.109.212:25675 *:*
>
> While a datagram socket, it does not match the socket()/bind() above.
>
> An INET6-domain datagram socket would be listed as udp6 here. Are you
> sure you're tracing the right VM and are looking at the right thread?

Again, truss isn't showing the correct results, confused me too ;-)

Possibly another bug in sockstat / netstat as well, when the socket is a
IPv6 socket bound to an IPv4 address maybe it should indicate this e.g.
udp6-4 instead of either udp4 or udp6; alternatively maybe udp6 + a IPv4
address is enough to indicate this, but that could cause confusion.

Thanks for looking at this, appreciated :)

Regards
Steve

================================================
This e.mail is private and confidential between Multiplay (UK) Ltd. and the person or entity to whom it is addressed. In the event of misdirection, the recipient is prohibited from using, copying, printing or otherwise disseminating it or any information contained in it.

In the event of misdirection, illegible or incomplete transmission please telephone +44 845 868 1337
or return the E.mail to postm...@multiplay.co.uk.

Matthias Andree

unread,
Jun 27, 2011, 8:18:05 AM6/27/11
to
Just so we have pointers in the public archives: alternatives to truss
are strace (in ports) and ktrace/kdump; and to obtain socket statistics,
try lsof (from ports, too) possibly with -i and optionally -n and/or -P
option.
0 new messages