Merge changes I2cea553a,Id8d3dcf6,I19e68e88,I35598935,Idd7dc369, ...
am: e01b4ce6c7 Change-Id: I1800eb214d501e76b8705a27ca817000d009736e
This commit is contained in:
@@ -22,6 +22,7 @@ import android.util.Log;
|
|||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
|
|
||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.net.Inet4Address;
|
import java.net.Inet4Address;
|
||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
@@ -130,6 +131,17 @@ public class NetworkUtils {
|
|||||||
*/
|
*/
|
||||||
public native static boolean queryUserAccess(int uid, int netId);
|
public native static boolean queryUserAccess(int uid, int netId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an entry into the ARP cache.
|
||||||
|
*/
|
||||||
|
public static void addArpEntry(Inet4Address ipv4Addr, MacAddress ethAddr, String ifname,
|
||||||
|
FileDescriptor fd) throws IOException {
|
||||||
|
addArpEntry(ethAddr.toByteArray(), ipv4Addr.getAddress(), ifname, fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static native void addArpEntry(byte[] ethAddr, byte[] netAddr, String ifname,
|
||||||
|
FileDescriptor fd) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see #intToInet4AddressHTL(int)
|
* @see #intToInet4AddressHTL(int)
|
||||||
* @deprecated Use either {@link #intToInet4AddressHTH(int)}
|
* @deprecated Use either {@link #intToInet4AddressHTH(int)}
|
||||||
@@ -149,7 +161,7 @@ public class NetworkUtils {
|
|||||||
* @param hostAddress an int coding for an IPv4 address, where higher-order int byte is
|
* @param hostAddress an int coding for an IPv4 address, where higher-order int byte is
|
||||||
* lower-order IPv4 address byte
|
* lower-order IPv4 address byte
|
||||||
*/
|
*/
|
||||||
public static InetAddress intToInet4AddressHTL(int hostAddress) {
|
public static Inet4Address intToInet4AddressHTL(int hostAddress) {
|
||||||
return intToInet4AddressHTH(Integer.reverseBytes(hostAddress));
|
return intToInet4AddressHTH(Integer.reverseBytes(hostAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,14 +169,14 @@ public class NetworkUtils {
|
|||||||
* Convert a IPv4 address from an integer to an InetAddress (0x01020304 -> 1.2.3.4)
|
* Convert a IPv4 address from an integer to an InetAddress (0x01020304 -> 1.2.3.4)
|
||||||
* @param hostAddress an int coding for an IPv4 address
|
* @param hostAddress an int coding for an IPv4 address
|
||||||
*/
|
*/
|
||||||
public static InetAddress intToInet4AddressHTH(int hostAddress) {
|
public static Inet4Address intToInet4AddressHTH(int hostAddress) {
|
||||||
byte[] addressBytes = { (byte) (0xff & (hostAddress >> 24)),
|
byte[] addressBytes = { (byte) (0xff & (hostAddress >> 24)),
|
||||||
(byte) (0xff & (hostAddress >> 16)),
|
(byte) (0xff & (hostAddress >> 16)),
|
||||||
(byte) (0xff & (hostAddress >> 8)),
|
(byte) (0xff & (hostAddress >> 8)),
|
||||||
(byte) (0xff & hostAddress) };
|
(byte) (0xff & hostAddress) };
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return InetAddress.getByAddress(addressBytes);
|
return (Inet4Address) InetAddress.getByAddress(addressBytes);
|
||||||
} catch (UnknownHostException e) {
|
} catch (UnknownHostException e) {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
@@ -396,6 +408,28 @@ public class NetworkUtils {
|
|||||||
return new Pair<InetAddress, Integer>(address, prefixLength);
|
return new Pair<InetAddress, Integer>(address, prefixLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a prefix mask as Inet4Address for a given prefix length.
|
||||||
|
*
|
||||||
|
* <p>For example 20 -> 255.255.240.0
|
||||||
|
*/
|
||||||
|
public static Inet4Address getPrefixMaskAsInet4Address(int prefixLength)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
return intToInet4AddressHTH(prefixLengthToV4NetmaskIntHTH(prefixLength));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the broadcast address for a given prefix.
|
||||||
|
*
|
||||||
|
* <p>For example 192.168.0.1/24 -> 192.168.0.255
|
||||||
|
*/
|
||||||
|
public static Inet4Address getBroadcastAddress(Inet4Address addr, int prefixLength)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
final int intBroadcastAddr = inet4AddressToIntHTH(addr)
|
||||||
|
| ~prefixLengthToV4NetmaskIntHTH(prefixLength);
|
||||||
|
return intToInet4AddressHTH(intBroadcastAddr);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if IP address type is consistent between two InetAddress.
|
* Check if IP address type is consistent between two InetAddress.
|
||||||
* @return true if both are the same type. False otherwise.
|
* @return true if both are the same type. False otherwise.
|
||||||
|
|||||||
@@ -323,6 +323,55 @@ static jboolean android_net_utils_queryUserAccess(JNIEnv *env, jobject thiz, jin
|
|||||||
return (jboolean) !queryUserAccess(uid, netId);
|
return (jboolean) !queryUserAccess(uid, netId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool checkLenAndCopy(JNIEnv* env, const jbyteArray& addr, int len, void* dst)
|
||||||
|
{
|
||||||
|
if (env->GetArrayLength(addr) != len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
env->GetByteArrayRegion(addr, 0, len, reinterpret_cast<jbyte*>(dst));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void android_net_utils_addArpEntry(JNIEnv *env, jobject thiz, jbyteArray ethAddr,
|
||||||
|
jbyteArray ipv4Addr, jstring ifname, jobject javaFd)
|
||||||
|
{
|
||||||
|
struct arpreq req = {};
|
||||||
|
struct sockaddr_in& netAddrStruct = *reinterpret_cast<sockaddr_in*>(&req.arp_pa);
|
||||||
|
struct sockaddr& ethAddrStruct = req.arp_ha;
|
||||||
|
|
||||||
|
ethAddrStruct.sa_family = ARPHRD_ETHER;
|
||||||
|
if (!checkLenAndCopy(env, ethAddr, ETH_ALEN, ethAddrStruct.sa_data)) {
|
||||||
|
jniThrowException(env, "java/io/IOException", "Invalid ethAddr length");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
netAddrStruct.sin_family = AF_INET;
|
||||||
|
if (!checkLenAndCopy(env, ipv4Addr, sizeof(in_addr), &netAddrStruct.sin_addr)) {
|
||||||
|
jniThrowException(env, "java/io/IOException", "Invalid ipv4Addr length");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ifLen = env->GetStringLength(ifname);
|
||||||
|
// IFNAMSIZ includes the terminating NULL character
|
||||||
|
if (ifLen >= IFNAMSIZ) {
|
||||||
|
jniThrowException(env, "java/io/IOException", "ifname too long");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
env->GetStringUTFRegion(ifname, 0, ifLen, req.arp_dev);
|
||||||
|
|
||||||
|
req.arp_flags = ATF_COM; // Completed entry (ha valid)
|
||||||
|
int fd = jniGetFDFromFileDescriptor(env, javaFd);
|
||||||
|
if (fd < 0) {
|
||||||
|
jniThrowExceptionFmt(env, "java/io/IOException", "Invalid file descriptor");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// See also: man 7 arp
|
||||||
|
if (ioctl(fd, SIOCSARP, &req)) {
|
||||||
|
jniThrowExceptionFmt(env, "java/io/IOException", "ioctl error: %s", strerror(errno));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -337,6 +386,7 @@ static const JNINativeMethod gNetworkUtilMethods[] = {
|
|||||||
{ "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork },
|
{ "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork },
|
||||||
{ "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
|
{ "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn },
|
||||||
{ "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
|
{ "queryUserAccess", "(II)Z", (void*)android_net_utils_queryUserAccess },
|
||||||
|
{ "addArpEntry", "([B[BLjava/lang/String;Ljava/io/FileDescriptor;)V", (void*) android_net_utils_addArpEntry },
|
||||||
{ "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
|
{ "attachDhcpFilter", "(Ljava/io/FileDescriptor;)V", (void*) android_net_utils_attachDhcpFilter },
|
||||||
{ "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter },
|
{ "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter },
|
||||||
{ "attachControlPacketFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachControlPacketFilter },
|
{ "attachControlPacketFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachControlPacketFilter },
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import static android.net.NetworkUtils.intToInet4AddressHTL;
|
|||||||
import static android.net.NetworkUtils.netmaskToPrefixLength;
|
import static android.net.NetworkUtils.netmaskToPrefixLength;
|
||||||
import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTH;
|
import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTH;
|
||||||
import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTL;
|
import static android.net.NetworkUtils.prefixLengthToV4NetmaskIntHTL;
|
||||||
|
import static android.net.NetworkUtils.getBroadcastAddress;
|
||||||
|
import static android.net.NetworkUtils.getPrefixMaskAsInet4Address;
|
||||||
|
|
||||||
import static junit.framework.Assert.assertEquals;
|
import static junit.framework.Assert.assertEquals;
|
||||||
|
|
||||||
@@ -125,7 +127,6 @@ public class NetworkUtilsTest {
|
|||||||
assertInvalidNetworkMask(IPv4Address("255.255.0.255"));
|
assertInvalidNetworkMask(IPv4Address("255.255.0.255"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testPrefixLengthToV4NetmaskIntHTL() {
|
public void testPrefixLengthToV4NetmaskIntHTL() {
|
||||||
assertEquals(0, prefixLengthToV4NetmaskIntHTL(0));
|
assertEquals(0, prefixLengthToV4NetmaskIntHTL(0));
|
||||||
@@ -266,4 +267,44 @@ public class NetworkUtilsTest {
|
|||||||
assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536),
|
assertEquals(BigInteger.valueOf(7l - 4 + 4 + 16 + 65536),
|
||||||
NetworkUtils.routedIPv6AddressCount(set));
|
NetworkUtils.routedIPv6AddressCount(set));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPrefixMaskAsAddress() {
|
||||||
|
assertEquals("255.255.240.0", getPrefixMaskAsInet4Address(20).getHostAddress());
|
||||||
|
assertEquals("255.0.0.0", getPrefixMaskAsInet4Address(8).getHostAddress());
|
||||||
|
assertEquals("0.0.0.0", getPrefixMaskAsInet4Address(0).getHostAddress());
|
||||||
|
assertEquals("255.255.255.255", getPrefixMaskAsInet4Address(32).getHostAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testGetPrefixMaskAsAddress_PrefixTooLarge() {
|
||||||
|
getPrefixMaskAsInet4Address(33);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testGetPrefixMaskAsAddress_NegativePrefix() {
|
||||||
|
getPrefixMaskAsInet4Address(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetBroadcastAddress() {
|
||||||
|
assertEquals("192.168.15.255",
|
||||||
|
getBroadcastAddress(IPv4Address("192.168.0.123"), 20).getHostAddress());
|
||||||
|
assertEquals("192.255.255.255",
|
||||||
|
getBroadcastAddress(IPv4Address("192.168.0.123"), 8).getHostAddress());
|
||||||
|
assertEquals("192.168.0.123",
|
||||||
|
getBroadcastAddress(IPv4Address("192.168.0.123"), 32).getHostAddress());
|
||||||
|
assertEquals("255.255.255.255",
|
||||||
|
getBroadcastAddress(IPv4Address("192.168.0.123"), 0).getHostAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testGetBroadcastAddress_PrefixTooLarge() {
|
||||||
|
getBroadcastAddress(IPv4Address("192.168.0.123"), 33);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
public void testGetBroadcastAddress_NegativePrefix() {
|
||||||
|
getBroadcastAddress(IPv4Address("192.168.0.123"), -1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user