diff --git a/core/java/src/net/i2p/util/Addresses.java b/core/java/src/net/i2p/util/Addresses.java index 24d94b0b6..cf16e9a25 100644 --- a/core/java/src/net/i2p/util/Addresses.java +++ b/core/java/src/net/i2p/util/Addresses.java @@ -340,6 +340,7 @@ public abstract class Addresses { _negativeCache.remove(host); } } + //I2PAppContext.getGlobalContext().logManager().getLog(Addresses.class).error("lookup of " + host, new Exception("I did it")); try { rv = InetAddress.getByName(host).getAddress(); if (InetAddressUtils.isIPv4Address(host) || @@ -358,6 +359,41 @@ public abstract class Addresses { return rv; } + /** + * Caching version of InetAddress.getByName(host).getAddress(), which is slow. + * Resolves literal IP addresses only, will not cause a DNS lookup. + * Will return null for host names. + * + * Unlike InetAddress.getByName(), we do NOT allow numeric IPs + * of the form d.d.d, d.d, or d, as these are almost certainly mistakes. + * + * @param host literal IPv4 or IPv6 address; if null returns null + * @return IP or null + * @since 0.9.32 + */ + public static byte[] getIPOnly(String host) { + if (host == null) + return null; + byte[] rv; + synchronized (_IPAddress) { + rv = _IPAddress.get(host); + } + if (rv == null) { + if (InetAddressUtils.isIPv4Address(host) || + InetAddressUtils.isIPv6Address(host)) { + try { + rv = InetAddress.getByName(host).getAddress(); + synchronized (_IPAddress) { + _IPAddress.put(host, rv); + } + } catch (UnknownHostException uhe) {} + //} else { + // I2PAppContext.getGlobalContext().logManager().getLog(Addresses.class).warn("Not looking up " + host, new Exception("I did it")); + } + } + return rv; + } + /** * For literal IP addresses, this is the same as getIP(String). * For host names, will return the preferred type (IPv4/v6) if available, @@ -417,6 +453,8 @@ public abstract class Addresses { * Number of results may also change based on caching at various layers, * even if the ultimate name server results did not change. * + * Note: Unused + * * @param host DNS or IPv4 or IPv6 host name; if null returns null * @return non-empty list IPs, or null if none * @since 0.9.28 diff --git a/history.txt b/history.txt index c47a84ac7..ceec17eb7 100644 --- a/history.txt +++ b/history.txt @@ -1,3 +1,6 @@ +2017-09-14 zzz + * Router: Don't lookup hostnames in addresses (proposal #141) + 2017-09-12 str4d * Core: New benchmarking framework based on JMH (ticket #2036) diff --git a/router/java/src/net/i2p/data/router/RouterAddress.java b/router/java/src/net/i2p/data/router/RouterAddress.java index ea3ead59e..d9ff333c4 100644 --- a/router/java/src/net/i2p/data/router/RouterAddress.java +++ b/router/java/src/net/i2p/data/router/RouterAddress.java @@ -214,7 +214,11 @@ public class RouterAddress extends DataStructureImpl { /** * Caching version of InetAddress.getByName(getOption("host")).getAddress(), which is slow. - * Caches numeric host names AND DNS host names, and negative caches also. + * Caches numeric host names, and negative caches also. + * + * As of 0.9.32, this works for literal IP addresses only, and does NOT resolve host names. + * If a host name is specified in the options, this will return null. + * Use getHost() if you need the host name. * * @return IP or null * @since 0.9.3 @@ -226,7 +230,7 @@ public class RouterAddress extends DataStructureImpl { // it will get republished or expired, so it's OK even for host names. String host = getHost(); if (host != null) - _ip = Addresses.getIP(host); + _ip = Addresses.getIPOnly(host); else _ip = null; } diff --git a/router/java/src/net/i2p/router/RouterVersion.java b/router/java/src/net/i2p/router/RouterVersion.java index 282c18b42..0725033fa 100644 --- a/router/java/src/net/i2p/router/RouterVersion.java +++ b/router/java/src/net/i2p/router/RouterVersion.java @@ -18,7 +18,7 @@ public class RouterVersion { /** deprecated */ public final static String ID = "Monotone"; public final static String VERSION = CoreVersion.VERSION; - public final static long BUILD = 2; + public final static long BUILD = 3; /** for example "-test" */ public final static String EXTRA = ""; diff --git a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java index f568df6c6..2809435be 100644 --- a/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java +++ b/router/java/src/net/i2p/router/transport/CommSystemFacadeImpl.java @@ -355,6 +355,8 @@ public class CommSystemFacadeImpl extends CommSystemFacade { /** * Collect the IPs for all routers in the DB, and queue them for lookup, * then fire off the periodic lookup task for the first time. + * + * As of 0.9.32, works only for literal IPs, ignores host names. */ private class QueueAll implements SimpleTimer.TimedEvent { public void timeReached() { @@ -449,6 +451,8 @@ public class CommSystemFacadeImpl extends CommSystemFacade { * Uses the transport IP first because that lookup is fast, * then the IP from the netDb. * + * As of 0.9.32, works only for literal IPs, returns null for host names. + * * @param peer not ourselves - use getOurCountry() for that * @return two-letter lower-case country code or null */ @@ -470,6 +474,10 @@ public class CommSystemFacadeImpl extends CommSystemFacade { /** * Return first IP (v4 or v6) we find, any transport. * Not validated, may be local, etc. + * + * As of 0.9.32, works only for literal IPs, returns null for host names. + * + * @return IP or null */ private static byte[] getIP(RouterInfo ri) { for (RouterAddress ra : ri.getAddresses()) { @@ -484,6 +492,9 @@ public class CommSystemFacadeImpl extends CommSystemFacade { * Return first valid IP (v4 or v6) we find, any transport. * Local and other invalid IPs will not be returned. * + * As of 0.9.32, works only for literal IPs, returns null for host names. + * + * @return IP or null * @since 0.9.18 */ private static byte[] getValidIP(RouterInfo ri) { diff --git a/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java b/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java index 9b73d597f..8524cee67 100644 --- a/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java +++ b/router/java/src/net/i2p/router/transport/ntcp/EventPumper.java @@ -891,9 +891,12 @@ class EventPumper implements Runnable { con.setKey(key); RouterAddress naddr = con.getRemoteAddress(); try { - if (naddr.getPort() <= 0) + // no DNS lookups, do not use host names + int port = naddr.getPort(); + byte[] ip = naddr.getIP(); + if (port <= 0 || ip == null) throw new IOException("Invalid NTCP address: " + naddr); - InetSocketAddress saddr = new InetSocketAddress(naddr.getHost(), naddr.getPort()); + InetSocketAddress saddr = new InetSocketAddress(InetAddress.getByAddress(ip), port); boolean connected = con.getChannel().connect(saddr); if (connected) { // Never happens, we use nonblocking diff --git a/router/java/src/net/i2p/router/transport/udp/UDPAddress.java b/router/java/src/net/i2p/router/transport/udp/UDPAddress.java index 0f238d5de..b4eaa15fe 100644 --- a/router/java/src/net/i2p/router/transport/udp/UDPAddress.java +++ b/router/java/src/net/i2p/router/transport/udp/UDPAddress.java @@ -205,6 +205,11 @@ class UDPAddress { public String getHost() { return _host; } + /** + * As of 0.9.32, will NOT resolve host names. + * + * @return InetAddress or null + */ InetAddress getHostAddress() { if (_hostAddress == null) _hostAddress = getByName(_host); @@ -224,6 +229,8 @@ class UDPAddress { int getIntroducerCount() { return (_introAddresses == null ? 0 : _introAddresses.length); } /** + * As of 0.9.32, will NOT resolve host names. + * * @throws NullPointerException if getIntroducerCount() == 0 * @throws ArrayIndexOutOfBoundsException if i < 0 or i >= getIntroducerCount() * @return null if invalid @@ -314,13 +321,13 @@ class UDPAddress { /** * Caching version of InetAddress.getByName(host), which is slow. - * Caches numeric host names only. - * Will resolve but not cache DNS host names. + * Caches numeric IPs only. + * As of 0.9.32, will NOT resolve host names. * * Unlike InetAddress.getByName(), we do NOT allow numeric IPs * of the form d.d.d, d.d, or d, as these are almost certainly mistakes. * - * @param host DNS or IPv4 or IPv6 host name; if null returns null + * @param host literal IPv4 or IPv6; if null or hostname, returns null * @return InetAddress or null * @since IPv6 */ @@ -332,15 +339,15 @@ class UDPAddress { rv = _inetAddressCache.get(host); } if (rv == null) { - try { - rv = InetAddress.getByName(host); - if (InetAddressUtils.isIPv4Address(host) || - InetAddressUtils.isIPv6Address(host)) { + if (InetAddressUtils.isIPv4Address(host) || + InetAddressUtils.isIPv6Address(host)) { + try { + rv = InetAddress.getByName(host); synchronized (_inetAddressCache) { _inetAddressCache.put(host, rv); } - } - } catch (UnknownHostException uhe) {} + } catch (UnknownHostException uhe) {} + } } return rv; }