diff --git a/transport-native-epoll/src/test/java/io/netty/channel/epoll/LinuxSocketTest.java b/transport-native-epoll/src/test/java/io/netty/channel/epoll/LinuxSocketTest.java new file mode 100644 index 0000000000..00d2afb687 --- /dev/null +++ b/transport-native-epoll/src/test/java/io/netty/channel/epoll/LinuxSocketTest.java @@ -0,0 +1,54 @@ +/* + * Copyright 2020 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: + * + * http://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 org.junit.BeforeClass; +import org.junit.Test; + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; + +import static org.junit.Assume.assumeTrue; + +public class LinuxSocketTest { + @BeforeClass + public static void loadJNI() { + assumeTrue(Epoll.isAvailable()); + } + + @Test(expected = IOException.class) + public void testBindNonIpv6SocketToInet6AddressThrows() throws Exception { + LinuxSocket socket = LinuxSocket.newSocketStream(false); + try { + socket.bind(new InetSocketAddress(InetAddress.getByAddress( + new byte[]{'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1'}), 0)); + } finally { + socket.close(); + } + } + + @Test(expected = IOException.class) + public void testConnectNonIpv6SocketToInet6AddressThrows() throws Exception { + LinuxSocket socket = LinuxSocket.newSocketStream(false); + try { + socket.connect(new InetSocketAddress(InetAddress.getByAddress( + new byte[]{'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1'}), 1234)); + } finally { + socket.close(); + } + } +} diff --git a/transport-native-unix-common/src/main/java/io/netty/channel/unix/Socket.java b/transport-native-unix-common/src/main/java/io/netty/channel/unix/Socket.java index 10a68d4b34..f5459eacf2 100644 --- a/transport-native-unix-common/src/main/java/io/netty/channel/unix/Socket.java +++ b/transport-native-unix-common/src/main/java/io/netty/channel/unix/Socket.java @@ -55,6 +55,13 @@ public class Socket extends FileDescriptor { this.ipv6 = isIPv6(fd); } + /** + * Returns {@code true} if we should use IPv6 internally, {@code false} otherwise. + */ + private boolean useIpv6(InetAddress address) { + return ipv6 || address instanceof Inet6Address; + } + public final void shutdown() throws IOException { shutdown(true, true); } @@ -117,7 +124,7 @@ public class Socket extends FileDescriptor { scopeId = 0; address = ipv4MappedIpv6Address(addr.getAddress()); } - int res = sendTo(fd, ipv6, buf, pos, limit, address, scopeId, port); + int res = sendTo(fd, useIpv6(addr), buf, pos, limit, address, scopeId, port); if (res >= 0) { return res; } @@ -141,7 +148,7 @@ public class Socket extends FileDescriptor { scopeId = 0; address = ipv4MappedIpv6Address(addr.getAddress()); } - int res = sendToAddress(fd, ipv6, memoryAddress, pos, limit, address, scopeId, port); + int res = sendToAddress(fd, useIpv6(addr), memoryAddress, pos, limit, address, scopeId, port); if (res >= 0) { return res; } @@ -164,7 +171,7 @@ public class Socket extends FileDescriptor { scopeId = 0; address = ipv4MappedIpv6Address(addr.getAddress()); } - int res = sendToAddresses(fd, ipv6, memoryAddress, length, address, scopeId, port); + int res = sendToAddresses(fd, useIpv6(addr), memoryAddress, length, address, scopeId, port); if (res >= 0) { return res; } @@ -215,8 +222,9 @@ public class Socket extends FileDescriptor { int res; if (socketAddress instanceof InetSocketAddress) { InetSocketAddress inetSocketAddress = (InetSocketAddress) socketAddress; - NativeInetAddress address = NativeInetAddress.newInstance(inetSocketAddress.getAddress()); - res = connect(fd, ipv6, address.address, address.scopeId, inetSocketAddress.getPort()); + InetAddress inetAddress = inetSocketAddress.getAddress(); + NativeInetAddress address = NativeInetAddress.newInstance(inetAddress); + res = connect(fd, useIpv6(inetAddress), address.address, address.scopeId, inetSocketAddress.getPort()); } else if (socketAddress instanceof DomainSocketAddress) { DomainSocketAddress unixDomainSocketAddress = (DomainSocketAddress) socketAddress; res = connectDomainSocket(fd, unixDomainSocketAddress.path().getBytes(CharsetUtil.UTF_8)); @@ -255,8 +263,9 @@ public class Socket extends FileDescriptor { public final void bind(SocketAddress socketAddress) throws IOException { if (socketAddress instanceof InetSocketAddress) { InetSocketAddress addr = (InetSocketAddress) socketAddress; - NativeInetAddress address = NativeInetAddress.newInstance(addr.getAddress()); - int res = bind(fd, ipv6, address.address, address.scopeId, addr.getPort()); + InetAddress inetAddress = addr.getAddress(); + NativeInetAddress address = NativeInetAddress.newInstance(inetAddress); + int res = bind(fd, useIpv6(inetAddress), address.address, address.scopeId, addr.getPort()); if (res < 0) { throw newIOException("bind", res); }