Router: Don't lookup hostnames in addresses (proposal #141)

This commit is contained in:
zzz
2017-09-14 15:04:16 +00:00
parent bcd7b7e6ca
commit de487411b6
7 changed files with 80 additions and 14 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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 = "";

View File

@@ -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) {

View File

@@ -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

View File

@@ -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 &lt; 0 or i &gt;= 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;
}