Avoid letting ipv6 addresses join ipv4 groups (#11015)
Motivation: #10995 when `io.netty.channel.unix.Socket` is ipv6 and join a multicast group with ipv4 address will cause `io.netty.channel.ChannelException: setsockopt() failed: Invalid argument` (at least in `Linux centos.dev 4.18.0-240.10.1.el8_3.x86_64 #1 SMP Mon Jan 18 17:05:51 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux`) Modification: check if target group address is ipv6 before call `io.netty.channel.epoll.LinuxSocket#joinGroup(java.net.InetAddress, java.net.NetworkInterface, java.net.InetAddress)` I'm not sure if this modification is currect, but i checked source code of java NIO ``` Java_sun_nio_ch_Net_canJoin6WithIPv4Group0(JNIEnv* env, jclass cl) { #if defined(__APPLE__) /* IPV6_ADD_MEMBERSHIP can be used to join IPv4 multicast groups */ return JNI_TRUE; #else /* IPV6_ADD_MEMBERSHIP cannot be used to join IPv4 multicast groups */ return JNI_FALSE; #endif } ``` seems ipv6 address can't join ipv4 group except osx Result: test on `Linux 3.10.0-514.el7.x86_64 #1 SMP Tue Nov 22 16:42:41 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux` exception ` setsockopt() failed: Invalid argument` has fixed Fixes #10995
This commit is contained in:
parent
b29df0f87a
commit
dbee8c9b89
@ -35,7 +35,7 @@ public abstract class AbstractDatagramTest extends AbstractComboTestsuiteTest<Bo
|
||||
|
||||
@Override
|
||||
protected List<TestsuitePermutation.BootstrapComboFactory<Bootstrap, Bootstrap>> newFactories() {
|
||||
return SocketTestPermutation.INSTANCE.datagram(internetProtocolFamily());
|
||||
return SocketTestPermutation.INSTANCE.datagram(socketInternetProtocalFamily());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -45,7 +45,7 @@ public abstract class AbstractDatagramTest extends AbstractComboTestsuiteTest<Bo
|
||||
}
|
||||
|
||||
protected SocketAddress newSocketAddress() {
|
||||
switch (internetProtocolFamily()) {
|
||||
switch (socketInternetProtocalFamily()) {
|
||||
case IPv4:
|
||||
return new InetSocketAddress(NetUtil.LOCALHOST4, 0);
|
||||
case IPv6:
|
||||
@ -58,4 +58,12 @@ public abstract class AbstractDatagramTest extends AbstractComboTestsuiteTest<Bo
|
||||
protected InternetProtocolFamily internetProtocolFamily() {
|
||||
return InternetProtocolFamily.IPv4;
|
||||
}
|
||||
|
||||
protected InternetProtocolFamily groupInternetProtocalFamily() {
|
||||
return internetProtocolFamily();
|
||||
}
|
||||
|
||||
protected InternetProtocolFamily socketInternetProtocalFamily() {
|
||||
return internetProtocolFamily();
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ public class DatagramMulticastTest extends AbstractDatagramTest {
|
||||
public void testMulticast(Bootstrap sb, Bootstrap cb) throws Throwable {
|
||||
NetworkInterface iface = multicastNetworkInterface();
|
||||
Assume.assumeNotNull("No NetworkInterface found that supports multicast and " +
|
||||
internetProtocolFamily(), iface);
|
||||
socketInternetProtocalFamily(), iface);
|
||||
|
||||
MulticastTestHandler mhandler = new MulticastTestHandler();
|
||||
|
||||
@ -156,11 +156,11 @@ public class DatagramMulticastTest extends AbstractDatagramTest {
|
||||
|
||||
@Override
|
||||
protected List<TestsuitePermutation.BootstrapComboFactory<Bootstrap, Bootstrap>> newFactories() {
|
||||
return SocketTestPermutation.INSTANCE.datagram(internetProtocolFamily());
|
||||
return SocketTestPermutation.INSTANCE.datagram(socketInternetProtocalFamily());
|
||||
}
|
||||
|
||||
private InetSocketAddress newAnySocketAddress() throws UnknownHostException {
|
||||
switch (internetProtocolFamily()) {
|
||||
switch (socketInternetProtocalFamily()) {
|
||||
case IPv4:
|
||||
return new InetSocketAddress(InetAddress.getByName("0.0.0.0"), 0);
|
||||
case IPv6:
|
||||
@ -174,7 +174,7 @@ public class DatagramMulticastTest extends AbstractDatagramTest {
|
||||
Enumeration<InetAddress> addresses = iface.getInetAddresses();
|
||||
while (addresses.hasMoreElements()) {
|
||||
InetAddress address = addresses.nextElement();
|
||||
if (internetProtocolFamily().addressType().isAssignableFrom(address.getClass())) {
|
||||
if (socketInternetProtocalFamily().addressType().isAssignableFrom(address.getClass())) {
|
||||
return new InetSocketAddress(address, 0);
|
||||
}
|
||||
}
|
||||
@ -189,13 +189,13 @@ public class DatagramMulticastTest extends AbstractDatagramTest {
|
||||
Enumeration<InetAddress> addresses = iface.getInetAddresses();
|
||||
while (addresses.hasMoreElements()) {
|
||||
InetAddress address = addresses.nextElement();
|
||||
if (internetProtocolFamily().addressType().isAssignableFrom(address.getClass())) {
|
||||
if (socketInternetProtocalFamily().addressType().isAssignableFrom(address.getClass())) {
|
||||
MulticastSocket socket = new MulticastSocket(newAnySocketAddress());
|
||||
socket.setReuseAddress(true);
|
||||
socket.setNetworkInterface(iface);
|
||||
try {
|
||||
socket.send(new java.net.DatagramPacket(new byte[] { 1, 2, 3, 4 }, 4,
|
||||
new InetSocketAddress(groupAddress(), 12345)));
|
||||
new InetSocketAddress(groupAddress(), 12345)));
|
||||
return iface;
|
||||
} catch (IOException ignore) {
|
||||
// Try the next interface
|
||||
@ -210,7 +210,7 @@ public class DatagramMulticastTest extends AbstractDatagramTest {
|
||||
}
|
||||
|
||||
private String groupAddress() {
|
||||
return internetProtocolFamily() == InternetProtocolFamily.IPv4 ?
|
||||
return groupInternetProtocalFamily() == InternetProtocolFamily.IPv4?
|
||||
"230.0.0.1" : "FF01:0:0:0:0:0:0:101";
|
||||
}
|
||||
}
|
||||
|
@ -117,11 +117,14 @@ final class LinuxSocket extends Socket {
|
||||
final boolean isIpv6 = group instanceof Inet6Address;
|
||||
final NativeInetAddress i = NativeInetAddress.newInstance(deriveInetAddress(netInterface, isIpv6));
|
||||
if (source != null) {
|
||||
if (source.getClass() != group.getClass()) {
|
||||
throw new IllegalArgumentException("Source address is different type to group");
|
||||
}
|
||||
final NativeInetAddress s = NativeInetAddress.newInstance(source);
|
||||
joinSsmGroup(intValue(), ipv6, g.address(), i.address(),
|
||||
joinSsmGroup(intValue(), ipv6 && isIpv6, g.address(), i.address(),
|
||||
g.scopeId(), interfaceIndex(netInterface), s.address());
|
||||
} else {
|
||||
joinGroup(intValue(), ipv6, g.address(), i.address(), g.scopeId(), interfaceIndex(netInterface));
|
||||
joinGroup(intValue(), ipv6 && isIpv6, g.address(), i.address(), g.scopeId(), interfaceIndex(netInterface));
|
||||
}
|
||||
}
|
||||
|
||||
@ -130,11 +133,14 @@ final class LinuxSocket extends Socket {
|
||||
final boolean isIpv6 = group instanceof Inet6Address;
|
||||
final NativeInetAddress i = NativeInetAddress.newInstance(deriveInetAddress(netInterface, isIpv6));
|
||||
if (source != null) {
|
||||
if (source.getClass() != group.getClass()) {
|
||||
throw new IllegalArgumentException("Source address is different type to group");
|
||||
}
|
||||
final NativeInetAddress s = NativeInetAddress.newInstance(source);
|
||||
leaveSsmGroup(intValue(), ipv6, g.address(), i.address(),
|
||||
leaveSsmGroup(intValue(), ipv6 && isIpv6, g.address(), i.address(),
|
||||
g.scopeId(), interfaceIndex(netInterface), s.address());
|
||||
} else {
|
||||
leaveGroup(intValue(), ipv6, g.address(), i.address(), g.scopeId(), interfaceIndex(netInterface));
|
||||
leaveGroup(intValue(), ipv6 && isIpv6, g.address(), i.address(), g.scopeId(), interfaceIndex(netInterface));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2021 The Netty Project
|
||||
*
|
||||
* The Netty Project licenses this file to you under the Apache License,
|
||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at:
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.channel.epoll;
|
||||
|
||||
import io.netty.channel.socket.InternetProtocolFamily;
|
||||
import io.netty.testsuite.transport.socket.DatagramMulticastTest;
|
||||
|
||||
public class EpollDatagramMulticastIpv6WithIpv4AddrTest extends DatagramMulticastTest {
|
||||
|
||||
@Override
|
||||
protected InternetProtocolFamily groupInternetProtocalFamily() {
|
||||
return InternetProtocolFamily.IPv4;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InternetProtocolFamily socketInternetProtocalFamily() {
|
||||
return InternetProtocolFamily.IPv6;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user