summaryrefslogtreecommitdiffstats
path: root/services
diff options
context:
space:
mode:
authorSreeram Ramachandran <sreeram@google.com>2014-07-27 14:18:26 -0700
committerSreeram Ramachandran <sreeram@google.com>2014-07-29 00:32:59 +0000
commitf4e0c0cb8ef22fdb20ae74b444c9f4b7d15ded8b (patch)
tree1fb3018075ae25c501f410129faca4f4db1ba9d7 /services
parent4789e41a9fb2817ef15df054a1d029b042e8e1d0 (diff)
downloadframeworks_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')
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java18
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java45
-rw-r--r--services/core/jni/Android.mk3
-rw-r--r--services/core/jni/com_android_server_connectivity_Vpn.cpp49
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)