HADOOP-8154. DNS#getIPs shouldn't silently return the local host IP for bogus interface names. Contributed by Eli Collins

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1298696 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Eli Collins 2012-03-09 03:51:15 +00:00
parent 069fb57f4e
commit d8cc362350
3 changed files with 92 additions and 65 deletions

View File

@ -270,6 +270,9 @@ Release 0.23.3 - UNRELEASED
HADOOP-7888. TestFailoverProxy fails intermittently on trunk. (Jason Lowe HADOOP-7888. TestFailoverProxy fails intermittently on trunk. (Jason Lowe
via atm) via atm)
HADOOP-8154. DNS#getIPs shouldn't silently return the local host
IP for bogus interface names. (eli)
Release 0.23.2 - UNRELEASED Release 0.23.2 - UNRELEASED
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -96,42 +96,51 @@ public static String reverseDns(InetAddress hostIp, String ns)
* *
* @param strInterface * @param strInterface
* The name of the network interface to query (e.g. eth0) * The name of the network interface to query (e.g. eth0)
* or the string "default"
* @return A string vector of all the IPs associated with the provided * @return A string vector of all the IPs associated with the provided
* interface * interface. The local host IP is returned if the interface
* name "default" is specified or there is an I/O error looking
* for the given interface.
* @throws UnknownHostException * @throws UnknownHostException
* If an UnknownHostException is encountered in querying the * If the given interface is invalid
* default interface
* *
*/ */
public static String[] getIPs(String strInterface) public static String[] getIPs(String strInterface)
throws UnknownHostException { throws UnknownHostException {
try { if ("default".equals(strInterface)) {
NetworkInterface netIF = NetworkInterface.getByName(strInterface); return new String[] { cachedHostAddress };
if (netIF == null) {
return new String[] { cachedHostAddress };
} else {
Vector<String> ips = new Vector<String>();
Enumeration e = netIF.getInetAddresses();
while (e.hasMoreElements()) {
ips.add(((InetAddress) e.nextElement()).getHostAddress());
}
return ips.toArray(new String[] {});
}
} catch (SocketException e) {
return new String[] { cachedHostAddress };
} }
NetworkInterface netIF;
try {
netIF = NetworkInterface.getByName(strInterface);
} catch (SocketException e) {
LOG.warn("I/O error finding interface " + strInterface +
": " + e.getMessage());
return new String[] { cachedHostAddress };
}
if (netIF == null) {
throw new UnknownHostException("No such interface " + strInterface);
}
Vector<String> ips = new Vector<String>();
Enumeration<InetAddress> e = netIF.getInetAddresses();
while (e.hasMoreElements()) {
ips.add(e.nextElement().getHostAddress());
}
return ips.toArray(new String[] {});
} }
/** /**
* Returns the first available IP address associated with the provided * Returns the first available IP address associated with the provided
* network interface * network interface or the local host IP if "default" is given.
* *
* @param strInterface * @param strInterface
* The name of the network interface to query (e.g. eth0) * The name of the network interface to query (e.g. eth0)
* @return The IP address in text form * or the string "default"
* @return The IP address in text form, the local host IP is returned
* if the interface name "default" is specified
* @throws UnknownHostException * @throws UnknownHostException
* If one is encountered in querying the default interface * If the given interface is invalid
*/ */
public static String getDefaultIP(String strInterface) public static String getDefaultIP(String strInterface)
throws UnknownHostException { throws UnknownHostException {
@ -149,21 +158,22 @@ public static String getDefaultIP(String strInterface)
* The DNS host name * The DNS host name
* @return A string vector of all host names associated with the IPs tied to * @return A string vector of all host names associated with the IPs tied to
* the specified interface * the specified interface
* @throws UnknownHostException if the hostname cannot be determined * @throws UnknownHostException if the given interface is invalid
*/ */
public static String[] getHosts(String strInterface, String nameserver) public static String[] getHosts(String strInterface, String nameserver)
throws UnknownHostException { throws UnknownHostException {
String[] ips = getIPs(strInterface); String[] ips = getIPs(strInterface);
Vector<String> hosts = new Vector<String>(); Vector<String> hosts = new Vector<String>();
for (int ctr = 0; ctr < ips.length; ctr++) for (int ctr = 0; ctr < ips.length; ctr++) {
try { try {
hosts.add(reverseDns(InetAddress.getByName(ips[ctr]), hosts.add(reverseDns(InetAddress.getByName(ips[ctr]),
nameserver)); nameserver));
} catch (UnknownHostException ignored) { } catch (UnknownHostException ignored) {
} catch (NamingException ignored) { } catch (NamingException ignored) {
} }
}
if (hosts.isEmpty()) { if (hosts.isEmpty()) {
LOG.warn("Unable to determine hostname for interface " + strInterface);
return new String[] { cachedHostname }; return new String[] { cachedHostname };
} else { } else {
return hosts.toArray(new String[hosts.size()]); return hosts.toArray(new String[hosts.size()]);
@ -181,8 +191,8 @@ private static String resolveLocalHostname() {
try { try {
localhost = InetAddress.getLocalHost().getCanonicalHostName(); localhost = InetAddress.getLocalHost().getCanonicalHostName();
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
LOG.info("Unable to determine local hostname " LOG.warn("Unable to determine local hostname "
+ "-falling back to \"" + LOCALHOST + "\"", e); + "-falling back to \"" + LOCALHOST + "\"", e);
localhost = LOCALHOST; localhost = LOCALHOST;
} }
return localhost; return localhost;
@ -204,7 +214,7 @@ private static String resolveLocalHostIPAddress() {
try { try {
address = InetAddress.getLocalHost().getHostAddress(); address = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
LOG.info("Unable to determine address of the host" LOG.warn("Unable to determine address of the host"
+ "-falling back to \"" + LOCALHOST + "\" address", e); + "-falling back to \"" + LOCALHOST + "\" address", e);
try { try {
address = InetAddress.getByName(LOCALHOST).getHostAddress(); address = InetAddress.getByName(LOCALHOST).getHostAddress();

View File

@ -16,39 +16,32 @@
* limitations under the License. * limitations under the License.
*/ */
package org.apache.hadoop.net; package org.apache.hadoop.net;
import junit.framework.TestCase;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.net.InetAddress; import java.net.InetAddress;
import javax.naming.NameNotFoundException;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import javax.naming.NameNotFoundException; import org.junit.Test;
import static org.junit.Assert.*;
/** /**
* * Test host name and IP resolution and caching.
*/ */
public class TestDNS extends TestCase { public class TestDNS {
private static final Log LOG = LogFactory.getLog(TestDNS.class); private static final Log LOG = LogFactory.getLog(TestDNS.class);
private static final String DEFAULT = "default"; private static final String DEFAULT = "default";
/**
* Constructs a test case with the given name.
*
* @param name test name
*/
public TestDNS(String name) {
super(name);
}
/** /**
* Test that asking for the default hostname works * Test that asking for the default hostname works
* @throws Exception if hostname lookups fail */ * @throws Exception if hostname lookups fail
*/
@Test
public void testGetLocalHost() throws Exception { public void testGetLocalHost() throws Exception {
String hostname = DNS.getDefaultHost(DEFAULT); String hostname = DNS.getDefaultHost(DEFAULT);
assertNotNull(hostname); assertNotNull(hostname);
@ -59,26 +52,27 @@ public void testGetLocalHost() throws Exception {
* hence that caching is being used * hence that caching is being used
* @throws Exception if hostname lookups fail * @throws Exception if hostname lookups fail
*/ */
@Test
public void testGetLocalHostIsFast() throws Exception { public void testGetLocalHostIsFast() throws Exception {
String hostname = DNS.getDefaultHost(DEFAULT); String hostname1 = DNS.getDefaultHost(DEFAULT);
assertNotNull(hostname); assertNotNull(hostname1);
long t1 = System.currentTimeMillis();
String hostname2 = DNS.getDefaultHost(DEFAULT); String hostname2 = DNS.getDefaultHost(DEFAULT);
long t2 = System.currentTimeMillis(); long t1 = System.currentTimeMillis();
String hostname3 = DNS.getDefaultHost(DEFAULT); String hostname3 = DNS.getDefaultHost(DEFAULT);
long t3 = System.currentTimeMillis(); long t2 = System.currentTimeMillis();
assertEquals(hostname3, hostname2); assertEquals(hostname3, hostname2);
assertEquals(hostname2, hostname); assertEquals(hostname2, hostname1);
long interval2 = t3 - t2; long interval = t2 - t1;
assertTrue( assertTrue(
"It is taking to long to determine the local host -caching is not working", "Took too long to determine local host - caching is not working",
interval2 < 20000); interval < 20000);
} }
/** /**
* Test that our local IP address is not null * Test that our local IP address is not null
* @throws Exception if something went wrong * @throws Exception if something went wrong
*/ */
@Test
public void testLocalHostHasAnAddress() throws Exception { public void testLocalHostHasAnAddress() throws Exception {
assertNotNull(getLocalIPAddr()); assertNotNull(getLocalIPAddr());
} }
@ -90,34 +84,54 @@ private InetAddress getLocalIPAddr() throws UnknownHostException {
} }
/** /**
* Test that passing a null pointer is as the interface * Test null interface name
* fails with a NullPointerException
* @throws Exception if something went wrong
*/ */
@Test
public void testNullInterface() throws Exception { public void testNullInterface() throws Exception {
try { try {
String host = DNS.getDefaultHost(null); String host = DNS.getDefaultHost(null);
fail("Expected a NullPointerException, got " + host); fail("Expected a NullPointerException, got " + host);
} catch (NullPointerException expected) { } catch (NullPointerException npe) {
//this is expected // Expected
}
try {
String ip = DNS.getDefaultIP(null);
fail("Expected a NullPointerException, got " + ip);
} catch (NullPointerException npe) {
// Expected
} }
} }
/** /**
* Get the IP addresses of an unknown interface, expect to get something * Get the IP addresses of an unknown interface
* back
* @throws Exception if something went wrong
*/ */
@Test
public void testIPsOfUnknownInterface() throws Exception { public void testIPsOfUnknownInterface() throws Exception {
String[] ips = DNS.getIPs("name-of-an-unknown-interface"); try {
assertNotNull(ips); DNS.getIPs("name-of-an-unknown-interface");
assertTrue(ips.length > 0); fail("Got an IP for a bogus interface");
} catch (UnknownHostException e) {
assertEquals("No such interface name-of-an-unknown-interface",
e.getMessage());
}
}
/**
* Test the "default" IP addresses is the local IP addr
*/
@Test
public void testGetIPWithDefault() throws Exception {
String[] ips = DNS.getIPs(DEFAULT);
assertEquals("Should only return 1 default IP", 1, ips.length);
assertEquals(getLocalIPAddr().getHostAddress(), ips[0].toString());
String ip = DNS.getDefaultIP(DEFAULT);
assertEquals(ip, ips[0].toString());
} }
/** /**
* TestCase: get our local address and reverse look it up * TestCase: get our local address and reverse look it up
* @throws Exception if that fails
*/ */
@Test
public void testRDNS() throws Exception { public void testRDNS() throws Exception {
InetAddress localhost = getLocalIPAddr(); InetAddress localhost = getLocalIPAddr();
try { try {
@ -140,8 +154,8 @@ public void testRDNS() throws Exception {
* Test that the name "localhost" resolves to something. * Test that the name "localhost" resolves to something.
* *
* If this fails, your machine's network is in a mess, go edit /etc/hosts * If this fails, your machine's network is in a mess, go edit /etc/hosts
* @throws Exception for any problems
*/ */
@Test
public void testLocalhostResolves() throws Exception { public void testLocalhostResolves() throws Exception {
InetAddress localhost = InetAddress.getByName("localhost"); InetAddress localhost = InetAddress.getByName("localhost");
assertNotNull("localhost is null", localhost); assertNotNull("localhost is null", localhost);