Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5c7c6a4b authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by Android (Google) Code Review
Browse files

Merge "Add support for TAP interfaces in TestNetworkManager." into qt-dev

parents f9585ca9 0b77c83f
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1365,6 +1365,7 @@ package android.net {
  }

  public class TestNetworkManager {
    method public android.net.TestNetworkInterface createTapInterface();
    method public android.net.TestNetworkInterface createTunInterface(@NonNull android.net.LinkAddress[]);
    method public void setupTestNetwork(@NonNull String, @NonNull android.os.IBinder);
    method public void teardownTestNetwork(@NonNull android.net.Network);
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import android.os.ParcelFileDescriptor;
interface ITestNetworkManager
{
    TestNetworkInterface createTunInterface(in LinkAddress[] linkAddrs);
    TestNetworkInterface createTapInterface();

    void setupTestNetwork(in String iface, in IBinder binder);

+17 −0
Original line number Diff line number Diff line
@@ -88,4 +88,21 @@ public class TestNetworkManager {
            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();
        }
    }

}
+31 −8
Original line number Diff line number Diff line
@@ -60,6 +60,7 @@ class TestNetworkService extends ITestNetworkManager.Stub {
    @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_TUN_PREFIX = "testtun";
    @NonNull private static final String TEST_TAP_PREFIX = "testtap";
    @NonNull private static final AtomicInteger sTestTunIndex = new AtomicInteger();

    @NonNull private final Context mContext;
@@ -70,7 +71,7 @@ class TestNetworkService extends ITestNetworkManager.Stub {
    @NonNull private final Handler mHandler;

    // Native method stubs
    private static native int jniCreateTun(@NonNull String iface);
    private static native int jniCreateTunTap(boolean isTun, @NonNull String iface);

    @VisibleForTesting
    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
     * TUN interface.
     * <p>This method will return the FileDescriptor to the interface. Close it to tear down the
     * interface.
     */
    @Override
    public TestNetworkInterface createTunInterface(@NonNull LinkAddress[] linkAddrs) {
    private TestNetworkInterface createInterface(boolean isTun, LinkAddress[] linkAddrs) {
        enforceTestNetworkPermissions(mContext);

        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(
                () -> {
                    try {
                        ParcelFileDescriptor tunIntf =
                                ParcelFileDescriptor.adoptFd(jniCreateTun(iface));
                                ParcelFileDescriptor.adoptFd(jniCreateTunTap(isTun, iface));
                        for (LinkAddress addr : linkAddrs) {
                            mNetd.interfaceAddAddress(
                                    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
    @GuardedBy("mTestNetworkTracker")
    @NonNull
+6 −6
Original line number Diff line number Diff line
@@ -54,12 +54,12 @@ static void throwException(JNIEnv* env, int error, const char* action, const cha
    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));
    ifreq ifr{};

    // 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);
    if (ioctl(tun.get(), TUNSETIFF, &ifr)) {
        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);
    if (!iface.c_str()) {
        jniThrowNullPointerException(env, "iface");
        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;
}

//------------------------------------------------------------------------------

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) {