summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Lorenzo Colitti <lorenzo@google.com> 2022-06-02 10:12:53 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-06-02 10:12:53 +0000
commit839756e661372f5280e0fbd123d6a7d154c75360 (patch)
tree6e6063f43e2d8176b9df614530daeff94f12e2c5
parent0d7f8cebd3609ca8b679bf5bf53909052aec0b97 (diff)
parent63b2a309ec234e6cc59dc2c03b0d31870ef2cb1e (diff)
Merge changes from topic "vpnmanager-events-T" into tm-dev
* changes: Address leftover comments of ag/18108411 Address leftover comments of ag/18112116 Rename vars of Ikev2VpnRunner Send VPN manager event when there is a network error Send VPN manager event when there is an IkeProtocolException
-rw-r--r--services/core/java/com/android/server/connectivity/Vpn.java217
-rw-r--r--services/core/java/com/android/server/connectivity/VpnIkev2Utils.java24
2 files changed, 195 insertions, 46 deletions
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 254a3226e6de..2ab68409a80f 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -88,7 +88,10 @@ import android.net.ipsec.ike.IkeSession;
import android.net.ipsec.ike.IkeSessionCallback;
import android.net.ipsec.ike.IkeSessionParams;
import android.net.ipsec.ike.IkeTunnelConnectionParams;
+import android.net.ipsec.ike.exceptions.IkeNetworkLostException;
+import android.net.ipsec.ike.exceptions.IkeNonProtocolException;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
+import android.net.ipsec.ike.exceptions.IkeTimeoutException;
import android.os.Binder;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
@@ -760,31 +763,36 @@ public class Vpn {
// Also notify the new package if there was a provider change.
final boolean shouldNotifyNewPkg = isVpnApp(packageName) && isPackageChanged;
- if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownAllowlist)) {
- saveAlwaysOnPackage();
- // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
- // ConnectivityServiceTest.
- if (shouldNotifyOldPkg && SdkLevel.isAtLeastT()) {
- // If both of shouldNotifyOldPkg & isPackageChanged are true, which means the
- // always-on of old package is disabled or the old package is replaced with the new
- // package. In this case, VpnProfileState should be disconnected.
- sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED,
- -1 /* errorClass */, -1 /* errorCode*/, oldPackage,
- null /* sessionKey */, isPackageChanged ? makeDisconnectedVpnProfileState()
- : makeVpnProfileStateLocked(),
- null /* underlyingNetwork */, null /* nc */, null /* lp */);
- }
- // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
- // ConnectivityServiceTest.
- if (shouldNotifyNewPkg && SdkLevel.isAtLeastT()) {
- sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED,
- -1 /* errorClass */, -1 /* errorCode*/, packageName,
- getSessionKeyLocked(), makeVpnProfileStateLocked(),
- null /* underlyingNetwork */, null /* nc */, null /* lp */);
- }
+ if (!setAlwaysOnPackageInternal(packageName, lockdown, lockdownAllowlist)) {
+ return false;
+ }
+
+ saveAlwaysOnPackage();
+
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from
+ // ConnectivityServiceTest.
+ if (!SdkLevel.isAtLeastT()) {
return true;
}
- return false;
+
+ if (shouldNotifyOldPkg) {
+ // If both of shouldNotifyOldPkg & isPackageChanged are true, that means the
+ // always-on of old package is disabled or the old package is replaced with the new
+ // package. In this case, VpnProfileState should be disconnected.
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED,
+ -1 /* errorClass */, -1 /* errorCode*/, oldPackage,
+ null /* sessionKey */, isPackageChanged ? makeDisconnectedVpnProfileState()
+ : makeVpnProfileStateLocked(),
+ null /* underlyingNetwork */, null /* nc */, null /* lp */);
+ }
+
+ if (shouldNotifyNewPkg) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_ALWAYS_ON_STATE_CHANGED,
+ -1 /* errorClass */, -1 /* errorCode*/, packageName,
+ getSessionKeyLocked(), makeVpnProfileStateLocked(),
+ null /* underlyingNetwork */, null /* nc */, null /* lp */);
+ }
+ return true;
}
/**
@@ -2530,6 +2538,21 @@ public class Vpn {
}
}
+ @Nullable
+ protected synchronized NetworkCapabilities getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ NetworkCapabilities nc) {
+ if (nc == null) return null;
+ return mConnectivityManager.getRedactedNetworkCapabilitiesForPackage(
+ nc, mOwnerUID, mPackage);
+ }
+
+ @Nullable
+ protected synchronized LinkProperties getRedactedLinkPropertiesOfUnderlyingNetwork(
+ LinkProperties lp) {
+ if (lp == null) return null;
+ return mConnectivityManager.getRedactedLinkPropertiesForPackage(lp, mOwnerUID, mPackage);
+ }
+
/** This class represents the common interface for all VPN runners. */
@VisibleForTesting
abstract class VpnRunner extends Thread {
@@ -2564,6 +2587,10 @@ public class Vpn {
interface IkeV2VpnRunnerCallback {
void onDefaultNetworkChanged(@NonNull Network network);
+ void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc);
+
+ void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp);
+
void onChildOpened(
@NonNull Network network, @NonNull ChildSessionConfiguration childConfig);
@@ -2620,14 +2647,14 @@ public class Vpn {
@Nullable private IpSecTunnelInterface mTunnelIface;
@Nullable private IkeSession mSession;
@Nullable private Network mActiveNetwork;
+ @Nullable private NetworkCapabilities mUnderlyingNetworkCapabilities;
+ @Nullable private LinkProperties mUnderlyingLinkProperties;
private final String mSessionKey;
IkeV2VpnRunner(@NonNull Ikev2VpnProfile profile) {
super(TAG);
mProfile = profile;
mIpSecManager = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
- // Pass mExecutor into Ikev2VpnNetworkCallback and make sure that IkeV2VpnRunnerCallback
- // will be called by the mExecutor thread.
mNetworkCallback = new VpnIkev2Utils.Ikev2VpnNetworkCallback(TAG, this, mExecutor);
mSessionKey = UUID.randomUUID().toString();
}
@@ -2849,6 +2876,16 @@ public class Vpn {
}
}
+ /** Called when the NetworkCapabilities of underlying network is changed */
+ public void onDefaultNetworkCapabilitiesChanged(@NonNull NetworkCapabilities nc) {
+ mUnderlyingNetworkCapabilities = nc;
+ }
+
+ /** Called when the LinkProperties of underlying network is changed */
+ public void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp) {
+ mUnderlyingLinkProperties = lp;
+ }
+
/** Marks the state as FAILED, and disconnects. */
private void markFailedAndDisconnect(Exception exception) {
synchronized (Vpn.this) {
@@ -2879,28 +2916,120 @@ public class Vpn {
return;
}
- if (exception instanceof IkeProtocolException) {
- final IkeProtocolException ikeException = (IkeProtocolException) exception;
-
- switch (ikeException.getErrorType()) {
- case IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN: // Fallthrough
- case IkeProtocolException.ERROR_TYPE_INVALID_KE_PAYLOAD: // Fallthrough
- case IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED: // Fallthrough
- case IkeProtocolException.ERROR_TYPE_SINGLE_PAIR_REQUIRED: // Fallthrough
- case IkeProtocolException.ERROR_TYPE_FAILED_CP_REQUIRED: // Fallthrough
- case IkeProtocolException.ERROR_TYPE_TS_UNACCEPTABLE:
- // All the above failures are configuration errors, and are terminal
- markFailedAndDisconnect(exception);
- return;
- // All other cases possibly recoverable.
+ synchronized (Vpn.this) {
+ if (exception instanceof IkeProtocolException) {
+ final IkeProtocolException ikeException = (IkeProtocolException) exception;
+
+ switch (ikeException.getErrorType()) {
+ case IkeProtocolException.ERROR_TYPE_NO_PROPOSAL_CHOSEN: // Fallthrough
+ case IkeProtocolException.ERROR_TYPE_INVALID_KE_PAYLOAD: // Fallthrough
+ case IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED: // Fallthrough
+ case IkeProtocolException.ERROR_TYPE_SINGLE_PAIR_REQUIRED: // Fallthrough
+ case IkeProtocolException.ERROR_TYPE_FAILED_CP_REQUIRED: // Fallthrough
+ case IkeProtocolException.ERROR_TYPE_TS_UNACCEPTABLE:
+ // All the above failures are configuration errors, and are terminal
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are
+ // decoupled from ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_IKE_ERROR,
+ VpnManager.ERROR_CLASS_NOT_RECOVERABLE,
+ ikeException.getErrorType(),
+ getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+ mActiveNetwork,
+ getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ mUnderlyingNetworkCapabilities),
+ getRedactedLinkPropertiesOfUnderlyingNetwork(
+ mUnderlyingLinkProperties));
+ }
+ markFailedAndDisconnect(exception);
+ return;
+ // All other cases possibly recoverable.
+ default:
+ // All the above failures are configuration errors, and are terminal
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are
+ // decoupled from ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_IKE_ERROR,
+ VpnManager.ERROR_CLASS_RECOVERABLE,
+ ikeException.getErrorType(),
+ getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+ mActiveNetwork,
+ getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ mUnderlyingNetworkCapabilities),
+ getRedactedLinkPropertiesOfUnderlyingNetwork(
+ mUnderlyingLinkProperties));
+ }
+ }
+ } else if (exception instanceof IllegalArgumentException) {
+ // Failed to build IKE/ChildSessionParams; fatal profile configuration error
+ markFailedAndDisconnect(exception);
+ return;
+ } else if (exception instanceof IkeNetworkLostException) {
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are
+ // decoupled from ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
+ VpnManager.ERROR_CLASS_RECOVERABLE,
+ VpnManager.ERROR_CODE_NETWORK_LOST,
+ getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+ mActiveNetwork,
+ getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ mUnderlyingNetworkCapabilities),
+ getRedactedLinkPropertiesOfUnderlyingNetwork(
+ mUnderlyingLinkProperties));
+ }
+ } else if (exception instanceof IkeNonProtocolException) {
+ if (exception.getCause() instanceof UnknownHostException) {
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are
+ // decoupled from ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
+ VpnManager.ERROR_CLASS_RECOVERABLE,
+ VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST,
+ getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+ mActiveNetwork,
+ getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ mUnderlyingNetworkCapabilities),
+ getRedactedLinkPropertiesOfUnderlyingNetwork(
+ mUnderlyingLinkProperties));
+ }
+ } else if (exception.getCause() instanceof IkeTimeoutException) {
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are
+ // decoupled from ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
+ VpnManager.ERROR_CLASS_RECOVERABLE,
+ VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT,
+ getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+ mActiveNetwork,
+ getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ mUnderlyingNetworkCapabilities),
+ getRedactedLinkPropertiesOfUnderlyingNetwork(
+ mUnderlyingLinkProperties));
+ }
+ } else if (exception.getCause() instanceof IOException) {
+ // TODO(b/230548427): Remove SDK check once VPN related stuff are
+ // decoupled from ConnectivityServiceTest.
+ if (SdkLevel.isAtLeastT()) {
+ sendEventToVpnManagerApp(VpnManager.CATEGORY_EVENT_NETWORK_ERROR,
+ VpnManager.ERROR_CLASS_RECOVERABLE,
+ VpnManager.ERROR_CODE_NETWORK_IO,
+ getPackage(), mSessionKey, makeVpnProfileStateLocked(),
+ mActiveNetwork,
+ getRedactedNetworkCapabilitiesOfUnderlyingNetwork(
+ mUnderlyingNetworkCapabilities),
+ getRedactedLinkPropertiesOfUnderlyingNetwork(
+ mUnderlyingLinkProperties));
+ }
+ }
+ } else if (exception != null) {
+ Log.wtf(TAG, "onSessionLost: exception = " + exception);
}
- } else if (exception instanceof IllegalArgumentException) {
- // Failed to build IKE/ChildSessionParams; fatal profile configuration error
- markFailedAndDisconnect(exception);
- return;
}
mActiveNetwork = null;
+ mUnderlyingNetworkCapabilities = null;
+ mUnderlyingLinkProperties = null;
// Close all obsolete state, but keep VPN alive incase a usable network comes up.
// (Mirrors VpnService behavior)
@@ -2965,6 +3094,8 @@ public class Vpn {
*/
private void disconnectVpnRunner() {
mActiveNetwork = null;
+ mUnderlyingNetworkCapabilities = null;
+ mUnderlyingLinkProperties = null;
mIsRunning = false;
resetIkeState();
diff --git a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
index 6982d6095689..17058282d947 100644
--- a/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
+++ b/services/core/java/com/android/server/connectivity/VpnIkev2Utils.java
@@ -50,7 +50,9 @@ import android.net.InetAddresses;
import android.net.IpPrefix;
import android.net.IpSecAlgorithm;
import android.net.IpSecTransform;
+import android.net.LinkProperties;
import android.net.Network;
+import android.net.NetworkCapabilities;
import android.net.RouteInfo;
import android.net.eap.EapSessionConfig;
import android.net.ipsec.ike.ChildSaProposal;
@@ -86,7 +88,7 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
-import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executor;
/**
* Utility class to build and convert IKEv2/IPsec parameters.
@@ -377,10 +379,10 @@ public class VpnIkev2Utils {
static class Ikev2VpnNetworkCallback extends NetworkCallback {
private final String mTag;
private final Vpn.IkeV2VpnRunnerCallback mCallback;
- private final ExecutorService mExecutor;
+ private final Executor mExecutor;
Ikev2VpnNetworkCallback(String tag, Vpn.IkeV2VpnRunnerCallback callback,
- ExecutorService executor) {
+ Executor executor) {
mTag = tag;
mCallback = callback;
mExecutor = executor;
@@ -393,6 +395,22 @@ public class VpnIkev2Utils {
}
@Override
+ public void onCapabilitiesChanged(@NonNull Network network,
+ @NonNull NetworkCapabilities networkCapabilities) {
+ Log.d(mTag, "NC changed for net " + network + " : " + networkCapabilities);
+ mExecutor.execute(
+ () -> mCallback.onDefaultNetworkCapabilitiesChanged(networkCapabilities));
+ }
+
+ @Override
+ public void onLinkPropertiesChanged(@NonNull Network network,
+ @NonNull LinkProperties linkProperties) {
+ Log.d(mTag, "LP changed for net " + network + " : " + linkProperties);
+ mExecutor.execute(
+ () -> mCallback.onDefaultNetworkLinkPropertiesChanged(linkProperties));
+ }
+
+ @Override
public void onLost(@NonNull Network network) {
Log.d(mTag, "Tearing down; lost network: " + network);
mExecutor.execute(() -> mCallback.onSessionLost(network, null));