1330e1089da80cddcd68758512370d217b19f8890Nathan Harold/*
2330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Copyright (C) 2017 The Android Open Source Project
3330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
4330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Licensed under the Apache License, Version 2.0 (the "License");
5330e1089da80cddcd68758512370d217b19f8890Nathan Harold * you may not use this file except in compliance with the License.
6330e1089da80cddcd68758512370d217b19f8890Nathan Harold * You may obtain a copy of the License at
7330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
8330e1089da80cddcd68758512370d217b19f8890Nathan Harold *      http://www.apache.org/licenses/LICENSE-2.0
9330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
10330e1089da80cddcd68758512370d217b19f8890Nathan Harold * Unless required by applicable law or agreed to in writing, software
11330e1089da80cddcd68758512370d217b19f8890Nathan Harold * distributed under the License is distributed on an "AS IS" BASIS,
12330e1089da80cddcd68758512370d217b19f8890Nathan Harold * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13330e1089da80cddcd68758512370d217b19f8890Nathan Harold * See the License for the specific language governing permissions and
14330e1089da80cddcd68758512370d217b19f8890Nathan Harold * limitations under the License.
15330e1089da80cddcd68758512370d217b19f8890Nathan Harold */
16330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpackage android.net;
17330e1089da80cddcd68758512370d217b19f8890Nathan Harold
1893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport static android.net.IpSecManager.INVALID_RESOURCE_ID;
1993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
20330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.annotation.IntDef;
2193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.annotation.NonNull;
22330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.annotation.SystemApi;
23330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.content.Context;
2493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.Binder;
2593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.IBinder;
2693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.RemoteException;
2793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.ServiceManager;
28330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.util.Log;
2993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport com.android.internal.util.Preconditions;
30330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport dalvik.system.CloseGuard;
31330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.IOException;
32330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.lang.annotation.Retention;
33330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.lang.annotation.RetentionPolicy;
34330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.InetAddress;
35330e1089da80cddcd68758512370d217b19f8890Nathan Harold
36330e1089da80cddcd68758512370d217b19f8890Nathan Harold/**
37330e1089da80cddcd68758512370d217b19f8890Nathan Harold * This class represents an IpSecTransform, which encapsulates both properties and state of IPsec.
38330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
39330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>IpSecTransforms must be built from an IpSecTransform.Builder, and they must persist throughout
40330e1089da80cddcd68758512370d217b19f8890Nathan Harold * the lifetime of the underlying transform. If a transform object leaves scope, the underlying
41330e1089da80cddcd68758512370d217b19f8890Nathan Harold * transform may be disabled automatically, with likely undesirable results.
42330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
43330e1089da80cddcd68758512370d217b19f8890Nathan Harold * <p>An IpSecTransform may either represent a tunnel mode transform that operates on a wide array
44330e1089da80cddcd68758512370d217b19f8890Nathan Harold * of traffic or may represent a transport mode transform operating on a Socket or Sockets.
45ac11ccb1f66d5dadb6c6fd1d47408e36c48c94ceNathan Harold *
46ac11ccb1f66d5dadb6c6fd1d47408e36c48c94ceNathan Harold * @hide
47330e1089da80cddcd68758512370d217b19f8890Nathan Harold */
48330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpublic final class IpSecTransform implements AutoCloseable {
49330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private static final String TAG = "IpSecTransform";
50330e1089da80cddcd68758512370d217b19f8890Nathan Harold
51330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
52330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * For direction-specific attributes of an IpSecTransform, indicates that an attribute applies
53330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * to traffic towards the host.
54330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
55330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final int DIRECTION_IN = 0;
56330e1089da80cddcd68758512370d217b19f8890Nathan Harold
57330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
58330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * For direction-specific attributes of an IpSecTransform, indicates that an attribute applies
59330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * to traffic from the host.
60330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
61330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final int DIRECTION_OUT = 1;
62330e1089da80cddcd68758512370d217b19f8890Nathan Harold
63330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /** @hide */
64330e1089da80cddcd68758512370d217b19f8890Nathan Harold    @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
65330e1089da80cddcd68758512370d217b19f8890Nathan Harold    @Retention(RetentionPolicy.SOURCE)
66330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public @interface TransformDirection {}
67330e1089da80cddcd68758512370d217b19f8890Nathan Harold
68330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /** @hide */
69330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private static final int MODE_TUNNEL = 0;
70330e1089da80cddcd68758512370d217b19f8890Nathan Harold
71330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /** @hide */
72330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private static final int MODE_TRANSPORT = 1;
73330e1089da80cddcd68758512370d217b19f8890Nathan Harold
74330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /** @hide */
75330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final int ENCAP_NONE = 0;
76330e1089da80cddcd68758512370d217b19f8890Nathan Harold
77330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
788dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold     * IpSec traffic will be encapsulated within a UDP header with an additional 8-byte header pad
798dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold     * (of '0'-value bytes) that prevents traffic from being interpreted as IKE or as ESP over UDP.
80330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
81330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
82330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
838dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold    public static final int ENCAP_ESPINUDP_NON_IKE = 1;
84330e1089da80cddcd68758512370d217b19f8890Nathan Harold
85330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
868dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold     * IpSec traffic will be encapsulated within UDP as per <a
878dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold     * href="https://tools.ietf.org/html/rfc3948">RFC3498</a>.
88330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
89330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
90330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
918dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold    public static final int ENCAP_ESPINUDP = 2;
92330e1089da80cddcd68758512370d217b19f8890Nathan Harold
93330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /** @hide */
948dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold    @IntDef(value = {ENCAP_NONE, ENCAP_ESPINUDP, ENCAP_ESPINUDP_NON_IKE})
95330e1089da80cddcd68758512370d217b19f8890Nathan Harold    @Retention(RetentionPolicy.SOURCE)
96330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public @interface EncapType {}
97330e1089da80cddcd68758512370d217b19f8890Nathan Harold
98330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private IpSecTransform(Context context, IpSecConfig config) {
99330e1089da80cddcd68758512370d217b19f8890Nathan Harold        mContext = context;
100330e1089da80cddcd68758512370d217b19f8890Nathan Harold        mConfig = config;
10193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        mResourceId = INVALID_RESOURCE_ID;
10293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
10393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
10493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    private IIpSecService getIpSecService() {
10593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        IBinder b = ServiceManager.getService(android.content.Context.IPSEC_SERVICE);
10693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        if (b == null) {
10793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            throw new RemoteException("Failed to connect to IpSecService")
10893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    .rethrowAsRuntimeException();
10993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
11093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
11193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        return IIpSecService.Stub.asInterface(b);
11293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
11393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
11493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    private void checkResultStatusAndThrow(int status)
11593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            throws IOException, IpSecManager.ResourceUnavailableException,
11693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    IpSecManager.SpiUnavailableException {
11793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        switch (status) {
11893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            case IpSecManager.Status.OK:
11993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                return;
12093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                // TODO: Pass Error string back from bundle so that errors can be more specific
12193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            case IpSecManager.Status.RESOURCE_UNAVAILABLE:
12293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                throw new IpSecManager.ResourceUnavailableException(
12393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        "Failed to allocate a new IpSecTransform");
12493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            case IpSecManager.Status.SPI_UNAVAILABLE:
12593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                Log.wtf(TAG, "Attempting to use an SPI that was somehow not reserved");
12693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                // Fall through
12793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            default:
12893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                throw new IllegalStateException(
12993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        "Failed to Create a Transform with status code " + status);
13093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
131330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
132330e1089da80cddcd68758512370d217b19f8890Nathan Harold
133330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private IpSecTransform activate()
134330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException, IpSecManager.ResourceUnavailableException,
135330e1089da80cddcd68758512370d217b19f8890Nathan Harold                    IpSecManager.SpiUnavailableException {
136330e1089da80cddcd68758512370d217b19f8890Nathan Harold        synchronized (this) {
13793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            try {
13893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                IIpSecService svc = getIpSecService();
1398dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                IpSecTransformResponse result =
1408dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        svc.createTransportModeTransform(mConfig, new Binder());
1418dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                int status = result.status;
14293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                checkResultStatusAndThrow(status);
1438dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mResourceId = result.resourceId;
14493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
14593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                /* Keepalive will silently fail if not needed by the config; but, if needed and
14693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                 * it fails to start, we need to bail because a transform will not be reliable
14793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                 * to use if keepalive is expected to offload and fails.
14893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                 */
14993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                // FIXME: if keepalive fails, we need to fail spectacularly
15093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                startKeepalive(mContext);
15193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                Log.d(TAG, "Added Transform with Id " + mResourceId);
15293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                mCloseGuard.open("build");
15393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            } catch (RemoteException e) {
15493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                throw e.rethrowAsRuntimeException();
155330e1089da80cddcd68758512370d217b19f8890Nathan Harold            }
156330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
157330e1089da80cddcd68758512370d217b19f8890Nathan Harold
158330e1089da80cddcd68758512370d217b19f8890Nathan Harold        return this;
159330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
160330e1089da80cddcd68758512370d217b19f8890Nathan Harold
161330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
162330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Deactivate an IpSecTransform and free all resources for that transform that are managed by
163330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * the system for this Transform.
164330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
165330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>Deactivating a transform while it is still applied to any Socket will result in sockets
166330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * refusing to send or receive data. This method will silently succeed if the specified
167330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * transform has already been removed; thus, it is always safe to attempt cleanup when a
168330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * transform is no longer needed.
169330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
170330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void close() {
17193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        Log.d(TAG, "Removing Transform with Id " + mResourceId);
172330e1089da80cddcd68758512370d217b19f8890Nathan Harold
173330e1089da80cddcd68758512370d217b19f8890Nathan Harold        // Always safe to attempt cleanup
17493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        if (mResourceId == INVALID_RESOURCE_ID) {
17593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mCloseGuard.close();
176330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return;
177330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
17893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        try {
17993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            /* Order matters here because the keepalive is best-effort but could fail in some
18093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold             * horrible way to be removed if the wifi (or cell) subsystem has crashed, and we
18193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold             * still want to clear out the transform.
18293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold             */
18393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            IIpSecService svc = getIpSecService();
18493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            svc.deleteTransportModeTransform(mResourceId);
18593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            stopKeepalive();
18693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        } catch (RemoteException e) {
18793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            throw e.rethrowAsRuntimeException();
18893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        } finally {
18993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mResourceId = INVALID_RESOURCE_ID;
19093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mCloseGuard.close();
19193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
192330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
193330e1089da80cddcd68758512370d217b19f8890Nathan Harold
194330e1089da80cddcd68758512370d217b19f8890Nathan Harold    @Override
195330e1089da80cddcd68758512370d217b19f8890Nathan Harold    protected void finalize() throws Throwable {
196330e1089da80cddcd68758512370d217b19f8890Nathan Harold        if (mCloseGuard != null) {
197330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.warnIfOpen();
198330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
199330e1089da80cddcd68758512370d217b19f8890Nathan Harold        close();
200330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
201330e1089da80cddcd68758512370d217b19f8890Nathan Harold
202330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /* Package */
203330e1089da80cddcd68758512370d217b19f8890Nathan Harold    IpSecConfig getConfig() {
204330e1089da80cddcd68758512370d217b19f8890Nathan Harold        return mConfig;
205330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
206330e1089da80cddcd68758512370d217b19f8890Nathan Harold
207330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private final IpSecConfig mConfig;
20893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    private int mResourceId;
209330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private final Context mContext;
210330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private final CloseGuard mCloseGuard = CloseGuard.get();
211330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private ConnectivityManager.PacketKeepalive mKeepalive;
212330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private int mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE;
213330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private Object mKeepaliveSyncLock = new Object();
214330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private ConnectivityManager.PacketKeepaliveCallback mKeepaliveCallback =
215330e1089da80cddcd68758512370d217b19f8890Nathan Harold            new ConnectivityManager.PacketKeepaliveCallback() {
216330e1089da80cddcd68758512370d217b19f8890Nathan Harold
217330e1089da80cddcd68758512370d217b19f8890Nathan Harold                @Override
218330e1089da80cddcd68758512370d217b19f8890Nathan Harold                public void onStarted() {
219330e1089da80cddcd68758512370d217b19f8890Nathan Harold                    synchronized (mKeepaliveSyncLock) {
220330e1089da80cddcd68758512370d217b19f8890Nathan Harold                        mKeepaliveStatus = ConnectivityManager.PacketKeepalive.SUCCESS;
221330e1089da80cddcd68758512370d217b19f8890Nathan Harold                        mKeepaliveSyncLock.notifyAll();
222330e1089da80cddcd68758512370d217b19f8890Nathan Harold                    }
223330e1089da80cddcd68758512370d217b19f8890Nathan Harold                }
224330e1089da80cddcd68758512370d217b19f8890Nathan Harold
225330e1089da80cddcd68758512370d217b19f8890Nathan Harold                @Override
226330e1089da80cddcd68758512370d217b19f8890Nathan Harold                public void onStopped() {
227330e1089da80cddcd68758512370d217b19f8890Nathan Harold                    synchronized (mKeepaliveSyncLock) {
228330e1089da80cddcd68758512370d217b19f8890Nathan Harold                        mKeepaliveStatus = ConnectivityManager.PacketKeepalive.NO_KEEPALIVE;
229330e1089da80cddcd68758512370d217b19f8890Nathan Harold                        mKeepaliveSyncLock.notifyAll();
230330e1089da80cddcd68758512370d217b19f8890Nathan Harold                    }
231330e1089da80cddcd68758512370d217b19f8890Nathan Harold                }
232330e1089da80cddcd68758512370d217b19f8890Nathan Harold
233330e1089da80cddcd68758512370d217b19f8890Nathan Harold                @Override
234330e1089da80cddcd68758512370d217b19f8890Nathan Harold                public void onError(int error) {
235330e1089da80cddcd68758512370d217b19f8890Nathan Harold                    synchronized (mKeepaliveSyncLock) {
236330e1089da80cddcd68758512370d217b19f8890Nathan Harold                        mKeepaliveStatus = error;
237330e1089da80cddcd68758512370d217b19f8890Nathan Harold                        mKeepaliveSyncLock.notifyAll();
238330e1089da80cddcd68758512370d217b19f8890Nathan Harold                    }
239330e1089da80cddcd68758512370d217b19f8890Nathan Harold                }
240330e1089da80cddcd68758512370d217b19f8890Nathan Harold            };
241330e1089da80cddcd68758512370d217b19f8890Nathan Harold
242330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /* Package */
243330e1089da80cddcd68758512370d217b19f8890Nathan Harold    void startKeepalive(Context c) {
24493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        // FIXME: NO_KEEPALIVE needs to be a constant
245330e1089da80cddcd68758512370d217b19f8890Nathan Harold        if (mConfig.getNattKeepaliveInterval() == 0) {
246330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return;
247330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
248330e1089da80cddcd68758512370d217b19f8890Nathan Harold
249330e1089da80cddcd68758512370d217b19f8890Nathan Harold        ConnectivityManager cm =
250330e1089da80cddcd68758512370d217b19f8890Nathan Harold                (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
251330e1089da80cddcd68758512370d217b19f8890Nathan Harold
252330e1089da80cddcd68758512370d217b19f8890Nathan Harold        if (mKeepalive != null) {
25393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            Log.wtf(TAG, "Keepalive already started for this IpSecTransform.");
254330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return;
255330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
256330e1089da80cddcd68758512370d217b19f8890Nathan Harold
257330e1089da80cddcd68758512370d217b19f8890Nathan Harold        synchronized (mKeepaliveSyncLock) {
258330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mKeepalive =
259330e1089da80cddcd68758512370d217b19f8890Nathan Harold                    cm.startNattKeepalive(
260330e1089da80cddcd68758512370d217b19f8890Nathan Harold                            mConfig.getNetwork(),
261330e1089da80cddcd68758512370d217b19f8890Nathan Harold                            mConfig.getNattKeepaliveInterval(),
262330e1089da80cddcd68758512370d217b19f8890Nathan Harold                            mKeepaliveCallback,
26393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                            mConfig.getLocalAddress(),
2648dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                            0x1234, /* FIXME: get the real port number again,
2658dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                                    which we need to retrieve from the provided
2668dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                                    EncapsulationSocket, and which isn't currently
2678dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                                    stashed in IpSecConfig */
26893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                            mConfig.getRemoteAddress());
269330e1089da80cddcd68758512370d217b19f8890Nathan Harold            try {
27093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                // FIXME: this is still a horrible way to fudge the synchronous callback
271330e1089da80cddcd68758512370d217b19f8890Nathan Harold                mKeepaliveSyncLock.wait(2000);
272330e1089da80cddcd68758512370d217b19f8890Nathan Harold            } catch (InterruptedException e) {
273330e1089da80cddcd68758512370d217b19f8890Nathan Harold            }
274330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
275330e1089da80cddcd68758512370d217b19f8890Nathan Harold        if (mKeepaliveStatus != ConnectivityManager.PacketKeepalive.SUCCESS) {
276330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throw new UnsupportedOperationException("Packet Keepalive cannot be started");
277330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
278330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
279330e1089da80cddcd68758512370d217b19f8890Nathan Harold
280330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /* Package */
28193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    int getResourceId() {
28293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        return mResourceId;
28393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
28493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
28593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /* Package */
286330e1089da80cddcd68758512370d217b19f8890Nathan Harold    void stopKeepalive() {
287330e1089da80cddcd68758512370d217b19f8890Nathan Harold        if (mKeepalive == null) {
288330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return;
289330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
290330e1089da80cddcd68758512370d217b19f8890Nathan Harold        mKeepalive.stop();
291330e1089da80cddcd68758512370d217b19f8890Nathan Harold        synchronized (mKeepaliveSyncLock) {
292330e1089da80cddcd68758512370d217b19f8890Nathan Harold            if (mKeepaliveStatus == ConnectivityManager.PacketKeepalive.SUCCESS) {
293330e1089da80cddcd68758512370d217b19f8890Nathan Harold                try {
294330e1089da80cddcd68758512370d217b19f8890Nathan Harold                    mKeepaliveSyncLock.wait(2000);
295330e1089da80cddcd68758512370d217b19f8890Nathan Harold                } catch (InterruptedException e) {
296330e1089da80cddcd68758512370d217b19f8890Nathan Harold                }
297330e1089da80cddcd68758512370d217b19f8890Nathan Harold            }
298330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
299330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
300330e1089da80cddcd68758512370d217b19f8890Nathan Harold
301330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
302330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Builder object to facilitate the creation of IpSecTransform objects.
303330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
304330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>Apply additional properties to the transform and then call a build() method to return an
305330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * IpSecTransform object.
306330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
307330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @see Builder#buildTransportModeTransform(InetAddress)
308330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
309330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static class Builder {
310330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private Context mContext;
311330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private IpSecConfig mConfig;
312330e1089da80cddcd68758512370d217b19f8890Nathan Harold
313330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
314330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Add an encryption algorithm to the transform for the given direction.
315330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
316330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * <p>If encryption is set for a given direction without also providing an SPI for that
317330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * direction, creation of an IpSecTransform will fail upon calling a build() method.
318330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
319330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
320330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
321330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
322330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public IpSecTransform.Builder setEncryption(
323330e1089da80cddcd68758512370d217b19f8890Nathan Harold                @TransformDirection int direction, IpSecAlgorithm algo) {
32493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mConfig.flow[direction].encryption = algo;
325330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return this;
326330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
327330e1089da80cddcd68758512370d217b19f8890Nathan Harold
328330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
329330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Add an authentication/integrity algorithm to the transform.
330330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
331330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * <p>If authentication is set for a given direction without also providing an SPI for that
332330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * direction, creation of an IpSecTransform will fail upon calling a build() method.
333330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
334330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
335330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
336330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
337330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public IpSecTransform.Builder setAuthentication(
338330e1089da80cddcd68758512370d217b19f8890Nathan Harold                @TransformDirection int direction, IpSecAlgorithm algo) {
33993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mConfig.flow[direction].authentication = algo;
340330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return this;
341330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
342330e1089da80cddcd68758512370d217b19f8890Nathan Harold
343330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
344330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Set the SPI, which uniquely identifies a particular IPsec session from others. Because
345330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * IPsec operates at the IP layer, this 32-bit identifier uniquely identifies packets to a
346330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * given destination address.
347330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
348330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * <p>Care should be chosen when selecting an SPI to ensure that is is as unique as
34948b566557d5a66d4476008b3c59b815eb78cb373Nathan Harold         * possible. To reserve a value call {@link IpSecManager#reserveSecurityParameterIndex(int,
35048b566557d5a66d4476008b3c59b815eb78cb373Nathan Harold         * InetAddress, int)}. Otherwise, SPI collisions would prevent a transform from being
35148b566557d5a66d4476008b3c59b815eb78cb373Nathan Harold         * activated. IpSecManager#reserveSecurityParameterIndex(int, InetAddres$s, int)}.
352330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
353330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * <p>Unless an SPI is set for a given direction, traffic in that direction will be
354330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * sent/received without any IPsec applied.
355330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
356330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
357330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
358330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     traffic
359330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
360330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public IpSecTransform.Builder setSpi(
361330e1089da80cddcd68758512370d217b19f8890Nathan Harold                @TransformDirection int direction, IpSecManager.SecurityParameterIndex spi) {
36293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            // TODO: convert to using the resource Id of the SPI. Then build() can validate
36393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            // the owner in the IpSecService
3648dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            mConfig.flow[direction].spiResourceId = spi.getResourceId();
365330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return this;
366330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
367330e1089da80cddcd68758512370d217b19f8890Nathan Harold
368330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
369330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Specify the network on which this transform will emit its traffic; (otherwise it will
370330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * emit on the default network).
371330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
372330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * <p>Restricts the transformed traffic to a particular {@link Network}. This is required in
373330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * tunnel mode.
374330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
375330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @hide
376330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
377330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @SystemApi
378330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public IpSecTransform.Builder setUnderlyingNetwork(Network net) {
379330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mConfig.network = net;
380330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return this;
381330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
382330e1089da80cddcd68758512370d217b19f8890Nathan Harold
383330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
384330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Add UDP encapsulation to an IPv4 transform
385330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
386330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * <p>This option allows IPsec traffic to pass through NAT. Refer to RFC 3947 and 3948 for
387330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * details on how UDP should be applied to IPsec.
388330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
389330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param localSocket a {@link IpSecManager.UdpEncapsulationSocket} for sending and
390330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     receiving encapsulating traffic.
391330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param remotePort the UDP port number of the remote that will send and receive
392330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     encapsulated traffic. In the case of IKE, this is likely port 4500.
393330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
394330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public IpSecTransform.Builder setIpv4Encapsulation(
395330e1089da80cddcd68758512370d217b19f8890Nathan Harold                IpSecManager.UdpEncapsulationSocket localSocket, int remotePort) {
396330e1089da80cddcd68758512370d217b19f8890Nathan Harold            // TODO: check encap type is valid.
397330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mConfig.encapType = ENCAP_ESPINUDP;
3988dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            mConfig.encapLocalPortResourceId = localSocket.getResourceId();
399330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mConfig.encapRemotePort = remotePort;
400330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return this;
401330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
402330e1089da80cddcd68758512370d217b19f8890Nathan Harold
403330e1089da80cddcd68758512370d217b19f8890Nathan Harold        // TODO: Decrease the minimum keepalive to maybe 10?
404330e1089da80cddcd68758512370d217b19f8890Nathan Harold        // TODO: Probably a better exception to throw for NATTKeepalive failure
405330e1089da80cddcd68758512370d217b19f8890Nathan Harold        // TODO: Specify the needed NATT keepalive permission.
406330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
407330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Send a NATT Keepalive packet with a given maximum interval. This will create an offloaded
408330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * request to do power-efficient NATT Keepalive. If NATT keepalive is requested but cannot
409330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * be activated, then the transform will fail to activate and throw an IOException.
410330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
411330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param intervalSeconds the maximum number of seconds between keepalive packets, no less
412330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     than 20s and no more than 3600s.
413330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @hide
414330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
415330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @SystemApi
416330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public IpSecTransform.Builder setNattKeepalive(int intervalSeconds) {
417330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mConfig.nattKeepaliveInterval = intervalSeconds;
418330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return this;
419330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
420330e1089da80cddcd68758512370d217b19f8890Nathan Harold
421330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
422330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Build and return an active {@link IpSecTransform} object as a Transport Mode Transform.
423330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Some parameters have interdependencies that are checked at build time. If a well-formed
424330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * transform cannot be created from the supplied parameters, this method will throw an
425330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Exception.
426330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
427330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * <p>Upon a successful return from this call, the provided IpSecTransform will be active
428330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * and may be applied to sockets. If too many IpSecTransform objects are active for a given
429330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * user this operation will fail and throw ResourceUnavailableException. To avoid these
430330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * exceptions, unused Transform objects must be cleaned up by calling {@link
431330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * IpSecTransform#close()} when they are no longer needed.
432330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
433330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param remoteAddress the {@link InetAddress} that, when matched on traffic to/from this
434330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     socket will cause the transform to be applied.
435330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     <p>Note that an active transform will not impact any network traffic until it has
436330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     been applied to one or more Sockets. Calling this method is a necessary precondition
437330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     for applying it to a socket, but is not sufficient to actually apply IPsec.
438330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @throws IllegalArgumentException indicating that a particular combination of transform
439330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     properties is invalid.
440330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @throws IpSecManager.ResourceUnavailableException in the event that no more Transforms
441330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     may be allocated
442330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @throws SpiUnavailableException if the SPI collides with an existing transform
443330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     (unlikely).
444330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @throws ResourceUnavailableException if the current user currently has exceeded the
445330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     number of allowed active transforms.
446330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
447330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public IpSecTransform buildTransportModeTransform(InetAddress remoteAddress)
448330e1089da80cddcd68758512370d217b19f8890Nathan Harold                throws IpSecManager.ResourceUnavailableException,
449330e1089da80cddcd68758512370d217b19f8890Nathan Harold                        IpSecManager.SpiUnavailableException, IOException {
450330e1089da80cddcd68758512370d217b19f8890Nathan Harold            //FIXME: argument validation here
451330e1089da80cddcd68758512370d217b19f8890Nathan Harold            //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation");
452330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mConfig.mode = MODE_TRANSPORT;
453330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mConfig.remoteAddress = remoteAddress;
454330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return new IpSecTransform(mContext, mConfig).activate();
455330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
456330e1089da80cddcd68758512370d217b19f8890Nathan Harold
457330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
458330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Build and return an {@link IpSecTransform} object as a Tunnel Mode Transform. Some
459330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * parameters have interdependencies that are checked at build time.
460330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
461330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param localAddress the {@link InetAddress} that provides the local endpoint for this
462330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     IPsec tunnel. This is almost certainly an address belonging to the {@link Network}
463330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     that will originate the traffic, which is set as the {@link #setUnderlyingNetwork}.
464330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param remoteAddress the {@link InetAddress} representing the remote endpoint of this
465330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     IPsec tunnel.
466330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @throws IllegalArgumentException indicating that a particular combination of transform
467330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *     properties is invalid.
468330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @hide
469330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
470330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public IpSecTransform buildTunnelModeTransform(
471330e1089da80cddcd68758512370d217b19f8890Nathan Harold                InetAddress localAddress, InetAddress remoteAddress) {
472330e1089da80cddcd68758512370d217b19f8890Nathan Harold            //FIXME: argument validation here
473330e1089da80cddcd68758512370d217b19f8890Nathan Harold            //throw new IllegalArgumentException("Natt Keepalive requires UDP Encapsulation");
474330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mConfig.localAddress = localAddress;
475330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mConfig.remoteAddress = remoteAddress;
476330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mConfig.mode = MODE_TUNNEL;
477330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return new IpSecTransform(mContext, mConfig);
478330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
479330e1089da80cddcd68758512370d217b19f8890Nathan Harold
480330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
481330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Create a new IpSecTransform.Builder to construct an IpSecTransform
482330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
483330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param context current Context
484330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
48593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public Builder(@NonNull Context context) {
48693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            Preconditions.checkNotNull(context);
487330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mContext = context;
488330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mConfig = new IpSecConfig();
489330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
490330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
491330e1089da80cddcd68758512370d217b19f8890Nathan Harold}
492