Loading services/java/com/android/server/connectivity/Vpn.java +7 −20 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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); Loading Loading @@ -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"); } } Loading Loading @@ -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); Loading Loading @@ -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) { Loading @@ -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(); } } Loading services/jni/com_android_server_connectivity_Vpn.cpp +60 −102 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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: Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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}, Loading Loading
services/java/com/android/server/connectivity/Vpn.java +7 −20 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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); Loading Loading @@ -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"); } } Loading Loading @@ -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); Loading Loading @@ -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) { Loading @@ -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(); } } Loading
services/jni/com_android_server_connectivity_Vpn.cpp +60 −102 Original line number Diff line number Diff line Loading @@ -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); Loading Loading @@ -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: Loading @@ -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); Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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) Loading Loading @@ -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}, Loading