diff --git a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java index 78ea1a7cd..3dc97829b 100644 --- a/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java +++ b/bramble-core/src/main/java/org/briarproject/bramble/plugin/tcp/LanTcpPlugin.java @@ -158,36 +158,41 @@ class LanTcpPlugin extends TcpPlugin { // Package access for testing boolean addressesAreOnSameLan(byte[] localIp, byte[] remoteIp) { // 10.0.0.0/8 - if (isPrefix10(localIp)) return isPrefix10(remoteIp); + if (isSlash8SiteLocal(localIp)) return isSlash8SiteLocal(remoteIp); // 172.16.0.0/12 - if (isPrefix172(localIp)) return isPrefix172(remoteIp); + if (isSlash12SiteLocal(localIp)) return isSlash12SiteLocal(remoteIp); // 192.168.0.0/16 - if (isPrefix192(localIp)) return isPrefix192(remoteIp); - // Unrecognised prefix - may be compatible - return true; + if (isSlash16SiteLocal(localIp)) return isSlash16SiteLocal(remoteIp); + // 169.254.0.0/16 + if (isSlash16LinkLocal(localIp)) return isSlash16LinkLocal(remoteIp); + // Unrecognised prefix + return false; } - private static boolean isPrefix10(byte[] ipv4) { + private static boolean isSlash8SiteLocal(byte[] ipv4) { return ipv4[0] == 10; } - private static boolean isPrefix172(byte[] ipv4) { + private static boolean isSlash12SiteLocal(byte[] ipv4) { return ipv4[0] == (byte) 172 && (ipv4[1] & 0xF0) == 16; } - private static boolean isPrefix192(byte[] ipv4) { + private static boolean isSlash16SiteLocal(byte[] ipv4) { return ipv4[0] == (byte) 192 && ipv4[1] == (byte) 168; } - // Returns the prefix length for an RFC 1918 address, or 0 for any other - // address - private static int getRfc1918PrefixLength(InetAddress addr) { + private static boolean isSlash16LinkLocal(byte[] ipv4) { + return ipv4[0] == (byte) 169 && ipv4[1] == (byte) 254; + } + + // Returns the prefix length for a link-local or site-local address, or 0 + // for any other address + private static int getPrefixLengthIfKnown(InetAddress addr) { if (!(addr instanceof Inet4Address)) return 0; - if (!addr.isSiteLocalAddress()) return 0; byte[] ipv4 = addr.getAddress(); - if (isPrefix10(ipv4)) return 8; - if (isPrefix172(ipv4)) return 12; - if (isPrefix192(ipv4)) return 16; + if (isSlash8SiteLocal(ipv4)) return 8; + if (isSlash12SiteLocal(ipv4)) return 12; + if (isSlash16SiteLocal(ipv4) || isSlash16LinkLocal(ipv4)) return 16; return 0; } @@ -308,9 +313,9 @@ class LanTcpPlugin extends TcpPlugin { int aPort = a.getPort(), bPort = b.getPort(); if (aPort > 0 && bPort == 0) return -1; if (aPort == 0 && bPort > 0) return 1; - // Prefer addresses with longer RFC 1918 prefixes - int aPrefix = getRfc1918PrefixLength(a.getAddress()); - int bPrefix = getRfc1918PrefixLength(b.getAddress()); + // Prefer addresses with longer prefixes + int aPrefix = getPrefixLengthIfKnown(a.getAddress()); + int bPrefix = getPrefixLengthIfKnown(b.getAddress()); return bPrefix - aPrefix; } } diff --git a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java index 12ccaf1e8..892e28693 100644 --- a/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java +++ b/bramble-core/src/test/java/org/briarproject/bramble/plugin/tcp/LanTcpPluginTest.java @@ -73,6 +73,8 @@ public class LanTcpPluginTest extends BrambleTestCase { makeAddress(10, 255, 255, 255))); assertFalse(plugin.addressesAreOnSameLan(makeAddress(192, 168, 0, 0), makeAddress(172, 31, 255, 255))); + assertFalse(plugin.addressesAreOnSameLan(makeAddress(169, 254, 0, 0), + makeAddress(192, 168, 255, 255))); // Remote prefix unrecognised should return false assertFalse(plugin.addressesAreOnSameLan(makeAddress(10, 0, 0, 0), makeAddress(1, 2, 3, 4))); @@ -80,8 +82,8 @@ public class LanTcpPluginTest extends BrambleTestCase { makeAddress(1, 2, 3, 4))); assertFalse(plugin.addressesAreOnSameLan(makeAddress(192, 168, 0, 0), makeAddress(1, 2, 3, 4))); - // Both prefixes unrecognised should return true (could be link-local) - assertTrue(plugin.addressesAreOnSameLan(makeAddress(1, 2, 3, 4), + // Both prefixes unrecognised should return false + assertFalse(plugin.addressesAreOnSameLan(makeAddress(1, 2, 3, 4), makeAddress(5, 6, 7, 8))); } @@ -292,41 +294,33 @@ public class LanTcpPluginTest extends BrambleTestCase { @Test public void testComparatorPrefersLongerPrefixes() { Comparator comparator = new LanAddressComparator(); + InetSocketAddress prefix169 = new InetSocketAddress("169.254.0.1", 0); InetSocketAddress prefix192 = new InetSocketAddress("192.168.0.1", 0); InetSocketAddress prefix172 = new InetSocketAddress("172.16.0.1", 0); InetSocketAddress prefix10 = new InetSocketAddress("10.0.0.1", 0); + assertEquals(0, comparator.compare(prefix169, prefix169)); + assertEquals(0, comparator.compare(prefix169, prefix192)); + assertTrue(comparator.compare(prefix169, prefix172) < 0); + assertTrue(comparator.compare(prefix169, prefix10) < 0); + assertEquals(0, comparator.compare(prefix192, prefix192)); + assertEquals(0, comparator.compare(prefix192, prefix169)); assertTrue(comparator.compare(prefix192, prefix172) < 0); assertTrue(comparator.compare(prefix192, prefix10) < 0); + assertTrue(comparator.compare(prefix172, prefix169) > 0); assertTrue(comparator.compare(prefix172, prefix192) > 0); assertEquals(0, comparator.compare(prefix172, prefix172)); assertTrue(comparator.compare(prefix172, prefix10) < 0); + assertTrue(comparator.compare(prefix10, prefix169) > 0); assertTrue(comparator.compare(prefix10, prefix192) > 0); assertTrue(comparator.compare(prefix10, prefix172) > 0); assertEquals(0, comparator.compare(prefix10, prefix10)); } - @Test - public void testComparatorPrefersSiteLocalToLinkLocal() { - Comparator comparator = new LanAddressComparator(); - InetSocketAddress prefix192 = new InetSocketAddress("192.168.0.1", 0); - InetSocketAddress prefix172 = new InetSocketAddress("172.16.0.1", 0); - InetSocketAddress prefix10 = new InetSocketAddress("10.0.0.1", 0); - InetSocketAddress linkLocal = new InetSocketAddress("169.254.0.1", 0); - - assertTrue(comparator.compare(prefix192, linkLocal) < 0); - assertTrue(comparator.compare(prefix172, linkLocal) < 0); - assertTrue(comparator.compare(prefix10, linkLocal) < 0); - - assertTrue(comparator.compare(linkLocal, prefix192) > 0); - assertTrue(comparator.compare(linkLocal, prefix172) > 0); - assertTrue(comparator.compare(linkLocal, prefix10) > 0); - assertEquals(0, comparator.compare(linkLocal, linkLocal)); - } - + @SuppressWarnings("BooleanMethodIsAlwaysInverted") private boolean systemHasLocalIpv4Address() throws Exception { for (NetworkInterface i : list(getNetworkInterfaces())) { for (InetAddress a : list(i.getInetAddresses())) {