diff options
-rw-r--r-- | core/java/android/net/NetworkUtils.java | 109 | ||||
-rw-r--r-- | tests/net/java/android/net/NetworkUtilsTest.java | 146 |
2 files changed, 213 insertions, 42 deletions
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java index 9a5d502673f3..dc1f8054f6a7 100644 --- a/core/java/android/net/NetworkUtils.java +++ b/core/java/android/net/NetworkUtils.java @@ -126,51 +126,122 @@ public class NetworkUtils { public native static boolean queryUserAccess(int uid, int netId); /** - * Convert a IPv4 address from an integer to an InetAddress. - * @param hostAddress an int corresponding to the IPv4 address in network byte order + * @see #intToInet4AddressHTL(int) + * @deprecated Use either {@link #intToInet4AddressHTH(int)} + * or {@link #intToInet4AddressHTL(int)} */ + @Deprecated public static InetAddress intToInetAddress(int hostAddress) { - byte[] addressBytes = { (byte)(0xff & hostAddress), - (byte)(0xff & (hostAddress >> 8)), - (byte)(0xff & (hostAddress >> 16)), - (byte)(0xff & (hostAddress >> 24)) }; + return intToInet4AddressHTL(hostAddress); + } + + /** + * Convert a IPv4 address from an integer to an InetAddress (0x04030201 -> 1.2.3.4) + * + * <p>This method uses the higher-order int bytes as the lower-order IPv4 address bytes, + * which is an unusual convention. Consider {@link #intToInet4AddressHTH(int)} instead. + * @param hostAddress an int coding for an IPv4 address, where higher-order int byte is + * lower-order IPv4 address byte + */ + public static InetAddress intToInet4AddressHTL(int hostAddress) { + return intToInet4AddressHTH(Integer.reverseBytes(hostAddress)); + } + + /** + * Convert a IPv4 address from an integer to an InetAddress (0x01020304 -> 1.2.3.4) + * @param hostAddress an int coding for an IPv4 address + */ + public static InetAddress intToInet4AddressHTH(int hostAddress) { + byte[] addressBytes = { (byte) (0xff & (hostAddress >> 24)), + (byte) (0xff & (hostAddress >> 16)), + (byte) (0xff & (hostAddress >> 8)), + (byte) (0xff & hostAddress) }; try { - return InetAddress.getByAddress(addressBytes); + return InetAddress.getByAddress(addressBytes); } catch (UnknownHostException e) { - throw new AssertionError(); + throw new AssertionError(); } } /** - * Convert a IPv4 address from an InetAddress to an integer - * @param inetAddr is an InetAddress corresponding to the IPv4 address - * @return the IP address as an integer in network byte order + * @see #inet4AddressToIntHTL(Inet4Address) + * @deprecated Use either {@link #inet4AddressToIntHTH(Inet4Address)} + * or {@link #inet4AddressToIntHTL(Inet4Address)} */ + @Deprecated public static int inetAddressToInt(Inet4Address inetAddr) throws IllegalArgumentException { + return inet4AddressToIntHTL(inetAddr); + } + + /** + * Convert an IPv4 address from an InetAddress to an integer (1.2.3.4 -> 0x01020304) + * + * <p>This conversion can help order IP addresses: considering the ordering + * 192.0.2.1 < 192.0.2.2 < ..., resulting ints will follow that ordering if read as unsigned + * integers with {@link Integer#toUnsignedLong}. + * @param inetAddr is an InetAddress corresponding to the IPv4 address + * @return the IP address as integer + */ + public static int inet4AddressToIntHTH(Inet4Address inetAddr) + throws IllegalArgumentException { byte [] addr = inetAddr.getAddress(); - return ((addr[3] & 0xff) << 24) | ((addr[2] & 0xff) << 16) | - ((addr[1] & 0xff) << 8) | (addr[0] & 0xff); + return ((addr[0] & 0xff) << 24) | ((addr[1] & 0xff) << 16) + | ((addr[2] & 0xff) << 8) | (addr[3] & 0xff); } /** - * Convert a network prefix length to an IPv4 netmask integer - * @param prefixLength - * @return the IPv4 netmask as an integer in network byte order + * Convert a IPv4 address from an InetAddress to an integer (1.2.3.4 -> 0x04030201) + * + * <p>This method stores the higher-order IPv4 address bytes in the lower-order int bytes, + * which is an unusual convention. Consider {@link #inet4AddressToIntHTH(Inet4Address)} instead. + * @param inetAddr is an InetAddress corresponding to the IPv4 address + * @return the IP address as integer */ + public static int inet4AddressToIntHTL(Inet4Address inetAddr) { + return Integer.reverseBytes(inet4AddressToIntHTH(inetAddr)); + } + + /** + * @see #prefixLengthToV4NetmaskIntHTL(int) + * @deprecated Use either {@link #prefixLengthToV4NetmaskIntHTH(int)} + * or {@link #prefixLengthToV4NetmaskIntHTL(int)} + */ + @Deprecated public static int prefixLengthToNetmaskInt(int prefixLength) throws IllegalArgumentException { + return prefixLengthToV4NetmaskIntHTL(prefixLength); + } + + /** + * Convert a network prefix length to an IPv4 netmask integer (prefixLength 17 -> 0xffff8000) + * @return the IPv4 netmask as an integer + */ + public static int prefixLengthToV4NetmaskIntHTH(int prefixLength) + throws IllegalArgumentException { if (prefixLength < 0 || prefixLength > 32) { throw new IllegalArgumentException("Invalid prefix length (0 <= prefix <= 32)"); } - int value = 0xffffffff << (32 - prefixLength); - return Integer.reverseBytes(value); + // (int)a << b is equivalent to a << (b & 0x1f): can't shift by 32 (-1 << 32 == -1) + return prefixLength == 0 ? 0 : 0xffffffff << (32 - prefixLength); + } + + /** + * Convert a network prefix length to an IPv4 netmask integer (prefixLength 17 -> 0x0080ffff). + * + * <p>This method stores the higher-order IPv4 address bytes in the lower-order int bytes, + * which is an unusual convention. Consider {@link #prefixLengthToV4NetmaskIntHTH(int)} instead. + * @return the IPv4 netmask as an integer + */ + public static int prefixLengthToV4NetmaskIntHTL(int prefixLength) + throws IllegalArgumentException { + return Integer.reverseBytes(prefixLengthToV4NetmaskIntHTH(prefixLength)); } /** * Convert a IPv4 netmask integer to a prefix length - * @param netmask as an integer in network byte order + * @param netmask as an integer (0xff000000 for a /8 subnet) * @return the network prefix length */ public static int netmaskIntToPrefixLength(int netmask) { diff --git a/tests/net/java/android/net/NetworkUtilsTest.java b/tests/net/java/android/net/NetworkUtilsTest.java index a5ee8e37553d..2b172dac4865 100644 --- a/tests/net/java/android/net/NetworkUtilsTest.java +++ b/tests/net/java/android/net/NetworkUtilsTest.java @@ -16,17 +16,32 @@ package android.net; -import android.net.NetworkUtils; -import android.test.suitebuilder.annotation.SmallTest; +import static android.net.NetworkUtils.getImplicitNetmask; +import static android.net.NetworkUtils.inet4AddressToIntHTH; +import static android.net.NetworkUtils.inet4AddressToIntHTL; +import static android.net.NetworkUtils.intToInet4AddressHTH; +import static android.net.NetworkUtils.intToInet4AddressHTL; +import static android.net.NetworkUtils.netmaskToPrefixLength; +import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTH; +import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTL; + +import static junit.framework.Assert.assertEquals; + +import static org.junit.Assert.fail; + +import android.support.test.runner.AndroidJUnit4; import java.math.BigInteger; import java.net.Inet4Address; import java.net.InetAddress; import java.util.TreeSet; -import junit.framework.TestCase; +import org.junit.Test; +import org.junit.runner.RunWith; -public class NetworkUtilsTest extends TestCase { +@RunWith(AndroidJUnit4.class) +@android.support.test.filters.SmallTest +public class NetworkUtilsTest { private InetAddress Address(String addr) { return InetAddress.parseNumericAddress(addr); @@ -36,41 +51,126 @@ public class NetworkUtilsTest extends TestCase { return (Inet4Address) Address(addr); } - @SmallTest + @Test public void testGetImplicitNetmask() { - assertEquals(8, NetworkUtils.getImplicitNetmask(IPv4Address("4.2.2.2"))); - assertEquals(8, NetworkUtils.getImplicitNetmask(IPv4Address("10.5.6.7"))); - assertEquals(16, NetworkUtils.getImplicitNetmask(IPv4Address("173.194.72.105"))); - assertEquals(16, NetworkUtils.getImplicitNetmask(IPv4Address("172.23.68.145"))); - assertEquals(24, NetworkUtils.getImplicitNetmask(IPv4Address("192.0.2.1"))); - assertEquals(24, NetworkUtils.getImplicitNetmask(IPv4Address("192.168.5.1"))); - assertEquals(32, NetworkUtils.getImplicitNetmask(IPv4Address("224.0.0.1"))); - assertEquals(32, NetworkUtils.getImplicitNetmask(IPv4Address("255.6.7.8"))); + assertEquals(8, getImplicitNetmask(IPv4Address("4.2.2.2"))); + assertEquals(8, getImplicitNetmask(IPv4Address("10.5.6.7"))); + assertEquals(16, getImplicitNetmask(IPv4Address("173.194.72.105"))); + assertEquals(16, getImplicitNetmask(IPv4Address("172.23.68.145"))); + assertEquals(24, getImplicitNetmask(IPv4Address("192.0.2.1"))); + assertEquals(24, getImplicitNetmask(IPv4Address("192.168.5.1"))); + assertEquals(32, getImplicitNetmask(IPv4Address("224.0.0.1"))); + assertEquals(32, getImplicitNetmask(IPv4Address("255.6.7.8"))); } private void assertInvalidNetworkMask(Inet4Address addr) { try { - NetworkUtils.netmaskToPrefixLength(addr); + netmaskToPrefixLength(addr); fail("Invalid netmask " + addr.getHostAddress() + " did not cause exception"); } catch (IllegalArgumentException expected) { } } - @SmallTest + @Test + public void testInet4AddressToIntHTL() { + assertEquals(0, inet4AddressToIntHTL(IPv4Address("0.0.0.0"))); + assertEquals(0x000080ff, inet4AddressToIntHTL(IPv4Address("255.128.0.0"))); + assertEquals(0x0080ff0a, inet4AddressToIntHTL(IPv4Address("10.255.128.0"))); + assertEquals(0x00feff0a, inet4AddressToIntHTL(IPv4Address("10.255.254.0"))); + assertEquals(0xfeffa8c0, inet4AddressToIntHTL(IPv4Address("192.168.255.254"))); + assertEquals(0xffffa8c0, inet4AddressToIntHTL(IPv4Address("192.168.255.255"))); + } + + @Test + public void testIntToInet4AddressHTL() { + assertEquals(IPv4Address("0.0.0.0"), intToInet4AddressHTL(0)); + assertEquals(IPv4Address("255.128.0.0"), intToInet4AddressHTL(0x000080ff)); + assertEquals(IPv4Address("10.255.128.0"), intToInet4AddressHTL(0x0080ff0a)); + assertEquals(IPv4Address("10.255.254.0"), intToInet4AddressHTL(0x00feff0a)); + assertEquals(IPv4Address("192.168.255.254"), intToInet4AddressHTL(0xfeffa8c0)); + assertEquals(IPv4Address("192.168.255.255"), intToInet4AddressHTL(0xffffa8c0)); + } + + @Test + public void testInet4AddressToIntHTH() { + assertEquals(0, inet4AddressToIntHTH(IPv4Address("0.0.0.0"))); + assertEquals(0xff800000, inet4AddressToIntHTH(IPv4Address("255.128.0.0"))); + assertEquals(0x0aff8000, inet4AddressToIntHTH(IPv4Address("10.255.128.0"))); + assertEquals(0x0afffe00, inet4AddressToIntHTH(IPv4Address("10.255.254.0"))); + assertEquals(0xc0a8fffe, inet4AddressToIntHTH(IPv4Address("192.168.255.254"))); + assertEquals(0xc0a8ffff, inet4AddressToIntHTH(IPv4Address("192.168.255.255"))); + } + + @Test + public void testIntToInet4AddressHTH() { + assertEquals(IPv4Address("0.0.0.0"), intToInet4AddressHTH(0)); + assertEquals(IPv4Address("255.128.0.0"), intToInet4AddressHTH(0xff800000)); + assertEquals(IPv4Address("10.255.128.0"), intToInet4AddressHTH(0x0aff8000)); + assertEquals(IPv4Address("10.255.254.0"), intToInet4AddressHTH(0x0afffe00)); + assertEquals(IPv4Address("192.168.255.254"), intToInet4AddressHTH(0xc0a8fffe)); + assertEquals(IPv4Address("192.168.255.255"), intToInet4AddressHTH(0xc0a8ffff)); + } + + @Test public void testNetmaskToPrefixLength() { - assertEquals(0, NetworkUtils.netmaskToPrefixLength(IPv4Address("0.0.0.0"))); - assertEquals(9, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.128.0.0"))); - assertEquals(17, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.128.0"))); - assertEquals(23, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.254.0"))); - assertEquals(31, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.255.254"))); - assertEquals(32, NetworkUtils.netmaskToPrefixLength(IPv4Address("255.255.255.255"))); + assertEquals(0, netmaskToPrefixLength(IPv4Address("0.0.0.0"))); + assertEquals(9, netmaskToPrefixLength(IPv4Address("255.128.0.0"))); + assertEquals(17, netmaskToPrefixLength(IPv4Address("255.255.128.0"))); + assertEquals(23, netmaskToPrefixLength(IPv4Address("255.255.254.0"))); + assertEquals(31, netmaskToPrefixLength(IPv4Address("255.255.255.254"))); + assertEquals(32, netmaskToPrefixLength(IPv4Address("255.255.255.255"))); assertInvalidNetworkMask(IPv4Address("0.0.0.1")); assertInvalidNetworkMask(IPv4Address("255.255.255.253")); assertInvalidNetworkMask(IPv4Address("255.255.0.255")); } - @SmallTest + + @Test + public void testPrefixLengthToV4NetmaskIntHTL() { + assertEquals(0, prefixLengthToV4NetmaskIntHTL(0)); + assertEquals(0x000080ff /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTL(9)); + assertEquals(0x0080ffff /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTL(17)); + assertEquals(0x00feffff /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTL(23)); + assertEquals(0xfeffffff /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTL(31)); + assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTL(32)); + } + + @Test + public void testPrefixLengthToV4NetmaskIntHTH() { + assertEquals(0, prefixLengthToV4NetmaskIntHTH(0)); + assertEquals(0xff800000 /* 255.128.0.0 */, prefixLengthToV4NetmaskIntHTH(9)); + assertEquals(0xffff8000 /* 255.255.128.0 */, prefixLengthToV4NetmaskIntHTH(17)); + assertEquals(0xfffffe00 /* 255.255.254.0 */, prefixLengthToV4NetmaskIntHTH(23)); + assertEquals(0xfffffffe /* 255.255.255.254 */, prefixLengthToV4NetmaskIntHTH(31)); + assertEquals(0xffffffff /* 255.255.255.255 */, prefixLengthToV4NetmaskIntHTH(32)); + } + + @Test(expected = IllegalArgumentException.class) + public void testPrefixLengthToV4NetmaskIntHTH_NegativeLength() { + prefixLengthToV4NetmaskIntHTH(-1); + } + + @Test(expected = IllegalArgumentException.class) + public void testPrefixLengthToV4NetmaskIntHTH_LengthTooLarge() { + prefixLengthToV4NetmaskIntHTH(33); + } + + private void checkAddressMasking(String expectedAddr, String addr, int prefixLength) { + final int prefix = prefixLengthToV4NetmaskIntHTH(prefixLength); + final int addrInt = inet4AddressToIntHTH(IPv4Address(addr)); + assertEquals(IPv4Address(expectedAddr), intToInet4AddressHTH(prefix & addrInt)); + } + + @Test + public void testPrefixLengthToV4NetmaskIntHTH_MaskAddr() { + checkAddressMasking("192.168.0.0", "192.168.128.1", 16); + checkAddressMasking("255.240.0.0", "255.255.255.255", 12); + checkAddressMasking("255.255.255.255", "255.255.255.255", 32); + checkAddressMasking("0.0.0.0", "255.255.255.255", 0); + } + + @Test public void testRoutedIPv4AddressCount() { final TreeSet<IpPrefix> set = new TreeSet<>(IpPrefix.lengthComparator()); // No routes routes to no addresses. @@ -118,7 +218,7 @@ public class NetworkUtilsTest extends TestCase { assertEquals(7l - 4 + 4 + 16 + 65536, NetworkUtils.routedIPv4AddressCount(set)); } - @SmallTest + @Test public void testRoutedIPv6AddressCount() { final TreeSet<IpPrefix> set = new TreeSet<>(IpPrefix.lengthComparator()); // No routes routes to no addresses. |