Add util to add an ARP table entry
This is to be used by the new DhcpServer to add ARP entries with new addresses before sending unicast responses. Test: manual: cat /proc/net/arp with implementation based on this Bug: b/109584964 Change-Id: I3559893583aa3c49b188ad689a41ee2f3e9d9bf3
This commit is contained in:
@@ -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;
|
||||
@@ -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)}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -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 },
|
||||
|
||||
Reference in New Issue
Block a user