Loading core/java/android/net/NetworkUtils.java +37 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.util.Log; import android.util.Pair; import java.io.FileDescriptor; import java.io.IOException; import java.math.BigInteger; import java.net.Inet4Address; import java.net.Inet6Address; Loading Loading @@ -130,6 +131,17 @@ public class NetworkUtils { */ 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) * @deprecated Use either {@link #intToInet4AddressHTH(int)} Loading @@ -149,7 +161,7 @@ public class NetworkUtils { * @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) { public static Inet4Address intToInet4AddressHTL(int hostAddress) { return intToInet4AddressHTH(Integer.reverseBytes(hostAddress)); } Loading @@ -157,14 +169,14 @@ public class NetworkUtils { * 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) { public static Inet4Address 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 (Inet4Address) InetAddress.getByAddress(addressBytes); } catch (UnknownHostException e) { throw new AssertionError(); } Loading Loading @@ -396,6 +408,28 @@ public class NetworkUtils { 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. * @return true if both are the same type. False otherwise. Loading core/jni/android_net_NetUtils.cpp +50 −0 Original line number Diff line number Diff line Loading @@ -323,6 +323,55 @@ static jboolean android_net_utils_queryUserAccess(JNIEnv *env, jobject thiz, jin 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; } } // ---------------------------------------------------------------------------- Loading @@ -337,6 +386,7 @@ static const JNINativeMethod gNetworkUtilMethods[] = { { "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork }, { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn }, { "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 }, { "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter }, { "attachControlPacketFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachControlPacketFilter }, Loading services/net/java/android/net/dhcp/DhcpDiscoverPacket.java +11 −4 Original line number Diff line number Diff line Loading @@ -23,11 +23,18 @@ import java.nio.ByteBuffer; * This class implements the DHCP-DISCOVER packet. */ class DhcpDiscoverPacket extends DhcpPacket { /** * The IP address of the client which sent this packet. */ final Inet4Address mSrcIp; /** * Generates a DISCOVER packet with the specified parameters. */ DhcpDiscoverPacket(int transId, short secs, byte[] clientMac, boolean broadcast) { super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast); DhcpDiscoverPacket(int transId, short secs, Inet4Address relayIp, byte[] clientMac, boolean broadcast, Inet4Address srcIp) { super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, relayIp, clientMac, broadcast); mSrcIp = srcIp; } public String toString() { Loading @@ -41,8 +48,8 @@ class DhcpDiscoverPacket extends DhcpPacket { */ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) { ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH); fillInPacket(encap, INADDR_BROADCAST, INADDR_ANY, destUdp, srcUdp, result, DHCP_BOOTREQUEST, mBroadcast); fillInPacket(encap, INADDR_BROADCAST, mSrcIp, destUdp, srcUdp, result, DHCP_BOOTREQUEST, mBroadcast); result.flip(); return result; } Loading services/net/java/android/net/dhcp/DhcpLease.java 0 → 100644 +138 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.dhcp; import android.annotation.NonNull; import android.annotation.Nullable; import android.net.MacAddress; import android.os.SystemClock; import android.text.TextUtils; import com.android.internal.util.HexDump; import java.net.Inet4Address; import java.util.Arrays; import java.util.Objects; /** * An IPv4 address assignment done through DHCPv4. * @hide */ public class DhcpLease { public static final long EXPIRATION_NEVER = Long.MAX_VALUE; public static final String HOSTNAME_NONE = null; @Nullable private final byte[] mClientId; @NonNull private final MacAddress mHwAddr; @NonNull private final Inet4Address mNetAddr; /** * Expiration time for the lease, to compare with {@link SystemClock#elapsedRealtime()}. */ private final long mExpTime; @Nullable private final String mHostname; public DhcpLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr, @NonNull Inet4Address netAddr, long expTime, @Nullable String hostname) { mClientId = (clientId == null ? null : Arrays.copyOf(clientId, clientId.length)); mHwAddr = hwAddr; mNetAddr = netAddr; mExpTime = expTime; mHostname = hostname; } @Nullable public byte[] getClientId() { if (mClientId == null) { return null; } return Arrays.copyOf(mClientId, mClientId.length); } @NonNull public MacAddress getHwAddr() { return mHwAddr; } @Nullable public String getHostname() { return mHostname; } @NonNull public Inet4Address getNetAddr() { return mNetAddr; } public long getExpTime() { return mExpTime; } /** * Push back the expiration time of this lease. If the provided time is sooner than the original * expiration time, the lease time will not be updated. * * <p>The lease hostname is updated with the provided one if set. * @return A {@link DhcpLease} with expiration time set to max(expTime, currentExpTime) */ public DhcpLease renewedLease(long expTime, @Nullable String hostname) { return new DhcpLease(mClientId, mHwAddr, mNetAddr, Math.max(expTime, mExpTime), (hostname == null ? mHostname : hostname)); } public boolean matchesClient(@Nullable byte[] clientId, @NonNull MacAddress hwAddr) { if (mClientId != null) { return Arrays.equals(mClientId, clientId); } else { return clientId == null && mHwAddr.equals(hwAddr); } } @Override public boolean equals(Object obj) { if (!(obj instanceof DhcpLease)) { return false; } final DhcpLease other = (DhcpLease)obj; return Arrays.equals(mClientId, other.mClientId) && mHwAddr.equals(other.mHwAddr) && mNetAddr.equals(other.mNetAddr) && mExpTime == other.mExpTime && TextUtils.equals(mHostname, other.mHostname); } @Override public int hashCode() { return Objects.hash(mClientId, mHwAddr, mNetAddr, mHostname, mExpTime); } static String clientIdToString(byte[] bytes) { if (bytes == null) { return "null"; } return HexDump.toHexString(bytes); } @Override public String toString() { return String.format("clientId: %s, hwAddr: %s, netAddr: %s, expTime: %d, hostname: %s", clientIdToString(mClientId), mHwAddr.toString(), mNetAddr, mExpTime, mHostname); } } services/net/java/android/net/dhcp/DhcpLeaseRepository.java 0 → 100644 +538 −0 File added.Preview size limit exceeded, changes collapsed. Show changes Loading
core/java/android/net/NetworkUtils.java +37 −3 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.util.Log; import android.util.Pair; import java.io.FileDescriptor; import java.io.IOException; import java.math.BigInteger; import java.net.Inet4Address; import java.net.Inet6Address; Loading Loading @@ -130,6 +131,17 @@ public class NetworkUtils { */ 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) * @deprecated Use either {@link #intToInet4AddressHTH(int)} Loading @@ -149,7 +161,7 @@ public class NetworkUtils { * @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) { public static Inet4Address intToInet4AddressHTL(int hostAddress) { return intToInet4AddressHTH(Integer.reverseBytes(hostAddress)); } Loading @@ -157,14 +169,14 @@ public class NetworkUtils { * 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) { public static Inet4Address 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 (Inet4Address) InetAddress.getByAddress(addressBytes); } catch (UnknownHostException e) { throw new AssertionError(); } Loading Loading @@ -396,6 +408,28 @@ public class NetworkUtils { 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. * @return true if both are the same type. False otherwise. Loading
core/jni/android_net_NetUtils.cpp +50 −0 Original line number Diff line number Diff line Loading @@ -323,6 +323,55 @@ static jboolean android_net_utils_queryUserAccess(JNIEnv *env, jobject thiz, jin 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; } } // ---------------------------------------------------------------------------- Loading @@ -337,6 +386,7 @@ static const JNINativeMethod gNetworkUtilMethods[] = { { "bindSocketToNetwork", "(II)I", (void*) android_net_utils_bindSocketToNetwork }, { "protectFromVpn", "(I)Z", (void*)android_net_utils_protectFromVpn }, { "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 }, { "attachRaFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachRaFilter }, { "attachControlPacketFilter", "(Ljava/io/FileDescriptor;I)V", (void*) android_net_utils_attachControlPacketFilter }, Loading
services/net/java/android/net/dhcp/DhcpDiscoverPacket.java +11 −4 Original line number Diff line number Diff line Loading @@ -23,11 +23,18 @@ import java.nio.ByteBuffer; * This class implements the DHCP-DISCOVER packet. */ class DhcpDiscoverPacket extends DhcpPacket { /** * The IP address of the client which sent this packet. */ final Inet4Address mSrcIp; /** * Generates a DISCOVER packet with the specified parameters. */ DhcpDiscoverPacket(int transId, short secs, byte[] clientMac, boolean broadcast) { super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, INADDR_ANY, clientMac, broadcast); DhcpDiscoverPacket(int transId, short secs, Inet4Address relayIp, byte[] clientMac, boolean broadcast, Inet4Address srcIp) { super(transId, secs, INADDR_ANY, INADDR_ANY, INADDR_ANY, relayIp, clientMac, broadcast); mSrcIp = srcIp; } public String toString() { Loading @@ -41,8 +48,8 @@ class DhcpDiscoverPacket extends DhcpPacket { */ public ByteBuffer buildPacket(int encap, short destUdp, short srcUdp) { ByteBuffer result = ByteBuffer.allocate(MAX_LENGTH); fillInPacket(encap, INADDR_BROADCAST, INADDR_ANY, destUdp, srcUdp, result, DHCP_BOOTREQUEST, mBroadcast); fillInPacket(encap, INADDR_BROADCAST, mSrcIp, destUdp, srcUdp, result, DHCP_BOOTREQUEST, mBroadcast); result.flip(); return result; } Loading
services/net/java/android/net/dhcp/DhcpLease.java 0 → 100644 +138 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.net.dhcp; import android.annotation.NonNull; import android.annotation.Nullable; import android.net.MacAddress; import android.os.SystemClock; import android.text.TextUtils; import com.android.internal.util.HexDump; import java.net.Inet4Address; import java.util.Arrays; import java.util.Objects; /** * An IPv4 address assignment done through DHCPv4. * @hide */ public class DhcpLease { public static final long EXPIRATION_NEVER = Long.MAX_VALUE; public static final String HOSTNAME_NONE = null; @Nullable private final byte[] mClientId; @NonNull private final MacAddress mHwAddr; @NonNull private final Inet4Address mNetAddr; /** * Expiration time for the lease, to compare with {@link SystemClock#elapsedRealtime()}. */ private final long mExpTime; @Nullable private final String mHostname; public DhcpLease(@Nullable byte[] clientId, @NonNull MacAddress hwAddr, @NonNull Inet4Address netAddr, long expTime, @Nullable String hostname) { mClientId = (clientId == null ? null : Arrays.copyOf(clientId, clientId.length)); mHwAddr = hwAddr; mNetAddr = netAddr; mExpTime = expTime; mHostname = hostname; } @Nullable public byte[] getClientId() { if (mClientId == null) { return null; } return Arrays.copyOf(mClientId, mClientId.length); } @NonNull public MacAddress getHwAddr() { return mHwAddr; } @Nullable public String getHostname() { return mHostname; } @NonNull public Inet4Address getNetAddr() { return mNetAddr; } public long getExpTime() { return mExpTime; } /** * Push back the expiration time of this lease. If the provided time is sooner than the original * expiration time, the lease time will not be updated. * * <p>The lease hostname is updated with the provided one if set. * @return A {@link DhcpLease} with expiration time set to max(expTime, currentExpTime) */ public DhcpLease renewedLease(long expTime, @Nullable String hostname) { return new DhcpLease(mClientId, mHwAddr, mNetAddr, Math.max(expTime, mExpTime), (hostname == null ? mHostname : hostname)); } public boolean matchesClient(@Nullable byte[] clientId, @NonNull MacAddress hwAddr) { if (mClientId != null) { return Arrays.equals(mClientId, clientId); } else { return clientId == null && mHwAddr.equals(hwAddr); } } @Override public boolean equals(Object obj) { if (!(obj instanceof DhcpLease)) { return false; } final DhcpLease other = (DhcpLease)obj; return Arrays.equals(mClientId, other.mClientId) && mHwAddr.equals(other.mHwAddr) && mNetAddr.equals(other.mNetAddr) && mExpTime == other.mExpTime && TextUtils.equals(mHostname, other.mHostname); } @Override public int hashCode() { return Objects.hash(mClientId, mHwAddr, mNetAddr, mHostname, mExpTime); } static String clientIdToString(byte[] bytes) { if (bytes == null) { return "null"; } return HexDump.toHexString(bytes); } @Override public String toString() { return String.format("clientId: %s, hwAddr: %s, netAddr: %s, expTime: %d, hostname: %s", clientIdToString(mClientId), mHwAddr.toString(), mNetAddr, mExpTime, mHostname); } }
services/net/java/android/net/dhcp/DhcpLeaseRepository.java 0 → 100644 +538 −0 File added.Preview size limit exceeded, changes collapsed. Show changes