diff options
author | Sreeram Ramachandran <sreeram@google.com> | 2014-07-27 14:18:26 -0700 |
---|---|---|
committer | Sreeram Ramachandran <sreeram@google.com> | 2014-07-29 00:32:59 +0000 |
commit | f4e0c0cb8ef22fdb20ae74b444c9f4b7d15ded8b (patch) | |
tree | 1fb3018075ae25c501f410129faca4f4db1ba9d7 /services | |
parent | 4789e41a9fb2817ef15df054a1d029b042e8e1d0 (diff) | |
download | frameworks_base-f4e0c0cb8ef22fdb20ae74b444c9f4b7d15ded8b.zip frameworks_base-f4e0c0cb8ef22fdb20ae74b444c9f4b7d15ded8b.tar.gz frameworks_base-f4e0c0cb8ef22fdb20ae74b444c9f4b7d15ded8b.tar.bz2 |
Allow VPNs to add/remove link addresses dynamically.
Bug: 15409819
Change-Id: If91fc6891d7ce04060362c6cde8c57462394c4e8
Diffstat (limited to 'services')
4 files changed, 113 insertions, 2 deletions
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java index 55070bb..428d857 100644 --- a/services/core/java/com/android/server/ConnectivityService.java +++ b/services/core/java/com/android/server/ConnectivityService.java @@ -5351,4 +5351,22 @@ public class ConnectivityService extends IConnectivityManager.Stub { } return new NetworkCapabilities(); } + + @Override + public boolean addVpnAddress(String address, int prefixLength) { + throwIfLockdownEnabled(); + int user = UserHandle.getUserId(Binder.getCallingUid()); + synchronized (mVpns) { + return mVpns.get(user).addAddress(address, prefixLength); + } + } + + @Override + public boolean removeVpnAddress(String address, int prefixLength) { + throwIfLockdownEnabled(); + int user = UserHandle.getUserId(Binder.getCallingUid()); + synchronized (mVpns) { + return mVpns.get(user).removeAddress(address, prefixLength); + } + } } diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 0a8ca6a..b9dd609 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -83,8 +83,9 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.InetAddress; import java.net.Inet4Address; +import java.net.Inet6Address; +import java.net.InetAddress; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; @@ -754,11 +755,53 @@ public class Vpn { } } + public synchronized boolean addAddress(String address, int prefixLength) { + if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) { + return false; + } + boolean success = jniAddAddress(mInterface, address, prefixLength); + if (success && (!mAllowIPv4 || !mAllowIPv6)) { + try { + InetAddress inetAddress = InetAddress.parseNumericAddress(address); + if ((inetAddress instanceof Inet4Address) && !mAllowIPv4) { + mAllowIPv4 = true; + mNetworkAgent.unblockAddressFamily(AF_INET); + } else if ((inetAddress instanceof Inet6Address) && !mAllowIPv6) { + mAllowIPv6 = true; + mNetworkAgent.unblockAddressFamily(AF_INET6); + } + } catch (IllegalArgumentException e) { + // ignore + } + } + // Ideally, we'd call mNetworkAgent.sendLinkProperties() here to notify ConnectivityService + // that the LinkAddress has changed. But we don't do so for two reasons: (1) We don't set + // LinkAddresses on the LinkProperties we establish in the first place (see agentConnect()) + // and (2) CS doesn't do anything with LinkAddresses anyway (see updateLinkProperties()). + // TODO: Maybe fix this. + return success; + } + + public synchronized boolean removeAddress(String address, int prefixLength) { + if (Binder.getCallingUid() != mOwnerUID || mInterface == null || mNetworkAgent == null) { + return false; + } + boolean success = jniDelAddress(mInterface, address, prefixLength); + // Ideally, we'd call mNetworkAgent.sendLinkProperties() here to notify ConnectivityService + // that the LinkAddress has changed. But we don't do so for two reasons: (1) We don't set + // LinkAddresses on the LinkProperties we establish in the first place (see agentConnect()) + // and (2) CS doesn't do anything with LinkAddresses anyway (see updateLinkProperties()). + // TODO: Maybe fix this. + return success; + } + private native int jniCreate(int mtu); private native String jniGetName(int tun); private native int jniSetAddresses(String interfaze, String addresses); private native void jniReset(String interfaze); private native int jniCheck(String interfaze); + private native boolean jniAddAddress(String interfaze, String address, int prefixLen); + private native boolean jniDelAddress(String interfaze, String address, int prefixLen); private static RouteInfo findIPv4DefaultRoute(LinkProperties prop) { for (RouteInfo route : prop.getAllRoutes()) { diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk index 9a4d900..1f377c7 100644 --- a/services/core/jni/Android.mk +++ b/services/core/jni/Android.mk @@ -61,5 +61,6 @@ LOCAL_SHARED_LIBRARIES += \ libusbhost \ libsuspend \ libEGL \ - libGLESv2 + libGLESv2 \ + libnetutils \ diff --git a/services/core/jni/com_android_server_connectivity_Vpn.cpp b/services/core/jni/com_android_server_connectivity_Vpn.cpp index 6031906..2a16dfe 100644 --- a/services/core/jni/com_android_server_connectivity_Vpn.cpp +++ b/services/core/jni/com_android_server_connectivity_Vpn.cpp @@ -18,6 +18,7 @@ #define LOG_TAG "VpnJni" #include <cutils/log.h> +#include "netutils/ifc.h" #include <stdio.h> #include <string.h> @@ -212,6 +213,40 @@ static int check_interface(const char *name) return ifr4.ifr_flags; } +static bool modifyAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddress, + jint jPrefixLength, bool add) +{ + int error = SYSTEM_ERROR; + const char *name = jName ? env->GetStringUTFChars(jName, NULL) : NULL; + const char *address = jAddress ? env->GetStringUTFChars(jAddress, NULL) : NULL; + + if (!name) { + jniThrowNullPointerException(env, "name"); + } else if (!address) { + jniThrowNullPointerException(env, "address"); + } else { + if (add) { + if (error = ifc_add_address(name, address, jPrefixLength)) { + ALOGE("Cannot add address %s/%d on interface %s (%s)", address, jPrefixLength, name, + strerror(-error)); + } + } else { + if (error = ifc_del_address(name, address, jPrefixLength)) { + ALOGE("Cannot del address %s/%d on interface %s (%s)", address, jPrefixLength, name, + strerror(-error)); + } + } + } + + if (name) { + env->ReleaseStringUTFChars(jName, name); + } + if (address) { + env->ReleaseStringUTFChars(jAddress, address); + } + return !error; +} + //------------------------------------------------------------------------------ static void throwException(JNIEnv *env, int error, const char *message) @@ -301,6 +336,18 @@ static jint check(JNIEnv *env, jobject thiz, jstring jName) return flags; } +static bool addAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddress, + jint jPrefixLength) +{ + return modifyAddress(env, thiz, jName, jAddress, jPrefixLength, true); +} + +static bool delAddress(JNIEnv *env, jobject thiz, jstring jName, jstring jAddress, + jint jPrefixLength) +{ + return modifyAddress(env, thiz, jName, jAddress, jPrefixLength, false); +} + //------------------------------------------------------------------------------ static JNINativeMethod gMethods[] = { @@ -309,6 +356,8 @@ static JNINativeMethod gMethods[] = { {"jniSetAddresses", "(Ljava/lang/String;Ljava/lang/String;)I", (void *)setAddresses}, {"jniReset", "(Ljava/lang/String;)V", (void *)reset}, {"jniCheck", "(Ljava/lang/String;)I", (void *)check}, + {"jniAddAddress", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)addAddress}, + {"jniDelAddress", "(Ljava/lang/String;Ljava/lang/String;I)Z", (void *)delAddress}, }; int register_android_server_connectivity_Vpn(JNIEnv *env) |