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

Commit 3281034c authored by Chia-chi Yeh's avatar Chia-chi Yeh
Browse files

VPN: merge JNI methods.

Legacy VPN needs to change routes by itself.

Change-Id: I4cf6639f2b00225810f49704ae05797fc70921d9
parent e9107901
Loading
Loading
Loading
Loading
+7 −20
Original line number Diff line number Diff line
@@ -177,16 +177,10 @@ public class Vpn extends INetworkManagementEventObserver.Stub {
        }

        // Configure the interface. Abort if any of these steps fails.
        ParcelFileDescriptor descriptor =
                ParcelFileDescriptor.adoptFd(jniCreateInterface(config.mtu));
        ParcelFileDescriptor descriptor = ParcelFileDescriptor.adoptFd(
                jniConfigure(config.mtu, config.addresses, config.routes));
        try {
            String name = jniGetInterfaceName(descriptor.getFd());
            if (jniSetAddresses(name, config.addresses) < 1) {
                throw new IllegalArgumentException("At least one address must be specified");
            }
            if (config.routes != null) {
                jniSetRoutes(name, config.routes);
            }
            if (mInterfaceName != null && !mInterfaceName.equals(name)) {
                jniResetInterface(mInterfaceName);
            }
@@ -269,10 +263,8 @@ public class Vpn extends INetworkManagementEventObserver.Stub {
        }
    }

    private native int jniCreateInterface(int mtu);
    private native int jniConfigure(int mtu, String addresses, String routes);
    private native String jniGetInterfaceName(int fd);
    private native int jniSetAddresses(String name, String addresses);
    private native int jniSetRoutes(String name, String routes);
    private native void jniResetInterface(String name);
    private native int jniCheckInterface(String name);
    private native void jniProtectSocket(int fd, String name);
@@ -354,7 +346,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub {
            } else if (now - mTimer <= 30000) {
                Thread.sleep(yield ? 200 : 1);
            } else {
                throw new InterruptedException("timeout");
                throw new InterruptedException("time is up");
            }
        }

@@ -433,7 +425,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub {
                    for (String argument : arguments) {
                        byte[] bytes = argument.getBytes(Charsets.UTF_8);
                        if (bytes.length >= 0xFFFF) {
                            throw new IllegalArgumentException("argument too large");
                            throw new IllegalArgumentException("argument is too large");
                        }
                        out.write(bytes.length >> 8);
                        out.write(bytes.length);
@@ -477,12 +469,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub {
                    }
                }

                // TODO: support routes and search domains from IPSec Mode-CFG.

                // Set the routes as requested.
                if (mConfig.routes != null) {
                    jniSetRoutes(mConfig.interfaceName, mConfig.routes);
                }
                // TODO: support search domains from ISAKMP mode config.

                // The final step must be synchronized.
                synchronized (Vpn.this) {
@@ -501,7 +488,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub {
                }
                Log.i(TAG, "Connected!");
            } catch (Exception e) {
                Log.i(TAG, "Abort due to " + e.getMessage());
                Log.i(TAG, "Abort because " + e.getMessage());
                exit();
            }
        }
+60 −102
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ static inline in_addr_t *as_in_addr(sockaddr *sa) {
#define SYSTEM_ERROR -1
#define BAD_ARGUMENT -2

static int create_interface(int mtu)
static int create_interface(char *name, int *index, int mtu)
{
    int tun = open("/dev/tun", O_RDWR | O_NONBLOCK);

@@ -82,6 +82,14 @@ static int create_interface(int mtu)
        goto error;
    }

    // Get interface index.
    if (ioctl(inet4, SIOGIFINDEX, &ifr4)) {
        LOGE("Cannot get index of %s: %s", ifr4.ifr_name, strerror(errno));
        goto error;
    }

    strncpy(name, ifr4.ifr_name, IFNAMSIZ);
    *index = ifr4.ifr_ifindex;
    return tun;

error:
@@ -89,35 +97,8 @@ error:
    return SYSTEM_ERROR;
}

static int get_interface_name(char *name, int tun)
static int set_addresses(const char *name, int index, const char *addresses)
{
    ifreq ifr4;
    if (ioctl(tun, TUNGETIFF, &ifr4)) {
        LOGE("Cannot get interface name: %s", strerror(errno));
        return SYSTEM_ERROR;
    }
    strncpy(name, ifr4.ifr_name, IFNAMSIZ);
    return 0;
}

static int get_interface_index(const char *name)
{
    ifreq ifr4;
    strncpy(ifr4.ifr_name, name, IFNAMSIZ);
    if (ioctl(inet4, SIOGIFINDEX, &ifr4)) {
        LOGE("Cannot get index of %s: %s", name, strerror(errno));
        return SYSTEM_ERROR;
    }
    return ifr4.ifr_ifindex;
}

static int set_addresses(const char *name, const char *addresses)
{
    int index = get_interface_index(name);
    if (index < 0) {
        return index;
    }

    ifreq ifr4;
    memset(&ifr4, 0, sizeof(ifr4));
    strncpy(ifr4.ifr_name, name, IFNAMSIZ);
@@ -187,13 +168,8 @@ static int set_addresses(const char *name, const char *addresses)
    return count;
}

static int set_routes(const char *name, const char *routes)
static int set_routes(const char *name, int index, const char *routes)
{
    int index = get_interface_index(name);
    if (index < 0) {
        return index;
    }

    rtentry rt4;
    memset(&rt4, 0, sizeof(rt4));
    rt4.rt_dev = (char *)name;
@@ -277,6 +253,17 @@ static int set_routes(const char *name, const char *routes)
    return count;
}

static int get_interface_name(char *name, int tun)
{
    ifreq ifr4;
    if (ioctl(tun, TUNGETIFF, &ifr4)) {
        LOGE("Cannot get interface name: %s", strerror(errno));
        return SYSTEM_ERROR;
    }
    strncpy(name, ifr4.ifr_name, IFNAMSIZ);
    return 0;
}

static int reset_interface(const char *name)
{
    ifreq ifr4;
@@ -322,90 +309,63 @@ static void throwException(JNIEnv *env, int error, const char *message)
    }
}

static jint createInterface(JNIEnv *env, jobject thiz, jint mtu)
static jint configure(JNIEnv *env, jobject thiz,
        jint mtu, jstring jAddresses, jstring jRoutes)
{
    int tun = create_interface(mtu);
    char name[IFNAMSIZ];
    int index;
    int tun = create_interface(name, &index, mtu);
    if (tun < 0) {
        throwException(env, tun, "Cannot create interface");
        return -1;
    }
    return tun;
}

static jstring getInterfaceName(JNIEnv *env, jobject thiz, jint tun)
{
    char name[IFNAMSIZ];
    if (get_interface_name(name, tun) < 0) {
        throwException(env, SYSTEM_ERROR, "Cannot get interface name");
        return NULL;
    }
    return env->NewStringUTF(name);
}

static jint setAddresses(JNIEnv *env, jobject thiz, jstring jName,
        jstring jAddresses)
{
    const char *name = NULL;
    const char *addresses = NULL;
    int count = -1;
    const char *routes = NULL;
    int count;

    name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
    if (!name) {
        jniThrowNullPointerException(env, "name");
        goto error;
    }
    // At least one address must be set.
    addresses = jAddresses ? env->GetStringUTFChars(jAddresses, NULL) : NULL;
    if (!addresses) {
        jniThrowNullPointerException(env, "addresses");
        jniThrowNullPointerException(env, "address");
        goto error;
    }
    count = set_addresses(name, addresses);
    if (count < 0) {
        throwException(env, count, "Cannot set address");
        count = -1;
    }

error:
    if (name) {
        env->ReleaseStringUTFChars(jName, name);
    }
    if (addresses) {
    count = set_addresses(name, index, addresses);
    env->ReleaseStringUTFChars(jAddresses, addresses);
    }
    return count;
}

static jint setRoutes(JNIEnv *env, jobject thiz, jstring jName,
        jstring jRoutes)
{
    const char *name = NULL;
    const char *routes = NULL;
    int count = -1;

    name = jName ? env->GetStringUTFChars(jName, NULL) : NULL;
    if (!name) {
        jniThrowNullPointerException(env, "name");
    if (count <= 0) {
        throwException(env, count, "Cannot set address");
        goto error;
    }
    LOGD("Configured %d address(es) on %s", count, name);

    // On the contrary, routes are optional.
    routes = jRoutes ? env->GetStringUTFChars(jRoutes, NULL) : NULL;
    if (!routes) {
        jniThrowNullPointerException(env, "routes");
        goto error;
    }
    count = set_routes(name, routes);
    if (routes) {
        count = set_routes(name, index, routes);
        env->ReleaseStringUTFChars(jRoutes, routes);
        if (count < 0) {
            throwException(env, count, "Cannot set route");
        count = -1;
            goto error;
        }
        LOGD("Configured %d route(s) on %s", count, name);
    }

    return tun;

error:
    if (name) {
        env->ReleaseStringUTFChars(jName, name);
    close(tun);
    LOGD("%s is destroyed", name);
    return -1;
}
    if (routes) {
        env->ReleaseStringUTFChars(jRoutes, routes);

static jstring getInterfaceName(JNIEnv *env, jobject thiz, jint tun)
{
    char name[IFNAMSIZ];
    if (get_interface_name(name, tun) < 0) {
        throwException(env, SYSTEM_ERROR, "Cannot get interface name");
        return NULL;
    }
    return count;
    return env->NewStringUTF(name);
}

static void resetInterface(JNIEnv *env, jobject thiz, jstring jName)
@@ -449,10 +409,8 @@ static void protectSocket(JNIEnv *env, jobject thiz, jint fd, jstring jName)
//------------------------------------------------------------------------------

static JNINativeMethod gMethods[] = {
    {"jniCreateInterface", "(I)I", (void *)createInterface},
    {"jniConfigure", "(ILjava/lang/String;Ljava/lang/String;)I", (void *)configure},
    {"jniGetInterfaceName", "(I)Ljava/lang/String;", (void *)getInterfaceName},
    {"jniSetAddresses", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setAddresses},
    {"jniSetRoutes", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setRoutes},
    {"jniResetInterface", "(Ljava/lang/String;)V", (void *)resetInterface},
    {"jniCheckInterface", "(Ljava/lang/String;)I", (void *)checkInterface},
    {"jniProtectSocket", "(ILjava/lang/String;)V", (void *)protectSocket},