HADOOP-6722. NetUtils.connect should check that it hasn't connected a socket to itself. Contributed by Todd Lipcon.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@939026 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Thomas White 2010-04-28 17:46:06 +00:00
parent cd85fc46dc
commit c59b4cd966
3 changed files with 75 additions and 0 deletions

View File

@ -376,6 +376,9 @@ Trunk (unreleased changes)
HADOOP-6724. IPC doesn't properly handle IOEs thrown by socket factory. HADOOP-6724. IPC doesn't properly handle IOEs thrown by socket factory.
(Todd Lipcon via tomwhite) (Todd Lipcon via tomwhite)
HADOOP-6722. NetUtils.connect should check that it hasn't connected a socket
to itself. (Todd Lipcon via tomwhite)
Release 0.21.0 - Unreleased Release 0.21.0 - Unreleased
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -26,6 +26,7 @@
import java.net.SocketAddress; import java.net.SocketAddress;
import java.net.URI; import java.net.URI;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.net.ConnectException;
import java.nio.channels.SocketChannel; import java.nio.channels.SocketChannel;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -367,6 +368,21 @@ public static void connect(Socket socket,
} else { } else {
SocketIOWithTimeout.connect(ch, endpoint, timeout); SocketIOWithTimeout.connect(ch, endpoint, timeout);
} }
// There is a very rare case allowed by the TCP specification, such that
// if we are trying to connect to an endpoint on the local machine,
// and we end up choosing an ephemeral port equal to the destination port,
// we will actually end up getting connected to ourself (ie any data we
// send just comes right back). This is only possible if the target
// daemon is down, so we'll treat it like connection refused.
if (socket.getLocalPort() == socket.getPort() &&
socket.getLocalAddress().equals(socket.getInetAddress())) {
LOG.info("Detected a loopback TCP socket, disconnecting it");
socket.close();
throw new ConnectException(
"Localhost targeted connection resulted in a loopback. " +
"No daemon is listening on the target port.");
}
} }
/** /**

View File

@ -0,0 +1,56 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF 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 org.apache.hadoop.net;
import org.junit.Test;
import static org.junit.Assert.*;
import java.net.Socket;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import org.apache.hadoop.conf.Configuration;
public class TestNetUtils {
/**
* Test that we can't accidentally connect back to the connecting socket due
* to a quirk in the TCP spec.
*
* This is a regression test for HADOOP-6722.
*/
@Test
public void testAvoidLoopbackTcpSockets() throws Exception {
Configuration conf = new Configuration();
Socket socket = NetUtils.getDefaultSocketFactory(conf)
.createSocket();
socket.bind(new InetSocketAddress("127.0.0.1", 0));
System.err.println("local address: " + socket.getLocalAddress());
System.err.println("local port: " + socket.getLocalPort());
try {
NetUtils.connect(socket,
new InetSocketAddress(socket.getLocalAddress(), socket.getLocalPort()),
20000);
socket.close();
fail("Should not have connected");
} catch (ConnectException ce) {
System.err.println("Got exception: " + ce);
assertTrue(ce.getMessage().contains("resulted in a loopback"));
}
}
}