Merge "Add support for TAP interfaces in TestNetworkManager."
This commit is contained in:
@@ -85,4 +85,21 @@ public class TestNetworkManager {
|
|||||||
throw e.rethrowFromSystemServer();
|
throw e.rethrowFromSystemServer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a tap interface for testing purposes
|
||||||
|
*
|
||||||
|
* @return A ParcelFileDescriptor of the underlying TAP interface. Close this to tear down the
|
||||||
|
* TAP interface.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
@TestApi
|
||||||
|
public TestNetworkInterface createTapInterface() {
|
||||||
|
try {
|
||||||
|
return mService.createTapInterface();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw e.rethrowFromSystemServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ class TestNetworkService extends ITestNetworkManager.Stub {
|
|||||||
@NonNull private static final String TAG = TestNetworkService.class.getSimpleName();
|
@NonNull private static final String TAG = TestNetworkService.class.getSimpleName();
|
||||||
@NonNull private static final String TEST_NETWORK_TYPE = "TEST_NETWORK";
|
@NonNull private static final String TEST_NETWORK_TYPE = "TEST_NETWORK";
|
||||||
@NonNull private static final String TEST_TUN_PREFIX = "testtun";
|
@NonNull private static final String TEST_TUN_PREFIX = "testtun";
|
||||||
|
@NonNull private static final String TEST_TAP_PREFIX = "testtap";
|
||||||
@NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger();
|
@NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger();
|
||||||
|
|
||||||
@NonNull private final Context mContext;
|
@NonNull private final Context mContext;
|
||||||
@@ -70,7 +71,7 @@ class TestNetworkService extends ITestNetworkManager.Stub {
|
|||||||
@NonNull private final Handler mHandler;
|
@NonNull private final Handler mHandler;
|
||||||
|
|
||||||
// Native method stubs
|
// Native method stubs
|
||||||
private static native int jniCreateTun(@NonNull String iface);
|
private static native int jniCreateTunTap(boolean isTun, @NonNull String iface);
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected TestNetworkService(
|
protected TestNetworkService(
|
||||||
@@ -85,23 +86,23 @@ class TestNetworkService extends ITestNetworkManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a TUN interface with the given interface name and link addresses
|
* Create a TUN or TAP interface with the given interface name and link addresses
|
||||||
*
|
*
|
||||||
* <p>This method will return the FileDescriptor to the TUN interface. Close it to tear down the
|
* <p>This method will return the FileDescriptor to the interface. Close it to tear down the
|
||||||
* TUN interface.
|
* interface.
|
||||||
*/
|
*/
|
||||||
@Override
|
private TestNetworkInterface createInterface(boolean isTun, LinkAddress[] linkAddrs) {
|
||||||
public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
|
|
||||||
enforceTestNetworkPermissions(mContext);
|
enforceTestNetworkPermissions(mContext);
|
||||||
|
|
||||||
checkNotNull(linkAddrs, "missing linkAddrs");
|
checkNotNull(linkAddrs, "missing linkAddrs");
|
||||||
|
|
||||||
String iface = TEST_TUN_PREFIX + sTestTunIndex.getAndIncrement();
|
String ifacePrefix = isTun ? TEST_TUN_PREFIX : TEST_TAP_PREFIX;
|
||||||
|
String iface = ifacePrefix + sTestTunIndex.getAndIncrement();
|
||||||
return Binder.withCleanCallingIdentity(
|
return Binder.withCleanCallingIdentity(
|
||||||
() -> {
|
() -> {
|
||||||
try {
|
try {
|
||||||
ParcelFileDescriptor tunIntf =
|
ParcelFileDescriptor tunIntf =
|
||||||
ParcelFileDescriptor.adoptFd(jniCreateTun(iface));
|
ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
|
||||||
for (LinkAddress addr : linkAddrs) {
|
for (LinkAddress addr : linkAddrs) {
|
||||||
mNetd.interfaceAddAddress(
|
mNetd.interfaceAddAddress(
|
||||||
iface,
|
iface,
|
||||||
@@ -116,6 +117,28 @@ class TestNetworkService extends ITestNetworkManager.Stub {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TUN interface with the given interface name and link addresses
|
||||||
|
*
|
||||||
|
* <p>This method will return the FileDescriptor to the TUN interface. Close it to tear down the
|
||||||
|
* TUN interface.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
|
||||||
|
return createInterface(true, linkAddrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a TAP interface with the given interface name
|
||||||
|
*
|
||||||
|
* <p>This method will return the FileDescriptor to the TAP interface. Close it to tear down the
|
||||||
|
* TAP interface.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public TestNetworkInterface createTapInterface() {
|
||||||
|
return createInterface(false, new LinkAddress[0]);
|
||||||
|
}
|
||||||
|
|
||||||
// Tracker for TestNetworkAgents
|
// Tracker for TestNetworkAgents
|
||||||
@GuardedBy("mTestNetworkTracker")
|
@GuardedBy("mTestNetworkTracker")
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|||||||
@@ -54,12 +54,12 @@ static void throwException(JNIEnv* env, int error, const char* action, const cha
|
|||||||
jniThrowException(env, "java/lang/IllegalStateException", msg.c_str());
|
jniThrowException(env, "java/lang/IllegalStateException", msg.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
static int createTunInterface(JNIEnv* env, const char* iface) {
|
static int createTunTapInterface(JNIEnv* env, bool isTun, const char* iface) {
|
||||||
base::unique_fd tun(open("/dev/tun", O_RDWR | O_NONBLOCK));
|
base::unique_fd tun(open("/dev/tun", O_RDWR | O_NONBLOCK));
|
||||||
ifreq ifr{};
|
ifreq ifr{};
|
||||||
|
|
||||||
// Allocate interface.
|
// Allocate interface.
|
||||||
ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
|
ifr.ifr_flags = (isTun ? IFF_TUN : IFF_TAP) | IFF_NO_PI;
|
||||||
strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
|
strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
|
||||||
if (ioctl(tun.get(), TUNSETIFF, &ifr)) {
|
if (ioctl(tun.get(), TUNSETIFF, &ifr)) {
|
||||||
throwException(env, errno, "allocating", ifr.ifr_name);
|
throwException(env, errno, "allocating", ifr.ifr_name);
|
||||||
@@ -80,23 +80,23 @@ static int createTunInterface(JNIEnv* env, const char* iface) {
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
static jint create(JNIEnv* env, jobject /* thiz */, jstring jIface) {
|
static jint create(JNIEnv* env, jobject /* thiz */, jboolean isTun, jstring jIface) {
|
||||||
ScopedUtfChars iface(env, jIface);
|
ScopedUtfChars iface(env, jIface);
|
||||||
if (!iface.c_str()) {
|
if (!iface.c_str()) {
|
||||||
jniThrowNullPointerException(env, "iface");
|
jniThrowNullPointerException(env, "iface");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tun = createTunInterface(env, iface.c_str());
|
int tun = createTunTapInterface(env, isTun, iface.c_str());
|
||||||
|
|
||||||
// Any exceptions will be thrown from the createTunInterface call
|
// Any exceptions will be thrown from the createTunTapInterface call
|
||||||
return tun;
|
return tun;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
static const JNINativeMethod gMethods[] = {
|
static const JNINativeMethod gMethods[] = {
|
||||||
{"jniCreateTun", "(Ljava/lang/String;)I", (void*)create},
|
{"jniCreateTunTap", "(ZLjava/lang/String;)I", (void*)create},
|
||||||
};
|
};
|
||||||
|
|
||||||
int register_android_server_TestNetworkService(JNIEnv* env) {
|
int register_android_server_TestNetworkService(JNIEnv* env) {
|
||||||
|
|||||||
Reference in New Issue
Block a user