Merge "Use token to identify IKE Session" am: 2775f8a1d1 am: 86c048a4d7
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2083849 Change-Id: Ic59d8564b97086ddf66e951524c86c09ef311d4c Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -2593,13 +2593,13 @@ public class Vpn {
|
|||||||
|
|
||||||
void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp);
|
void onDefaultNetworkLinkPropertiesChanged(@NonNull LinkProperties lp);
|
||||||
|
|
||||||
void onChildOpened(
|
void onDefaultNetworkLost(@NonNull Network network);
|
||||||
@NonNull Network network, @NonNull ChildSessionConfiguration childConfig);
|
|
||||||
|
|
||||||
void onChildTransformCreated(
|
void onChildOpened(int token, @NonNull ChildSessionConfiguration childConfig);
|
||||||
@NonNull Network network, @NonNull IpSecTransform transform, int direction);
|
|
||||||
|
|
||||||
void onSessionLost(@NonNull Network network, @Nullable Exception exception);
|
void onChildTransformCreated(int token, @NonNull IpSecTransform transform, int direction);
|
||||||
|
|
||||||
|
void onSessionLost(int token, @Nullable Exception exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -2646,6 +2646,13 @@ public class Vpn {
|
|||||||
/** Signal to ensure shutdown is honored even if a new Network is connected. */
|
/** Signal to ensure shutdown is honored even if a new Network is connected. */
|
||||||
private boolean mIsRunning = true;
|
private boolean mIsRunning = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The token used by the primary/current/active IKE session.
|
||||||
|
*
|
||||||
|
* <p>This token MUST be updated when the VPN switches to use a new IKE session.
|
||||||
|
*/
|
||||||
|
private int mCurrentToken = -1;
|
||||||
|
|
||||||
@Nullable private IpSecTunnelInterface mTunnelIface;
|
@Nullable private IpSecTunnelInterface mTunnelIface;
|
||||||
@Nullable private IkeSession mSession;
|
@Nullable private IkeSession mSession;
|
||||||
@Nullable private Network mActiveNetwork;
|
@Nullable private Network mActiveNetwork;
|
||||||
@@ -2699,22 +2706,25 @@ public class Vpn {
|
|||||||
return Objects.equals(mActiveNetwork, network) && mIsRunning;
|
return Objects.equals(mActiveNetwork, network) && mIsRunning;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isActiveToken(int token) {
|
||||||
|
return (mCurrentToken == token) && mIsRunning;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when an IKE Child session has been opened, signalling completion of the startup.
|
* Called when an IKE Child session has been opened, signalling completion of the startup.
|
||||||
*
|
*
|
||||||
* <p>This method is only ever called once per IkeSession, and MUST run on the mExecutor
|
* <p>This method is only ever called once per IkeSession, and MUST run on the mExecutor
|
||||||
* thread in order to ensure consistency of the Ikev2VpnRunner fields.
|
* thread in order to ensure consistency of the Ikev2VpnRunner fields.
|
||||||
*/
|
*/
|
||||||
public void onChildOpened(
|
public void onChildOpened(int token, @NonNull ChildSessionConfiguration childConfig) {
|
||||||
@NonNull Network network, @NonNull ChildSessionConfiguration childConfig) {
|
if (!isActiveToken(token)) {
|
||||||
if (!isActiveNetwork(network)) {
|
Log.d(TAG, "onChildOpened called for obsolete token " + token);
|
||||||
Log.d(TAG, "onOpened called for obsolete network " + network);
|
|
||||||
|
|
||||||
// Do nothing; this signals that either: (1) a new/better Network was found,
|
// Do nothing; this signals that either: (1) a new/better Network was found,
|
||||||
// and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this
|
// and the Ikev2VpnRunner has switched to it by restarting a new IKE session in
|
||||||
// IKE session was already shut down (exited, or an error was encountered somewhere
|
// onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited,
|
||||||
// else). In both cases, all resources and sessions are torn down via
|
// or an error was encountered somewhere else). In both cases, all resources and
|
||||||
// resetIkeState().
|
// sessions are torn down via resetIkeState().
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2751,7 +2761,7 @@ public class Vpn {
|
|||||||
mConfig.dnsServers.clear();
|
mConfig.dnsServers.clear();
|
||||||
mConfig.dnsServers.addAll(dnsAddrStrings);
|
mConfig.dnsServers.addAll(dnsAddrStrings);
|
||||||
|
|
||||||
mConfig.underlyingNetworks = new Network[] {network};
|
mConfig.underlyingNetworks = new Network[] {mActiveNetwork};
|
||||||
|
|
||||||
mConfig.disallowedApplications = getAppExclusionList(mPackage);
|
mConfig.disallowedApplications = getAppExclusionList(mPackage);
|
||||||
|
|
||||||
@@ -2767,7 +2777,8 @@ public class Vpn {
|
|||||||
return; // Link properties are already sent.
|
return; // Link properties are already sent.
|
||||||
} else {
|
} else {
|
||||||
// Underlying networks also set in agentConnect()
|
// Underlying networks also set in agentConnect()
|
||||||
networkAgent.setUnderlyingNetworks(Collections.singletonList(network));
|
networkAgent.setUnderlyingNetworks(
|
||||||
|
Collections.singletonList(mActiveNetwork));
|
||||||
}
|
}
|
||||||
|
|
||||||
lp = makeLinkProperties(); // Accesses VPN instance fields; must be locked
|
lp = makeLinkProperties(); // Accesses VPN instance fields; must be locked
|
||||||
@@ -2775,8 +2786,8 @@ public class Vpn {
|
|||||||
|
|
||||||
networkAgent.sendLinkProperties(lp);
|
networkAgent.sendLinkProperties(lp);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.d(TAG, "Error in ChildOpened for network " + network, e);
|
Log.d(TAG, "Error in ChildOpened for token " + token, e);
|
||||||
onSessionLost(network, e);
|
onSessionLost(token, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2788,15 +2799,15 @@ public class Vpn {
|
|||||||
* consistency of the Ikev2VpnRunner fields.
|
* consistency of the Ikev2VpnRunner fields.
|
||||||
*/
|
*/
|
||||||
public void onChildTransformCreated(
|
public void onChildTransformCreated(
|
||||||
@NonNull Network network, @NonNull IpSecTransform transform, int direction) {
|
int token, @NonNull IpSecTransform transform, int direction) {
|
||||||
if (!isActiveNetwork(network)) {
|
if (!isActiveToken(token)) {
|
||||||
Log.d(TAG, "ChildTransformCreated for obsolete network " + network);
|
Log.d(TAG, "ChildTransformCreated for obsolete token " + token);
|
||||||
|
|
||||||
// Do nothing; this signals that either: (1) a new/better Network was found,
|
// Do nothing; this signals that either: (1) a new/better Network was found,
|
||||||
// and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this
|
// and the Ikev2VpnRunner has switched to it by restarting a new IKE session in
|
||||||
// IKE session was already shut down (exited, or an error was encountered somewhere
|
// onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited,
|
||||||
// else). In both cases, all resources and sessions are torn down via
|
// or an error was encountered somewhere else). In both cases, all resources and
|
||||||
// resetIkeState().
|
// sessions are torn down via resetIkeState().
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2805,8 +2816,8 @@ public class Vpn {
|
|||||||
// them alive for us
|
// them alive for us
|
||||||
mIpSecManager.applyTunnelModeTransform(mTunnelIface, direction, transform);
|
mIpSecManager.applyTunnelModeTransform(mTunnelIface, direction, transform);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.d(TAG, "Transform application failed for network " + network, e);
|
Log.d(TAG, "Transform application failed for token " + token, e);
|
||||||
onSessionLost(network, e);
|
onSessionLost(token, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2864,19 +2875,21 @@ public class Vpn {
|
|||||||
network);
|
network);
|
||||||
NetdUtils.setInterfaceUp(mNetd, mTunnelIface.getInterfaceName());
|
NetdUtils.setInterfaceUp(mNetd, mTunnelIface.getInterfaceName());
|
||||||
|
|
||||||
mSession = mIkev2SessionCreator.createIkeSession(
|
final int token = ++mCurrentToken;
|
||||||
mContext,
|
mSession =
|
||||||
ikeSessionParams,
|
mIkev2SessionCreator.createIkeSession(
|
||||||
childSessionParams,
|
mContext,
|
||||||
mExecutor,
|
ikeSessionParams,
|
||||||
new VpnIkev2Utils.IkeSessionCallbackImpl(
|
childSessionParams,
|
||||||
TAG, IkeV2VpnRunner.this, network),
|
mExecutor,
|
||||||
new VpnIkev2Utils.ChildSessionCallbackImpl(
|
new VpnIkev2Utils.IkeSessionCallbackImpl(
|
||||||
TAG, IkeV2VpnRunner.this, network));
|
TAG, IkeV2VpnRunner.this, token),
|
||||||
Log.d(TAG, "Ike Session started for network " + network);
|
new VpnIkev2Utils.ChildSessionCallbackImpl(
|
||||||
|
TAG, IkeV2VpnRunner.this, token));
|
||||||
|
Log.d(TAG, "IKE session started for token " + token);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.i(TAG, "Setup failed for network " + network + ". Aborting", e);
|
Log.i(TAG, "Setup failed for token " + mCurrentToken + ". Aborting", e);
|
||||||
onSessionLost(network, e);
|
onSessionLost(mCurrentToken, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2890,6 +2903,29 @@ public class Vpn {
|
|||||||
mUnderlyingLinkProperties = lp;
|
mUnderlyingLinkProperties = lp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles loss of the default underlying network
|
||||||
|
*
|
||||||
|
* <p>The Ikev2VpnRunner will kill the IKE session and reset the VPN.
|
||||||
|
*
|
||||||
|
* <p>This method MUST always be called on the mExecutor thread in order to ensure
|
||||||
|
* consistency of the Ikev2VpnRunner fields.
|
||||||
|
*/
|
||||||
|
public void onDefaultNetworkLost(@NonNull Network network) {
|
||||||
|
if (!isActiveNetwork(network)) {
|
||||||
|
Log.d(TAG, "onDefaultNetworkLost called for obsolete network " + network);
|
||||||
|
|
||||||
|
// Do nothing; this signals that either: (1) a new/better Network was found,
|
||||||
|
// and the Ikev2VpnRunner has switched to it by restarting a new IKE session in
|
||||||
|
// onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited,
|
||||||
|
// or an error was encountered somewhere else). In both cases, all resources and
|
||||||
|
// sessions are torn down via resetIkeState().
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSessionLost(null);
|
||||||
|
}
|
||||||
|
|
||||||
/** Marks the state as FAILED, and disconnects. */
|
/** Marks the state as FAILED, and disconnects. */
|
||||||
private void markFailedAndDisconnect(Exception exception) {
|
private void markFailedAndDisconnect(Exception exception) {
|
||||||
synchronized (Vpn.this) {
|
synchronized (Vpn.this) {
|
||||||
@@ -2908,18 +2944,22 @@ public class Vpn {
|
|||||||
* <p>This method MUST always be called on the mExecutor thread in order to ensure
|
* <p>This method MUST always be called on the mExecutor thread in order to ensure
|
||||||
* consistency of the Ikev2VpnRunner fields.
|
* consistency of the Ikev2VpnRunner fields.
|
||||||
*/
|
*/
|
||||||
public void onSessionLost(@NonNull Network network, @Nullable Exception exception) {
|
public void onSessionLost(int token, @Nullable Exception exception) {
|
||||||
if (!isActiveNetwork(network)) {
|
if (!isActiveToken(token)) {
|
||||||
Log.d(TAG, "onSessionLost() called for obsolete network " + network);
|
Log.d(TAG, "onSessionLost() called for obsolete token " + token);
|
||||||
|
|
||||||
// Do nothing; this signals that either: (1) a new/better Network was found,
|
// Do nothing; this signals that either: (1) a new/better Network was found,
|
||||||
// and the Ikev2VpnRunner has switched to it in onDefaultNetworkChanged, or (2) this
|
// and the Ikev2VpnRunner has switched to it by restarting a new IKE session in
|
||||||
// IKE session was already shut down (exited, or an error was encountered somewhere
|
// onDefaultNetworkChanged, or (2) this IKE session was already shut down (exited,
|
||||||
// else). In both cases, all resources and sessions are torn down via
|
// or an error was encountered somewhere else). In both cases, all resources and
|
||||||
// onSessionLost() and resetIkeState().
|
// sessions are torn down via resetIkeState().
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleSessionLost(exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSessionLost(@Nullable Exception exception) {
|
||||||
synchronized (Vpn.this) {
|
synchronized (Vpn.this) {
|
||||||
if (exception instanceof IkeProtocolException) {
|
if (exception instanceof IkeProtocolException) {
|
||||||
final IkeProtocolException ikeException = (IkeProtocolException) exception;
|
final IkeProtocolException ikeException = (IkeProtocolException) exception;
|
||||||
@@ -3037,7 +3077,7 @@ public class Vpn {
|
|||||||
|
|
||||||
// Close all obsolete state, but keep VPN alive incase a usable network comes up.
|
// Close all obsolete state, but keep VPN alive incase a usable network comes up.
|
||||||
// (Mirrors VpnService behavior)
|
// (Mirrors VpnService behavior)
|
||||||
Log.d(TAG, "Resetting state for network: " + network);
|
Log.d(TAG, "Resetting state for token: " + mCurrentToken);
|
||||||
|
|
||||||
synchronized (Vpn.this) {
|
synchronized (Vpn.this) {
|
||||||
// Since this method handles non-fatal errors only, set mInterface to null to
|
// Since this method handles non-fatal errors only, set mInterface to null to
|
||||||
|
|||||||
@@ -298,35 +298,35 @@ public class VpnIkev2Utils {
|
|||||||
static class IkeSessionCallbackImpl implements IkeSessionCallback {
|
static class IkeSessionCallbackImpl implements IkeSessionCallback {
|
||||||
private final String mTag;
|
private final String mTag;
|
||||||
private final Vpn.IkeV2VpnRunnerCallback mCallback;
|
private final Vpn.IkeV2VpnRunnerCallback mCallback;
|
||||||
private final Network mNetwork;
|
private final int mToken;
|
||||||
|
|
||||||
IkeSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, Network network) {
|
IkeSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, int token) {
|
||||||
mTag = tag;
|
mTag = tag;
|
||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
mNetwork = network;
|
mToken = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOpened(@NonNull IkeSessionConfiguration ikeSessionConfig) {
|
public void onOpened(@NonNull IkeSessionConfiguration ikeSessionConfig) {
|
||||||
Log.d(mTag, "IkeOpened for network " + mNetwork);
|
Log.d(mTag, "IkeOpened for token " + mToken);
|
||||||
// Nothing to do here.
|
// Nothing to do here.
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClosed() {
|
public void onClosed() {
|
||||||
Log.d(mTag, "IkeClosed for network " + mNetwork);
|
Log.d(mTag, "IkeClosed for token " + mToken);
|
||||||
mCallback.onSessionLost(mNetwork, null); // Server requested session closure. Retry?
|
mCallback.onSessionLost(mToken, null); // Server requested session closure. Retry?
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClosedExceptionally(@NonNull IkeException exception) {
|
public void onClosedExceptionally(@NonNull IkeException exception) {
|
||||||
Log.d(mTag, "IkeClosedExceptionally for network " + mNetwork, exception);
|
Log.d(mTag, "IkeClosedExceptionally for token " + mToken, exception);
|
||||||
mCallback.onSessionLost(mNetwork, exception);
|
mCallback.onSessionLost(mToken, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(@NonNull IkeProtocolException exception) {
|
public void onError(@NonNull IkeProtocolException exception) {
|
||||||
Log.d(mTag, "IkeError for network " + mNetwork, exception);
|
Log.d(mTag, "IkeError for token " + mToken, exception);
|
||||||
// Non-fatal, log and continue.
|
// Non-fatal, log and continue.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -334,36 +334,36 @@ public class VpnIkev2Utils {
|
|||||||
static class ChildSessionCallbackImpl implements ChildSessionCallback {
|
static class ChildSessionCallbackImpl implements ChildSessionCallback {
|
||||||
private final String mTag;
|
private final String mTag;
|
||||||
private final Vpn.IkeV2VpnRunnerCallback mCallback;
|
private final Vpn.IkeV2VpnRunnerCallback mCallback;
|
||||||
private final Network mNetwork;
|
private final int mToken;
|
||||||
|
|
||||||
ChildSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, Network network) {
|
ChildSessionCallbackImpl(String tag, Vpn.IkeV2VpnRunnerCallback callback, int token) {
|
||||||
mTag = tag;
|
mTag = tag;
|
||||||
mCallback = callback;
|
mCallback = callback;
|
||||||
mNetwork = network;
|
mToken = token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOpened(@NonNull ChildSessionConfiguration childConfig) {
|
public void onOpened(@NonNull ChildSessionConfiguration childConfig) {
|
||||||
Log.d(mTag, "ChildOpened for network " + mNetwork);
|
Log.d(mTag, "ChildOpened for token " + mToken);
|
||||||
mCallback.onChildOpened(mNetwork, childConfig);
|
mCallback.onChildOpened(mToken, childConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClosed() {
|
public void onClosed() {
|
||||||
Log.d(mTag, "ChildClosed for network " + mNetwork);
|
Log.d(mTag, "ChildClosed for token " + mToken);
|
||||||
mCallback.onSessionLost(mNetwork, null);
|
mCallback.onSessionLost(mToken, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClosedExceptionally(@NonNull IkeException exception) {
|
public void onClosedExceptionally(@NonNull IkeException exception) {
|
||||||
Log.d(mTag, "ChildClosedExceptionally for network " + mNetwork, exception);
|
Log.d(mTag, "ChildClosedExceptionally for token " + mToken, exception);
|
||||||
mCallback.onSessionLost(mNetwork, exception);
|
mCallback.onSessionLost(mToken, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onIpSecTransformCreated(@NonNull IpSecTransform transform, int direction) {
|
public void onIpSecTransformCreated(@NonNull IpSecTransform transform, int direction) {
|
||||||
Log.d(mTag, "ChildTransformCreated; Direction: " + direction + "; network " + mNetwork);
|
Log.d(mTag, "ChildTransformCreated; Direction: " + direction + "; token " + mToken);
|
||||||
mCallback.onChildTransformCreated(mNetwork, transform, direction);
|
mCallback.onChildTransformCreated(mToken, transform, direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -371,8 +371,7 @@ public class VpnIkev2Utils {
|
|||||||
// Nothing to be done; no references to the IpSecTransform are held by the
|
// Nothing to be done; no references to the IpSecTransform are held by the
|
||||||
// Ikev2VpnRunner (or this callback class), and this transform will be closed by the
|
// Ikev2VpnRunner (or this callback class), and this transform will be closed by the
|
||||||
// IKE library.
|
// IKE library.
|
||||||
Log.d(mTag,
|
Log.d(mTag, "ChildTransformDeleted; Direction: " + direction + "; for token " + mToken);
|
||||||
"ChildTransformDeleted; Direction: " + direction + "; for network " + mNetwork);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -412,8 +411,8 @@ public class VpnIkev2Utils {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onLost(@NonNull Network network) {
|
public void onLost(@NonNull Network network) {
|
||||||
Log.d(mTag, "Tearing down; lost network: " + network);
|
Log.d(mTag, "onLost called for network: " + network);
|
||||||
mExecutor.execute(() -> mCallback.onSessionLost(network, null));
|
mExecutor.execute(() -> mCallback.onDefaultNetworkLost(network));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user