490 lines
22 KiB
Java
490 lines
22 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2019 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
package android.net.ipsec.ike;
|
||
|
|
||
|
import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_NONE;
|
||
|
import static android.net.ipsec.ike.IkeSessionParams.ESP_ENCAP_TYPE_UDP;
|
||
|
import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_IPV4;
|
||
|
import static android.net.ipsec.ike.IkeSessionParams.ESP_IP_VERSION_IPV6;
|
||
|
import static android.net.ipsec.ike.IkeSessionParams.IKE_NATT_KEEPALIVE_DELAY_SEC_MAX;
|
||
|
import static android.net.ipsec.ike.IkeSessionParams.IKE_NATT_KEEPALIVE_DELAY_SEC_MIN;
|
||
|
|
||
|
import android.annotation.FlaggedApi;
|
||
|
import android.annotation.IntRange;
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.SuppressLint;
|
||
|
import android.annotation.SystemApi;
|
||
|
import android.content.Context;
|
||
|
import android.content.pm.PackageManager;
|
||
|
import android.net.IpSecManager;
|
||
|
import android.net.Network;
|
||
|
import android.net.ipsec.ike.exceptions.IkeException;
|
||
|
import android.os.HandlerThread;
|
||
|
import android.os.Looper;
|
||
|
import android.util.CloseGuard;
|
||
|
|
||
|
import com.android.internal.annotations.VisibleForTesting;
|
||
|
import com.android.internal.net.ipsec.ike.IkeSessionStateMachine;
|
||
|
|
||
|
import java.io.PrintWriter;
|
||
|
import java.util.Objects;
|
||
|
import java.util.concurrent.Executor;
|
||
|
|
||
|
/**
|
||
|
* This class represents an IKE Session management object that allows for keying and management of
|
||
|
* {@link android.net.IpSecTransform}s.
|
||
|
*
|
||
|
* <p>An IKE/Child Session represents an IKE/Child SA as well as its rekeyed successors. A Child
|
||
|
* Session is bounded by the lifecycle of the IKE Session under which it is set up. Closing an IKE
|
||
|
* Session implicitly closes any remaining Child Sessions under it.
|
||
|
*
|
||
|
* <p>An IKE procedure is one or multiple IKE message exchanges that are used to create, delete or
|
||
|
* rekey an IKE Session or Child Session.
|
||
|
*
|
||
|
* <p>This class provides methods for initiating IKE procedures, such as the Creation and Deletion
|
||
|
* of a Child Session, or the Deletion of the IKE session. All procedures (except for IKE deletion)
|
||
|
* will be initiated sequentially after IKE Session is set up.
|
||
|
*
|
||
|
* @see <a href="https://tools.ietf.org/html/rfc7296">RFC 7296, Internet Key Exchange Protocol
|
||
|
* Version 2 (IKEv2)</a>
|
||
|
*/
|
||
|
public final class IkeSession implements AutoCloseable {
|
||
|
private final CloseGuard mCloseGuard = new CloseGuard();
|
||
|
private final Context mContext;
|
||
|
|
||
|
/**
|
||
|
* Attribution tag for IWLAN callers
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final String CONTEXT_ATTRIBUTION_TAG_IWLAN = "IWLAN";
|
||
|
|
||
|
/**
|
||
|
* Attribution tag for VCN callers
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final String CONTEXT_ATTRIBUTION_TAG_VCN = "VCN";
|
||
|
|
||
|
/**
|
||
|
* Attribution tag for VPN callers
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
public static final String CONTEXT_ATTRIBUTION_TAG_VPN = "VPN_MANAGER";
|
||
|
|
||
|
@VisibleForTesting final IkeSessionStateMachine mIkeSessionStateMachine;
|
||
|
|
||
|
/**
|
||
|
* Constructs a new IKE session.
|
||
|
*
|
||
|
* <p>This method will immediately return an instance of {@link IkeSession} and asynchronously
|
||
|
* initiate the setup procedure of {@link IkeSession} as well as its first Child Session.
|
||
|
* Callers will be notified of these two setup results via the callback arguments.
|
||
|
*
|
||
|
* <p>FEATURE_IPSEC_TUNNELS is required for setting up a tunnel mode Child SA.
|
||
|
*
|
||
|
* @param context a valid {@link Context} instance.
|
||
|
* @param ikeSessionParams the {@link IkeSessionParams} that contains a set of valid {@link
|
||
|
* IkeSession} configurations.
|
||
|
* @param firstChildSessionParams the {@link ChildSessionParams} that contains a set of valid
|
||
|
* configurations for the first Child Session.
|
||
|
* @param userCbExecutor the {@link Executor} upon which all callbacks will be posted. For
|
||
|
* security and consistency, the callbacks posted to this executor MUST be executed serially
|
||
|
* and in the order they were posted, as guaranteed by executors such as {@link
|
||
|
* java.util.concurrent.Executors#newSingleThreadExecutor()}
|
||
|
* @param ikeSessionCallback the {@link IkeSessionCallback} interface to notify callers of state
|
||
|
* changes within the {@link IkeSession}.
|
||
|
* @param firstChildSessionCallback the {@link ChildSessionCallback} interface to notify callers
|
||
|
* of state changes within the first Child Session.
|
||
|
* @return an instance of {@link IkeSession}.
|
||
|
*/
|
||
|
public IkeSession(
|
||
|
@NonNull Context context,
|
||
|
@NonNull IkeSessionParams ikeSessionParams,
|
||
|
@NonNull ChildSessionParams firstChildSessionParams,
|
||
|
@NonNull Executor userCbExecutor,
|
||
|
@NonNull IkeSessionCallback ikeSessionCallback,
|
||
|
@NonNull ChildSessionCallback firstChildSessionCallback) {
|
||
|
this(
|
||
|
context,
|
||
|
(IpSecManager) context.getSystemService(Context.IPSEC_SERVICE),
|
||
|
ikeSessionParams,
|
||
|
firstChildSessionParams,
|
||
|
userCbExecutor,
|
||
|
ikeSessionCallback,
|
||
|
firstChildSessionCallback);
|
||
|
}
|
||
|
|
||
|
/** Package private */
|
||
|
@VisibleForTesting
|
||
|
IkeSession(
|
||
|
Context context,
|
||
|
IpSecManager ipSecManager,
|
||
|
IkeSessionParams ikeSessionParams,
|
||
|
ChildSessionParams firstChildSessionParams,
|
||
|
Executor userCbExecutor,
|
||
|
IkeSessionCallback ikeSessionCallback,
|
||
|
ChildSessionCallback firstChildSessionCallback) {
|
||
|
this(
|
||
|
IkeThreadHolder.IKE_WORKER_THREAD.getLooper(),
|
||
|
context,
|
||
|
ipSecManager,
|
||
|
ikeSessionParams,
|
||
|
firstChildSessionParams,
|
||
|
userCbExecutor,
|
||
|
ikeSessionCallback,
|
||
|
firstChildSessionCallback);
|
||
|
}
|
||
|
|
||
|
/** Package private */
|
||
|
@VisibleForTesting
|
||
|
IkeSession(
|
||
|
Looper looper,
|
||
|
Context context,
|
||
|
IpSecManager ipSecManager,
|
||
|
IkeSessionParams ikeSessionParams,
|
||
|
ChildSessionParams firstChildSessionParams,
|
||
|
Executor userCbExecutor,
|
||
|
IkeSessionCallback ikeSessionCallback,
|
||
|
ChildSessionCallback firstChildSessionCallback) {
|
||
|
mContext = context;
|
||
|
|
||
|
if (firstChildSessionParams instanceof TunnelModeChildSessionParams) {
|
||
|
checkTunnelFeatureOrThrow(mContext);
|
||
|
}
|
||
|
|
||
|
mIkeSessionStateMachine =
|
||
|
new IkeSessionStateMachine(
|
||
|
looper,
|
||
|
context,
|
||
|
ipSecManager,
|
||
|
ikeSessionParams,
|
||
|
firstChildSessionParams,
|
||
|
userCbExecutor,
|
||
|
ikeSessionCallback,
|
||
|
firstChildSessionCallback);
|
||
|
mIkeSessionStateMachine.openSession();
|
||
|
|
||
|
mCloseGuard.open("open");
|
||
|
}
|
||
|
|
||
|
/** @hide */
|
||
|
@Override
|
||
|
public void finalize() {
|
||
|
if (mCloseGuard != null) {
|
||
|
mCloseGuard.warnIfOpen();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void checkTunnelFeatureOrThrow(Context context) {
|
||
|
// TODO(b/157754168): Also check if OP_MANAGE_IPSEC_TUNNELS is granted when it is exposed
|
||
|
if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_IPSEC_TUNNELS)) {
|
||
|
throw new IllegalStateException(
|
||
|
"Cannot set up tunnel mode Child SA due to FEATURE_IPSEC_TUNNELS missing");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** Initialization-on-demand holder */
|
||
|
private static class IkeThreadHolder {
|
||
|
static final HandlerThread IKE_WORKER_THREAD;
|
||
|
|
||
|
static {
|
||
|
IKE_WORKER_THREAD = new HandlerThread("IkeWorkerThread");
|
||
|
IKE_WORKER_THREAD.start();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// TODO: b/133340675 Destroy the worker thread when there is no more alive {@link IkeSession}.
|
||
|
|
||
|
/**
|
||
|
* Request a new Child Session.
|
||
|
*
|
||
|
* <p>Users MUST provide a unique {@link ChildSessionCallback} instance for each new Child
|
||
|
* Session.
|
||
|
*
|
||
|
* <p>Upon setup, {@link ChildSessionCallback#onOpened(ChildSessionConfiguration)} will be
|
||
|
* fired.
|
||
|
*
|
||
|
* <p>FEATURE_IPSEC_TUNNELS is required for setting up a tunnel mode Child SA.
|
||
|
*
|
||
|
* @param childSessionParams the {@link ChildSessionParams} that contains the Child Session
|
||
|
* configurations to negotiate.
|
||
|
* @param childSessionCallback the {@link ChildSessionCallback} interface to notify users the
|
||
|
* state changes of the Child Session. It will be posted to the callback {@link Executor} of
|
||
|
* this {@link IkeSession}.
|
||
|
* @throws IllegalArgumentException if the ChildSessionCallback is already in use.
|
||
|
*/
|
||
|
// The childSessionCallback will be called on the same executor as was passed in the constructor
|
||
|
// for security reasons.
|
||
|
@SuppressLint("ExecutorRegistration")
|
||
|
public void openChildSession(
|
||
|
@NonNull ChildSessionParams childSessionParams,
|
||
|
@NonNull ChildSessionCallback childSessionCallback) {
|
||
|
if (childSessionParams instanceof TunnelModeChildSessionParams) {
|
||
|
checkTunnelFeatureOrThrow(mContext);
|
||
|
}
|
||
|
|
||
|
mIkeSessionStateMachine.openChildSession(childSessionParams, childSessionCallback);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Delete a Child Session.
|
||
|
*
|
||
|
* <p>Upon closure, {@link ChildSessionCallback#onClosed()} will be fired.
|
||
|
*
|
||
|
* @param childSessionCallback The {@link ChildSessionCallback} instance that uniquely identify
|
||
|
* the Child Session.
|
||
|
* @throws IllegalArgumentException if no Child Session found bound with this callback.
|
||
|
*/
|
||
|
// The childSessionCallback will be called on the same executor as was passed in the constructor
|
||
|
// for security reasons.
|
||
|
@SuppressLint("ExecutorRegistration")
|
||
|
public void closeChildSession(@NonNull ChildSessionCallback childSessionCallback) {
|
||
|
mIkeSessionStateMachine.closeChildSession(childSessionCallback);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Close the IKE session gracefully.
|
||
|
*
|
||
|
* <p>Implements {@link AutoCloseable#close()}
|
||
|
*
|
||
|
* <p>Upon closure, {@link IkeSessionCallback#onClosed()} or {@link
|
||
|
* IkeSessionCallback#onClosedWithException(IkeException)} will be fired.
|
||
|
*
|
||
|
* <p>Closing an IKE Session implicitly closes any remaining Child Sessions negotiated under it.
|
||
|
* Users SHOULD stop all outbound traffic that uses these Child Sessions ({@link
|
||
|
* android.net.IpSecTransform} pairs) before calling this method. Otherwise IPsec packets will
|
||
|
* be dropped due to the lack of a valid {@link android.net.IpSecTransform}.
|
||
|
*
|
||
|
* <p>Closure of an IKE session will take priority over, and cancel other procedures waiting in
|
||
|
* the queue (but will wait for ongoing locally initiated procedures to complete). After sending
|
||
|
* the Delete request, the IKE library will wait until a Delete response is received or
|
||
|
* retransmission timeout occurs.
|
||
|
*/
|
||
|
@Override
|
||
|
public void close() {
|
||
|
mCloseGuard.close();
|
||
|
mIkeSessionStateMachine.closeSession();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Terminate (forcibly close) the IKE session.
|
||
|
*
|
||
|
* <p>Upon closing, {@link IkeSessionCallback#onClosed()} will be fired.
|
||
|
*
|
||
|
* <p>Closing an IKE Session implicitly closes any remaining Child Sessions negotiated under it.
|
||
|
* Users SHOULD stop all outbound traffic that uses these Child Sessions ({@link
|
||
|
* android.net.IpSecTransform} pairs) before calling this method. Otherwise IPsec packets will
|
||
|
* be dropped due to the lack of a valid {@link android.net.IpSecTransform}.
|
||
|
*
|
||
|
* <p>Forcible closure of an IKE session will take priority over, and cancel other procedures
|
||
|
* waiting in the queue. It will also interrupt any ongoing locally initiated procedure.
|
||
|
*/
|
||
|
public void kill() {
|
||
|
mCloseGuard.close();
|
||
|
mIkeSessionStateMachine.killSession();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Update the IkeSession's underlying Network to use the specified Network.
|
||
|
*
|
||
|
* @see #setNetwork(Network, int, int)
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
public void setNetwork(@NonNull Network network) {
|
||
|
setNetwork(network, IkeSessionParams.ESP_IP_VERSION_AUTO,
|
||
|
IkeSessionParams.ESP_ENCAP_TYPE_AUTO,
|
||
|
IkeSessionParams.NATT_KEEPALIVE_INTERVAL_AUTO);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Update the IkeSession's underlying Network, protocol preference and keepalive delay.
|
||
|
*
|
||
|
* <p>Updating the IkeSession's Network also updates the Network for any Child Sessions created
|
||
|
* with this IkeSession. To perform the update, callers must implement:
|
||
|
*
|
||
|
* <ul>
|
||
|
* <li>{@link IkeSessionCallback#onIkeSessionConnectionInfoChanged(IkeSessionConnectionInfo)}:
|
||
|
* This call will be triggered once the IKE Session has been updated. The implementation
|
||
|
* MUST migrate all IpSecTunnelInterface instances associated with this IkeSession via
|
||
|
* {@link android.net.IpSecManager.IpSecTunnelInterface#setUnderlyingNetwork(Network)}
|
||
|
* <li>{@link ChildSessionCallback#onIpSecTransformsMigrated(android.net.IpSecTransform,
|
||
|
* android.net.IpSecTransform)}: This call will be triggered once a Child Session has been
|
||
|
* updated. The implementation MUST re-apply the migrated transforms to the {@link
|
||
|
* android.net.IpSecManager.IpSecTunnelInterface} associated with this
|
||
|
* ChildSessionCallback, via {@link android.net.IpSecManager#applyTunnelModeTransform(
|
||
|
* android.net.IpSecManager.IpSecTunnelInterface, int, android.net.IpSecTransform)}.
|
||
|
* </ul>
|
||
|
*
|
||
|
* <p>In order for Network migration to be possible, the following must be true:
|
||
|
*
|
||
|
* <ul>
|
||
|
* <li>the {@link IkeSessionParams} for this IkeSession must be configured with {@link
|
||
|
* IkeSessionParams#IKE_OPTION_MOBIKE} (set via {@link
|
||
|
* IkeSessionParams.Builder#addIkeOption(int)}), and
|
||
|
* <li>the IkeSession must have been started with the Network specified via {@link
|
||
|
* IkeSessionParams.Builder#setNetwork(Network)}.
|
||
|
* </ul>
|
||
|
*
|
||
|
* <p>As MOBIKE support is negotiated, callers are advised to check for MOBIKE support in {@link
|
||
|
* IkeSessionConfiguration} before calling this method to update the network. Failure to do so
|
||
|
* may cause this call to be ignored.
|
||
|
*
|
||
|
* @see <a href="https://tools.ietf.org/html/rfc4555">RFC 4555, IKEv2 Mobility and Multihoming
|
||
|
* Protocol (MOBIKE)</a>
|
||
|
* @param network the Network to use for this IkeSession
|
||
|
* @param ipVersion the IP version to use for ESP packets
|
||
|
* @param encapType the encapsulation type to use for ESP packets
|
||
|
* @param keepaliveDelaySeconds the keepalive delay in seconds, or NATT_KEEPALIVE_INTERVAL_AUTO
|
||
|
* to choose the value automatically based on the network.
|
||
|
* @throws IllegalStateException if {@link IkeSessionParams#IKE_OPTION_MOBIKE} is not configured
|
||
|
* in IkeSessionParams, or if the Network was not specified in IkeSessionParams.
|
||
|
* @throws UnsupportedOperationException if the provided option is not supported.
|
||
|
* @see IkeSessionParams#getNattKeepAliveDelaySeconds()
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||
|
public void setNetwork(
|
||
|
@NonNull Network network,
|
||
|
@IkeSessionParams.EspIpVersion int ipVersion,
|
||
|
@IkeSessionParams.EspEncapType int encapType,
|
||
|
// Is there a way to specify an intrange + a sentinel value ?
|
||
|
@IntRange(
|
||
|
from = IKE_NATT_KEEPALIVE_DELAY_SEC_MIN,
|
||
|
to = IKE_NATT_KEEPALIVE_DELAY_SEC_MAX)
|
||
|
int keepaliveDelaySeconds) {
|
||
|
if ((ipVersion == ESP_IP_VERSION_IPV4 && encapType == ESP_ENCAP_TYPE_NONE)
|
||
|
|| (ipVersion == ESP_IP_VERSION_IPV6 && encapType == ESP_ENCAP_TYPE_UDP)) {
|
||
|
throw new UnsupportedOperationException("Sending packets with IPv4 ESP or IPv6 UDP"
|
||
|
+ " are not supported");
|
||
|
}
|
||
|
|
||
|
mIkeSessionStateMachine.setNetwork(Objects.requireNonNull(network),
|
||
|
ipVersion, encapType, keepaliveDelaySeconds);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Inform the session that it is used to supply the passed network.
|
||
|
*
|
||
|
* This will be used by the session when it needs to perform actions that depend on what
|
||
|
* network this session is underpinning. In particular, this can be used to turn off
|
||
|
* keepalives when there are no connections open on the underpinned network, if the
|
||
|
* {@link IkeSessionParams#IKE_OPTION_AUTOMATIC_KEEPALIVE_ON_OFF} option is turned on.
|
||
|
*
|
||
|
* @param underpinnedNetwork the network underpinned by this session.
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
|
||
|
public void setUnderpinnedNetwork(@NonNull Network underpinnedNetwork) {
|
||
|
mIkeSessionStateMachine.setUnderpinnedNetwork(Objects.requireNonNull(underpinnedNetwork));
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Request to check liveness of peer.
|
||
|
*
|
||
|
* <p>This method returns immediately and asynchronously,
|
||
|
*
|
||
|
* <p>The liveness check determines whether a peer is alive by executing a new on-demand DPD
|
||
|
* task or joining an existing running task depending on the situation.
|
||
|
*
|
||
|
* <ul>
|
||
|
* <li>If there is no running task when a liveness check request is called, a new on-demand
|
||
|
* DPD task is started. The on-demand DPD (Dead Peer Detection) is used for checking
|
||
|
* liveness of peer in this case. This method adds an on-demand DPD request to the work
|
||
|
* queue to check that the peer is alive. The on-demand DPD uses retransmit timeouts from
|
||
|
* {@link IkeSessionParams#getLivenessRetransmissionTimeoutsMillis}.
|
||
|
* <li>If any IKE message is already in progress when a client requests a liveness check, the
|
||
|
* liveness check request is joined to an existing running task. And then the liveness
|
||
|
* check runs in the background. When a running task receives a valid IKE message packet
|
||
|
* from a peer, it can verify that the peer is alive in the background without triggering
|
||
|
* an on-demand DPD task. A running task uses retransmit timeouts from {@link
|
||
|
* IkeSessionParams#getRetransmissionTimeoutsMillis}.
|
||
|
* </ul>
|
||
|
*
|
||
|
* <p>The client is notified of the progress or result statuses of the liveness check via {@link
|
||
|
* IkeSessionCallback#onLivenessStatusChanged}. These statuses are notified after a liveness
|
||
|
* check request is started. By notifying {@link
|
||
|
* IkeSessionCallback.LivenessStatus#LIVENESS_STATUS_SUCCESS} or {@link
|
||
|
* IkeSessionCallback.LivenessStatus#LIVENESS_STATUS_FAILURE}, the liveness check request is
|
||
|
* done and no further status notification is made until the next {@link
|
||
|
* IkeSession#requestLivenessCheck}. The status notifications to the client are as follows.
|
||
|
*
|
||
|
* <ul>
|
||
|
* <li>{@link IkeSessionCallback.LivenessStatus#LIVENESS_STATUS_ON_DEMAND_STARTED}: This
|
||
|
* status is called when liveness checking is started with a new on-demand DPD task.
|
||
|
* <li>{@link IkeSessionCallback.LivenessStatus#LIVENESS_STATUS_ON_DEMAND_ONGOING}: This
|
||
|
* status is called when liveness checking is already running in an on-demand DPD task.
|
||
|
* <li>{@link IkeSessionCallback.LivenessStatus#LIVENESS_STATUS_BACKGROUND_STARTED}: This
|
||
|
* status is called when liveness checking is started in the background and has joined an
|
||
|
* existing running task.
|
||
|
* <li>{@link IkeSessionCallback.LivenessStatus#LIVENESS_STATUS_BACKGROUND_ONGOING}: This
|
||
|
* status is called when liveness checking is already running in the background by joining
|
||
|
* an existing running task.
|
||
|
* <li>{@link IkeSessionCallback.LivenessStatus#LIVENESS_STATUS_SUCCESS}: This status is
|
||
|
* called when the peer's liveness is proven. Once this status is notified, the liveness
|
||
|
* check request is done and no further status notification is made until the next {@link
|
||
|
* IkeSession#requestLivenessCheck}.
|
||
|
* <li>{@link IkeSessionCallback.LivenessStatus#LIVENESS_STATUS_FAILURE}: This state is called
|
||
|
* when the peer is determined as dead for a liveness check request. After this status is
|
||
|
* notified, the IkeSession will be closed immediately by calling {@link
|
||
|
* IkeSessionCallback#onClosedWithException} with {@link
|
||
|
* android.net.ipsec.ike.exceptions.IkeTimeoutException} in the {@link
|
||
|
* IkeException#getCause()}.
|
||
|
* </ul>
|
||
|
*
|
||
|
* <p>If a valid IKE message response is received from the peer, the IkeSession remains as
|
||
|
* connected and periodic DPD reschedules by {@link IkeSessionParams#getDpdDelaySeconds}
|
||
|
*
|
||
|
* <p>If the liveness check request couldn't get any a peer's valid response in retransmission
|
||
|
* timeout, The IkeSession will be closed. Session closing is also notified to {@link
|
||
|
* IkeSessionCallback#onClosedWithException} with {@link
|
||
|
* android.net.ipsec.ike.exceptions.IkeTimeoutException} cause.
|
||
|
*
|
||
|
* @hide
|
||
|
*/
|
||
|
@SystemApi
|
||
|
@FlaggedApi("com.android.ipsec.flags.liveness_check_api")
|
||
|
public void requestLivenessCheck() {
|
||
|
mIkeSessionStateMachine.requestLivenessCheck();
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Dumps the state of {@link IkeSession} information for the clients
|
||
|
*
|
||
|
* @param pw Print writer
|
||
|
*/
|
||
|
@FlaggedApi("com.android.ipsec.flags.dumpsys_api")
|
||
|
public void dump(@NonNull PrintWriter pw) {
|
||
|
// TODO(b/336409878): Add @RequiresPermission annotation.
|
||
|
mContext.enforceCallingOrSelfPermission(
|
||
|
android.Manifest.permission.DUMP, mContext.getAttributionTag());
|
||
|
|
||
|
// Please make sure that the dump is thread-safe
|
||
|
// so the client won't get a crash or exception when adding codes to the dump.
|
||
|
pw.println();
|
||
|
pw.println("IkeSession:");
|
||
|
pw.println("------------------------------");
|
||
|
// Dump ike state machine.
|
||
|
if (mIkeSessionStateMachine != null) {
|
||
|
pw.println();
|
||
|
mIkeSessionStateMachine.dump(pw);
|
||
|
}
|
||
|
pw.println("------------------------------");
|
||
|
}
|
||
|
}
|