IpSecManager.java revision 5a920ca377efaaaaabf3fe6c77111d8158202055
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
18330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport static com.android.internal.util.Preconditions.checkNotNull;
19330e1089da80cddcd68758512370d217b19f8890Nathan Harold
20a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport android.annotation.IntDef;
2193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.annotation.NonNull;
225a920ca377efaaaaabf3fe6c77111d8158202055Nathan Haroldimport android.annotation.RequiresPermission;
23c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Haroldimport android.annotation.SystemApi;
24d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.annotation.SystemService;
25c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseriimport android.annotation.TestApi;
26d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkeyimport android.content.Context;
2793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.Binder;
28330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.os.ParcelFileDescriptor;
2993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Haroldimport android.os.RemoteException;
30330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport android.util.AndroidException;
318dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Haroldimport android.util.Log;
32b72821747cd8cfa9bcaff7f11247ebfce3255fbfNathan Harold
33a10003d5de52339f4d30fedd7294941378e5f13cNathan Haroldimport com.android.internal.annotations.VisibleForTesting;
34a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold
35330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport dalvik.system.CloseGuard;
36b72821747cd8cfa9bcaff7f11247ebfce3255fbfNathan Harold
37330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.FileDescriptor;
38330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.io.IOException;
39a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport java.lang.annotation.Retention;
40a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Haroldimport java.lang.annotation.RetentionPolicy;
41330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.DatagramSocket;
42330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.InetAddress;
43330e1089da80cddcd68758512370d217b19f8890Nathan Haroldimport java.net.Socket;
44330e1089da80cddcd68758512370d217b19f8890Nathan Harold
45330e1089da80cddcd68758512370d217b19f8890Nathan Harold/**
46c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * This class contains methods for managing IPsec sessions. Once configured, the kernel will apply
47c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * confidentiality (encryption) and integrity (authentication) to IP traffic.
48330e1089da80cddcd68758512370d217b19f8890Nathan Harold *
49c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * <p>Note that not all aspects of IPsec are permitted by this API. Applications may create
50c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * transport mode security associations and apply them to individual sockets. Applications looking
51c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * to create a VPN should use {@link VpnService}.
52c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri *
53c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri * @see <a href="https://tools.ietf.org/html/rfc4301">RFC 4301, Security Architecture for the
545fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri *     Internet Protocol</a>
55330e1089da80cddcd68758512370d217b19f8890Nathan Harold */
56d86b8fea43ebb6e5c31691b44d8ceb0d8d3c9072Jeff Sharkey@SystemService(Context.IPSEC_SERVICE)
57330e1089da80cddcd68758512370d217b19f8890Nathan Haroldpublic final class IpSecManager {
58330e1089da80cddcd68758512370d217b19f8890Nathan Harold    private static final String TAG = "IpSecManager";
59330e1089da80cddcd68758512370d217b19f8890Nathan Harold
60330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
61a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
62a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * applies to traffic towards the host.
63a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     */
64a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    public static final int DIRECTION_IN = 0;
65a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold
66a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    /**
67a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * For direction-specific attributes of an {@link IpSecTransform}, indicates that an attribute
68a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * applies to traffic from the host.
69a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     */
70a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    public static final int DIRECTION_OUT = 1;
71a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold
72a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    /** @hide */
73a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    @IntDef(value = {DIRECTION_IN, DIRECTION_OUT})
74a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    @Retention(RetentionPolicy.SOURCE)
75a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    public @interface PolicyDirection {}
76a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold
77a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    /**
78c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * The Security Parameter Index (SPI) 0 indicates an unknown or invalid index.
7993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     *
8093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     * <p>No IPsec packet may contain an SPI of 0.
81c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
82c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @hide
8393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold     */
845fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri    @TestApi public static final int INVALID_SECURITY_PARAMETER_INDEX = 0;
8593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
8693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /** @hide */
8793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    public interface Status {
8893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public static final int OK = 0;
8993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public static final int RESOURCE_UNAVAILABLE = 1;
9093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        public static final int SPI_UNAVAILABLE = 2;
9193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
9293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
9393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /** @hide */
946119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold    public static final int INVALID_RESOURCE_ID = -1;
9593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
9693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    /**
97c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Thrown to indicate that a requested SPI is in use.
98c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
99c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>The combination of remote {@code InetAddress} and SPI must be unique across all apps on
100c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * one device. If this error is encountered, a new SPI is required before a transform may be
101c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * created. This error can be avoided by calling {@link
1025fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * IpSecManager#allocateSecurityParameterIndex}.
103330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
104330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class SpiUnavailableException extends AndroidException {
105330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final int mSpi;
106330e1089da80cddcd68758512370d217b19f8890Nathan Harold
107330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
108330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Construct an exception indicating that a transform with the given SPI is already in use
109330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * or otherwise unavailable.
110330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
111c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri         * @param msg description indicating the colliding SPI
112330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * @param spi the SPI that could not be used due to a collision
113330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
114330e1089da80cddcd68758512370d217b19f8890Nathan Harold        SpiUnavailableException(String msg, int spi) {
115c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri            super(msg + " (spi: " + spi + ")");
116330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mSpi = spi;
117330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
118330e1089da80cddcd68758512370d217b19f8890Nathan Harold
119c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        /** Get the SPI that caused a collision. */
120330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public int getSpi() {
121330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return mSpi;
122330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
123330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
124330e1089da80cddcd68758512370d217b19f8890Nathan Harold
125330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
126c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Thrown to indicate that an IPsec resource is unavailable.
127c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
128c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>This could apply to resources such as sockets, {@link SecurityParameterIndex}, {@link
129c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * IpSecTransform}, or other system resources. If this exception is thrown, users should release
130c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * allocated objects of the type requested.
131330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
132330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class ResourceUnavailableException extends AndroidException {
133330e1089da80cddcd68758512370d217b19f8890Nathan Harold
134330e1089da80cddcd68758512370d217b19f8890Nathan Harold        ResourceUnavailableException(String msg) {
135330e1089da80cddcd68758512370d217b19f8890Nathan Harold            super(msg);
136330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
137330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
138330e1089da80cddcd68758512370d217b19f8890Nathan Harold
1391afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold    private final IIpSecService mService;
140330e1089da80cddcd68758512370d217b19f8890Nathan Harold
141c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri    /**
142c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * This class represents a reserved SPI.
143c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
144c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>Objects of this type are used to track reserved security parameter indices. They can be
1455fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * obtained by calling {@link IpSecManager#allocateSecurityParameterIndex} and must be released
146c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * by calling {@link #close()} when they are no longer needed.
147c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     */
148330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class SecurityParameterIndex implements AutoCloseable {
1491afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        private final IIpSecService mService;
150a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold        private final InetAddress mDestinationAddress;
151330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final CloseGuard mCloseGuard = CloseGuard.get();
15293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private int mSpi = INVALID_SECURITY_PARAMETER_INDEX;
1536119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold        private int mResourceId = INVALID_RESOURCE_ID;
154330e1089da80cddcd68758512370d217b19f8890Nathan Harold
155c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        /** Get the underlying SPI held by this object. */
156330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public int getSpi() {
157330e1089da80cddcd68758512370d217b19f8890Nathan Harold            return mSpi;
158330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
159330e1089da80cddcd68758512370d217b19f8890Nathan Harold
160330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
161330e1089da80cddcd68758512370d217b19f8890Nathan Harold         * Release an SPI that was previously reserved.
162330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
163c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold         * <p>Release an SPI for use by other users in the system. If a SecurityParameterIndex is
164c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold         * applied to an IpSecTransform, it will become unusable for future transforms but should
165c4f879925b58b1b5ca9a3cfdc898c20cbf56355aNathan Harold         * still be closed to ensure system resources are released.
166330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
167330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
168330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public void close() {
1698dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            try {
1708dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mService.releaseSecurityParameterIndex(mResourceId);
1716119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold                mResourceId = INVALID_RESOURCE_ID;
1728dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            } catch (RemoteException e) {
1738dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throw e.rethrowFromSystemServer();
1748dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
175330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.close();
176330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
177330e1089da80cddcd68758512370d217b19f8890Nathan Harold
178c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        /** Check that the SPI was closed properly. */
179330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
180440824f7434e1e2c343b21a9ca3e6f405b8e0ea1Nathan Harold        protected void finalize() throws Throwable {
181330e1089da80cddcd68758512370d217b19f8890Nathan Harold            if (mCloseGuard != null) {
182330e1089da80cddcd68758512370d217b19f8890Nathan Harold                mCloseGuard.warnIfOpen();
183330e1089da80cddcd68758512370d217b19f8890Nathan Harold            }
184330e1089da80cddcd68758512370d217b19f8890Nathan Harold
185330e1089da80cddcd68758512370d217b19f8890Nathan Harold            close();
186330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
187330e1089da80cddcd68758512370d217b19f8890Nathan Harold
18893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private SecurityParameterIndex(
189a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold                @NonNull IIpSecService service, InetAddress destinationAddress, int spi)
19093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                throws ResourceUnavailableException, SpiUnavailableException {
19193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mService = service;
192a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold            mDestinationAddress = destinationAddress;
19393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            try {
1948dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                IpSecSpiResponse result =
1955fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri                        mService.allocateSecurityParameterIndex(
196a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold                                destinationAddress.getHostAddress(), spi, new Binder());
19793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
19893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                if (result == null) {
19993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    throw new NullPointerException("Received null response from IpSecService");
20093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
20193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
2028dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                int status = result.status;
20393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                switch (status) {
20493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    case Status.OK:
20593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        break;
20693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    case Status.RESOURCE_UNAVAILABLE:
20793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        throw new ResourceUnavailableException(
20893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                                "No more SPIs may be allocated by this requester.");
20993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    case Status.SPI_UNAVAILABLE:
21093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        throw new SpiUnavailableException("Requested SPI is unavailable", spi);
21193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    default:
21293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                        throw new RuntimeException(
21393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                                "Unknown status returned by IpSecService: " + status);
21493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
2158dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mSpi = result.spi;
2168dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mResourceId = result.resourceId;
21793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
21893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                if (mSpi == INVALID_SECURITY_PARAMETER_INDEX) {
21993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    throw new RuntimeException("Invalid SPI returned by IpSecService: " + status);
22093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
22193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
22293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                if (mResourceId == INVALID_RESOURCE_ID) {
22393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                    throw new RuntimeException(
22493962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                            "Invalid Resource ID returned by IpSecService: " + status);
22593962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                }
22693962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold
22793962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            } catch (RemoteException e) {
22893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold                throw e.rethrowFromSystemServer();
22993962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            }
23093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            mCloseGuard.open("open");
23193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
2328dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold
2338dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        /** @hide */
234a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold        @VisibleForTesting
235a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold        public int getResourceId() {
2368dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            return mResourceId;
2378dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
23893962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
239330e1089da80cddcd68758512370d217b19f8890Nathan Harold
240330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
241a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * Reserve a random SPI for traffic bound to or from the specified destination address.
242330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
243330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * <p>If successful, this SPI is guaranteed available until released by a call to {@link
244330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * SecurityParameterIndex#close()}.
245330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
246a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @param destinationAddress the destination address for traffic bearing the requested SPI.
247a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     *     For inbound traffic, the destination should be an address currently assigned on-device.
248330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @return the reserved SecurityParameterIndex
249a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
250a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     *     currently allocated for this user
251330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
252a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    public SecurityParameterIndex allocateSecurityParameterIndex(InetAddress destinationAddress)
253a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold            throws ResourceUnavailableException {
2546045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        try {
2556045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold            return new SecurityParameterIndex(
2566045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold                    mService,
257a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold                    destinationAddress,
2586045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold                    IpSecManager.INVALID_SECURITY_PARAMETER_INDEX);
2596045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        } catch (SpiUnavailableException unlikely) {
2606045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold            throw new ResourceUnavailableException("No SPIs available");
2616045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        }
2626045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold    }
2636045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold
2646045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold    /**
265a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * Reserve the requested SPI for traffic bound to or from the specified destination address.
2666045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     *
2676045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * <p>If successful, this SPI is guaranteed available until released by a call to {@link
2686045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * SecurityParameterIndex#close()}.
2696045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     *
270a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @param destinationAddress the destination address for traffic bearing the requested SPI.
271a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     *     For inbound traffic, the destination should be an address currently assigned on-device.
272c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param requestedSpi the requested SPI, or '0' to allocate a random SPI
2736045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     * @return the reserved SecurityParameterIndex
274a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @throws {@link #ResourceUnavailableException} indicating that too many SPIs are
275a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     *     currently allocated for this user
276a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @throws {@link #SpiUnavailableException} indicating that the requested SPI could not be
277a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     *     reserved
2786045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold     */
2795fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri    public SecurityParameterIndex allocateSecurityParameterIndex(
280a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold            InetAddress destinationAddress, int requestedSpi)
281330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws SpiUnavailableException, ResourceUnavailableException {
2826045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        if (requestedSpi == IpSecManager.INVALID_SECURITY_PARAMETER_INDEX) {
2836045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold            throw new IllegalArgumentException("Requested SPI must be a valid (non-zero) SPI");
2846045429b35ca4c1cbd920e5e0872dec9de493fdeNathan Harold        }
285a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold        return new SecurityParameterIndex(mService, destinationAddress, requestedSpi);
286330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
287330e1089da80cddcd68758512370d217b19f8890Nathan Harold
288330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
289c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Apply an IPsec transform to a stream socket.
290c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
291c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
292c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
293a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
294c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * unprotected traffic can resume on that socket.
295c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
296c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>For security reasons, the destination address of any traffic on the socket must match the
2975fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
298c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * other IP address will result in an IOException. In addition, reads and writes on the socket
299c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * will throw IOException if the user deactivates the transform (by calling {@link
300a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
301c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
3025fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * <h4>Rekey Procedure</h4>
3035fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     *
3045fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * <p>When applying a new tranform to a socket, the previous transform will be removed. However,
3055fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * inbound traffic on the old transform will continue to be decrypted until that transform is
3065fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures
3075fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * where both transforms are valid until both endpoints are using the new transform and all
3085fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * in-flight packets have been received.
309330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
310330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param socket a stream socket
311a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @param direction the policy direction either {@link #DIRECTION_IN} or {@link #DIRECTION_OUT}
312c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param transform a transport mode {@code IpSecTransform}
313c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the transform could not be applied
314330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
315a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    public void applyTransportModeTransform(
316a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold            Socket socket, int direction, IpSecTransform transform)
317330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException {
318b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold        applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
319330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
320330e1089da80cddcd68758512370d217b19f8890Nathan Harold
321330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
322c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Apply an IPsec transform to a datagram socket.
323c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
324c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
325c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
326a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
327c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * unprotected traffic can resume on that socket.
328c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
329c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>For security reasons, the destination address of any traffic on the socket must match the
330c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
331c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * other IP address will result in an IOException. In addition, reads and writes on the socket
332c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * will throw IOException if the user deactivates the transform (by calling {@link
333a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
334c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
3355fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * <h4>Rekey Procedure</h4>
3365fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     *
3375fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * <p>When applying a new tranform to a socket, the previous transform will be removed. However,
3385fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * inbound traffic on the old transform will continue to be decrypted until that transform is
3395fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures
3405fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * where both transforms are valid until both endpoints are using the new transform and all
3415fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * in-flight packets have been received.
342330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
343330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param socket a datagram socket
344a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT
345c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param transform a transport mode {@code IpSecTransform}
346c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the transform could not be applied
347330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
348a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    public void applyTransportModeTransform(
349a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold            DatagramSocket socket, int direction, IpSecTransform transform) throws IOException {
350b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold        applyTransportModeTransform(socket.getFileDescriptor$(), direction, transform);
35193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
352330e1089da80cddcd68758512370d217b19f8890Nathan Harold
353330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
354c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Apply an IPsec transform to a socket.
355c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
356c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>This applies transport mode encapsulation to the given socket. Once applied, I/O on the
357c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * socket will be encapsulated according to the parameters of the {@code IpSecTransform}. When
358a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * the transform is removed from the socket by calling {@link #removeTransportModeTransforms},
359c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * unprotected traffic can resume on that socket.
360c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
361c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>For security reasons, the destination address of any traffic on the socket must match the
362c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * remote {@code InetAddress} of the {@code IpSecTransform}. Attempts to send traffic to any
363c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * other IP address will result in an IOException. In addition, reads and writes on the socket
364c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * will throw IOException if the user deactivates the transform (by calling {@link
365a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * IpSecTransform#close()}) without calling {@link #removeTransportModeTransforms}.
366c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
3675fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * <h4>Rekey Procedure</h4>
3685fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     *
3695fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * <p>When applying a new tranform to a socket, the previous transform will be removed. However,
3705fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * inbound traffic on the old transform will continue to be decrypted until that transform is
3715fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * deallocated by calling {@link IpSecTransform#close()}. This overlap allows rekey procedures
3725fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * where both transforms are valid until both endpoints are using the new transform and all
3735fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * in-flight packets have been received.
374b64993559b049327365bb63e81e8046a892a1033Nathan Harold     *
375b64993559b049327365bb63e81e8046a892a1033Nathan Harold     * @param socket a socket file descriptor
376a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold     * @param direction the policy direction either DIRECTION_IN or DIRECTION_OUT
377c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param transform a transport mode {@code IpSecTransform}
378c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the transform could not be applied
379b64993559b049327365bb63e81e8046a892a1033Nathan Harold     */
380a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold    public void applyTransportModeTransform(
381a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold            FileDescriptor socket, int direction, IpSecTransform transform)
382b64993559b049327365bb63e81e8046a892a1033Nathan Harold            throws IOException {
3838dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        // We dup() the FileDescriptor here because if we don't, then the ParcelFileDescriptor()
384b548d251b7995a5b76e495978b61ad6c3c4183d1Nathan Harold        // constructor takes control and closes the user's FD when we exit the method.
3858dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
386a25233123b2d29fde83dd686f6313f0a232c5b2aNathan Harold            mService.applyTransportModeTransform(pfd, direction, transform.getResourceId());
3878dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        } catch (RemoteException e) {
3888dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            throw e.rethrowFromSystemServer();
3898dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
390b64993559b049327365bb63e81e8046a892a1033Nathan Harold    }
391b64993559b049327365bb63e81e8046a892a1033Nathan Harold
392b64993559b049327365bb63e81e8046a892a1033Nathan Harold    /**
393330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Apply an active Tunnel Mode IPsec Transform to a network, which will tunnel all traffic to
394330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * and from that network's interface with IPsec (applies an outer IP header and IPsec Header to
395330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * all traffic, and expects an additional IP header and IPsec Header on all inbound traffic).
396330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Applications should probably not use this API directly. Instead, they should use {@link
397330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * VpnService} to provide VPN capability in a more generic fashion.
398330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
3995fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * <p>TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked.
4005fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     *
401330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param net a {@link Network} that will be tunneled via IP Sec.
402330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform an {@link IpSecTransform}, which must be an active Tunnel Mode transform.
403330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
404330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
405330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void applyTunnelModeTransform(Network net, IpSecTransform transform) {}
406330e1089da80cddcd68758512370d217b19f8890Nathan Harold
407330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
408c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Remove an IPsec transform from a stream socket.
409c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
410f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
411f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold     * socket allows the socket to be reused for communication in the clear.
412c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
413c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
414c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
415c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * is called.
416330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
417c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param socket a socket that previously had a transform applied to it
418c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the transform could not be removed from the socket
419330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
420f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold    public void removeTransportModeTransforms(Socket socket)
4210bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold            throws IOException {
422f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold        removeTransportModeTransforms(socket.getFileDescriptor$());
423330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
424330e1089da80cddcd68758512370d217b19f8890Nathan Harold
425330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
426c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Remove an IPsec transform from a datagram socket.
427330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
428f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
429f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold     * socket allows the socket to be reused for communication in the clear.
430c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
431c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
432c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
433c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * is called.
434c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
435c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param socket a socket that previously had a transform applied to it
436c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the transform could not be removed from the socket
437330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
438f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold    public void removeTransportModeTransforms(DatagramSocket socket)
4390bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold            throws IOException {
440f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold        removeTransportModeTransforms(socket.getFileDescriptor$());
441330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
442330e1089da80cddcd68758512370d217b19f8890Nathan Harold
443b64993559b049327365bb63e81e8046a892a1033Nathan Harold    /**
444c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Remove an IPsec transform from a socket.
445c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
446f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold     * <p>Once removed, traffic on the socket will not be encrypted. Removing transforms from a
447f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold     * socket allows the socket to be reused for communication in the clear.
448b64993559b049327365bb63e81e8046a892a1033Nathan Harold     *
449c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>If an {@code IpSecTransform} object applied to this socket was deallocated by calling
450c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * {@link IpSecTransform#close()}, then communication on the socket will fail until this method
451c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * is called.
452c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
453c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param socket a socket that previously had a transform applied to it
454c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the transform could not be removed from the socket
455b64993559b049327365bb63e81e8046a892a1033Nathan Harold     */
456f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold    public void removeTransportModeTransforms(FileDescriptor socket)
4570bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold            throws IOException {
4588dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        try (ParcelFileDescriptor pfd = ParcelFileDescriptor.dup(socket)) {
459f73d252c8f51936eec49313f4cc26f1da7727b6cNathan Harold            mService.removeTransportModeTransforms(pfd);
46093962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        } catch (RemoteException e) {
46193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold            throw e.rethrowFromSystemServer();
46293962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        }
46393962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold    }
464330e1089da80cddcd68758512370d217b19f8890Nathan Harold
465330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
466330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * Remove a Tunnel Mode IPsec Transform from a {@link Network}. This must be used as part of
467330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * cleanup if a tunneled Network experiences a change in default route. The Network will drop
468330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * all traffic that cannot be routed to the Tunnel's outbound interface. If that interface is
469330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * lost, all traffic will drop.
470330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
4715fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     * <p>TODO: Update javadoc for tunnel mode APIs at the same time the APIs are re-worked.
4725fb929032de14ca78163e1d0c42c34f6fb287da4Jonathan Basseri     *
473330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param net a network that currently has transform applied to it.
474330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param transform a Tunnel Mode IPsec Transform that has been previously applied to the given
475330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *     network
476330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
477330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
478330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public void removeTunnelModeTransform(Network net, IpSecTransform transform) {}
479330e1089da80cddcd68758512370d217b19f8890Nathan Harold
480330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
481c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * This class provides access to a UDP encapsulation Socket.
482330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
483c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>{@code UdpEncapsulationSocket} wraps a system-provided datagram socket intended for IKEv2
484c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * signalling and UDP encapsulated IPsec traffic. Instances can be obtained by calling {@link
485c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * IpSecManager#openUdpEncapsulationSocket}. The provided socket cannot be re-bound by the
486c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * caller. The caller should not close the {@code FileDescriptor} returned by {@link
487c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * #getSocket}, but should use {@link #close} instead.
488c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     *
489c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>Allowing the user to close or unbind a UDP encapsulation socket could impact the traffic
490c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * of the next user who binds to that port. To prevent this scenario, these sockets are held
491c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * open by the system so that they may only be closed by calling {@link #close} or when the user
492c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * process exits.
493330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
494330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public static final class UdpEncapsulationSocket implements AutoCloseable {
4958dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        private final ParcelFileDescriptor mPfd;
4961afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        private final IIpSecService mService;
4976119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold        private int mResourceId = INVALID_RESOURCE_ID;
4988dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        private final int mPort;
499330e1089da80cddcd68758512370d217b19f8890Nathan Harold        private final CloseGuard mCloseGuard = CloseGuard.get();
500330e1089da80cddcd68758512370d217b19f8890Nathan Harold
50193962f34ce21f5aac825afbcebf2f3e8c7a30910Nathan Harold        private UdpEncapsulationSocket(@NonNull IIpSecService service, int port)
5028dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throws ResourceUnavailableException, IOException {
5031afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold            mService = service;
5048dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            try {
5058dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                IpSecUdpEncapResponse result =
5068dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        mService.openUdpEncapsulationSocket(port, new Binder());
5078dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                switch (result.status) {
5088dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                    case Status.OK:
5098dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        break;
5108dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                    case Status.RESOURCE_UNAVAILABLE:
5118dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        throw new ResourceUnavailableException(
5128dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                                "No more Sockets may be allocated by this requester.");
5138dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                    default:
5148dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                        throw new RuntimeException(
5158dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                                "Unknown status returned by IpSecService: " + result.status);
5168dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                }
5178dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mResourceId = result.resourceId;
5188dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mPort = result.port;
5198dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mPfd = result.fileDescriptor;
5208dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            } catch (RemoteException e) {
5218dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throw e.rethrowFromSystemServer();
5228dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
523330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.open("constructor");
524330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
525330e1089da80cddcd68758512370d217b19f8890Nathan Harold
526c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        /** Get the wrapped socket. */
527330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public FileDescriptor getSocket() {
5288dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            if (mPfd == null) {
5298dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                return null;
5308dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
5318dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            return mPfd.getFileDescriptor();
532330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
533330e1089da80cddcd68758512370d217b19f8890Nathan Harold
534c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        /** Get the bound port of the wrapped socket. */
535330e1089da80cddcd68758512370d217b19f8890Nathan Harold        public int getPort() {
5368dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            return mPort;
537330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
538330e1089da80cddcd68758512370d217b19f8890Nathan Harold
539330e1089da80cddcd68758512370d217b19f8890Nathan Harold        /**
540c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri         * Close this socket.
541330e1089da80cddcd68758512370d217b19f8890Nathan Harold         *
542c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri         * <p>This closes the wrapped socket. Open encapsulation sockets count against a user's
543c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri         * resource limits, and forgetting to close them eventually will result in {@link
544c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri         * ResourceUnavailableException} being thrown.
545330e1089da80cddcd68758512370d217b19f8890Nathan Harold         */
546c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        @Override
5470bfb2075320a9f648fc2b3fcdfc58f425c9a685aNathan Harold        public void close() throws IOException {
5488dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            try {
5498dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mService.closeUdpEncapsulationSocket(mResourceId);
5506119d8d1d0d89b0d4c4ac822e9e93bb47f1ebd9aNathan Harold                mResourceId = INVALID_RESOURCE_ID;
5518dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            } catch (RemoteException e) {
5528dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throw e.rethrowFromSystemServer();
5538dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
5548dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold
5558dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            try {
5568dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                mPfd.close();
5578dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            } catch (IOException e) {
5588dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                Log.e(TAG, "Failed to close UDP Encapsulation Socket with Port= " + mPort);
5598dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold                throw e;
5608dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            }
561330e1089da80cddcd68758512370d217b19f8890Nathan Harold            mCloseGuard.close();
562330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
563330e1089da80cddcd68758512370d217b19f8890Nathan Harold
564c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri        /** Check that the socket was closed properly. */
565330e1089da80cddcd68758512370d217b19f8890Nathan Harold        @Override
566330e1089da80cddcd68758512370d217b19f8890Nathan Harold        protected void finalize() throws Throwable {
567330e1089da80cddcd68758512370d217b19f8890Nathan Harold            if (mCloseGuard != null) {
568330e1089da80cddcd68758512370d217b19f8890Nathan Harold                mCloseGuard.warnIfOpen();
569330e1089da80cddcd68758512370d217b19f8890Nathan Harold            }
570330e1089da80cddcd68758512370d217b19f8890Nathan Harold            close();
571330e1089da80cddcd68758512370d217b19f8890Nathan Harold        }
5728dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold
5738dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        /** @hide */
574a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold        @VisibleForTesting
575a10003d5de52339f4d30fedd7294941378e5f13cNathan Harold        public int getResourceId() {
5768dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            return mResourceId;
5778dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
578330e1089da80cddcd68758512370d217b19f8890Nathan Harold    };
579330e1089da80cddcd68758512370d217b19f8890Nathan Harold
580330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
581c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Open a socket for UDP encapsulation and bind to the given port.
582330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
583c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket.
584330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
585c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @param port a local UDP port
586c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @return a socket that is bound to the given port
587c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the socket could not be opened or bound
588c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
589330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
590330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // Returning a socket in this fashion that has been created and bound by the system
591330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // is the only safe way to ensure that a socket is both accessible to the user and
592330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // safely usable for Encapsulation without allowing a user to possibly unbind from/close
593330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // the port, which could potentially impact the traffic of the next user who binds to that
594330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // socket.
595330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public UdpEncapsulationSocket openUdpEncapsulationSocket(int port)
596330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException, ResourceUnavailableException {
5978dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        /*
5988dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold         * Most range checking is done in the service, but this version of the constructor expects
5998dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold         * a valid port number, and zero cannot be checked after being passed to the service.
6008dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold         */
6018dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        if (port == 0) {
6028dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold            throw new IllegalArgumentException("Specified port must be a valid port number!");
6038dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        }
6041afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold        return new UdpEncapsulationSocket(mService, port);
605330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
606330e1089da80cddcd68758512370d217b19f8890Nathan Harold
607330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
608c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Open a socket for UDP encapsulation.
609330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
610c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>See {@link UdpEncapsulationSocket} for the proper way to close the returned socket.
611330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
612c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * <p>The local port of the returned socket can be obtained by calling {@link
613c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * UdpEncapsulationSocket#getPort()}.
614330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
615c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @return a socket that is bound to a local port
616c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws IOException indicating that the socket could not be opened or bound
617c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
618330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
619330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // Returning a socket in this fashion that has been created and bound by the system
620330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // is the only safe way to ensure that a socket is both accessible to the user and
621330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // safely usable for Encapsulation without allowing a user to possibly unbind from/close
622330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // the port, which could potentially impact the traffic of the next user who binds to that
623330e1089da80cddcd68758512370d217b19f8890Nathan Harold    // socket.
624330e1089da80cddcd68758512370d217b19f8890Nathan Harold    public UdpEncapsulationSocket openUdpEncapsulationSocket()
625330e1089da80cddcd68758512370d217b19f8890Nathan Harold            throws IOException, ResourceUnavailableException {
6268dc1fd0237992e1d693376b4f6eea45e7447e9dbNathan Harold        return new UdpEncapsulationSocket(mService, 0);
627330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
628330e1089da80cddcd68758512370d217b19f8890Nathan Harold
629330e1089da80cddcd68758512370d217b19f8890Nathan Harold    /**
630c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * This class represents an IpSecTunnelInterface
631c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *
632c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * <p>IpSecTunnelInterface objects track tunnel interfaces that serve as
633c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * local endpoints for IPsec tunnels.
634c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *
635c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * <p>Creating an IpSecTunnelInterface creates a device to which IpSecTransforms may be
636c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * applied to provide IPsec security to packets sent through the tunnel. While a tunnel
637c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * cannot be used in standalone mode within Android, the higher layers may use the tunnel
638c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * to create Network objects which are accessible to the Android system.
639c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @hide
640c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     */
641c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    @SystemApi
642c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    public static final class IpSecTunnelInterface implements AutoCloseable {
643c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private final IIpSecService mService;
644c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private final InetAddress mRemoteAddress;
645c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private final InetAddress mLocalAddress;
646c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private final Network mUnderlyingNetwork;
647c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private final CloseGuard mCloseGuard = CloseGuard.get();
648c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private String mInterfaceName;
649c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private int mResourceId = INVALID_RESOURCE_ID;
650c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
651c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        /** Get the underlying SPI held by this object. */
652c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        public String getInterfaceName() {
653c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            return mInterfaceName;
654c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        }
655c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
656c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        /**
657c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * Add an address to the IpSecTunnelInterface
658c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         *
659c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * <p>Add an address which may be used as the local inner address for
660c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * tunneled traffic.
661c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         *
662c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * @param address the local address for traffic inside the tunnel
663c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * @throws IOException if the address could not be added
664c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * @hide
665c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         */
666c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        public void addAddress(LinkAddress address) throws IOException {
667c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        }
668c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
669c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        /**
670c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * Remove an address from the IpSecTunnelInterface
671c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         *
672c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * <p>Remove an address which was previously added to the IpSecTunnelInterface
673c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         *
674c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * @param address to be removed
675c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * @throws IOException if the address could not be removed
676c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * @hide
677c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         */
678c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        public void removeAddress(LinkAddress address) throws IOException {
679c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        }
680c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
681c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        private IpSecTunnelInterface(@NonNull IIpSecService service,
682c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold                @NonNull InetAddress localAddress, @NonNull InetAddress remoteAddress,
683c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold                @NonNull Network underlyingNetwork)
684c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold                throws ResourceUnavailableException, IOException {
685c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            mService = service;
686c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            mLocalAddress = localAddress;
687c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            mRemoteAddress = remoteAddress;
688c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            mUnderlyingNetwork = underlyingNetwork;
6898149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong
6908149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            try {
6918149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                IpSecTunnelInterfaceResponse result =
6928149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                        mService.createTunnelInterface(
6938149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                                localAddress.getHostAddress(),
6948149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                                remoteAddress.getHostAddress(),
6958149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                                underlyingNetwork,
6968149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                                new Binder());
6978149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                switch (result.status) {
6988149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                    case Status.OK:
6998149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                        break;
7008149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                    case Status.RESOURCE_UNAVAILABLE:
7018149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                        throw new ResourceUnavailableException(
7028149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                                "No more tunnel interfaces may be allocated by this requester.");
7038149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                    default:
7048149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                        throw new RuntimeException(
7058149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                                "Unknown status returned by IpSecService: " + result.status);
7068149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                }
7078149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                mResourceId = result.resourceId;
7088149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                mInterfaceName = result.interfaceName;
7098149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            } catch (RemoteException e) {
7108149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                throw e.rethrowFromSystemServer();
7118149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            }
7128149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            mCloseGuard.open("constructor");
713c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        }
714c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
715c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        /**
716c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * Delete an IpSecTunnelInterface
717c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         *
718c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * <p>Calling close will deallocate the IpSecTunnelInterface and all of its system
719c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * resources. Any packets bound for this interface either inbound or outbound will
720c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         * all be lost.
721c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold         */
722c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        @Override
723c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        public void close() {
7248149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            try {
7258149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                mService.deleteTunnelInterface(mResourceId);
7268149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                mResourceId = INVALID_RESOURCE_ID;
7278149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            } catch (RemoteException e) {
7288149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                throw e.rethrowFromSystemServer();
7298149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            }
730c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            mCloseGuard.close();
731c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        }
732c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
733c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        /** Check that the Interface was closed properly. */
734c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        @Override
735c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        protected void finalize() throws Throwable {
736c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            if (mCloseGuard != null) {
737c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold                mCloseGuard.warnIfOpen();
738c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            }
739c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            close();
740c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        }
7418149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong
7428149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        /** @hide */
7438149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        @VisibleForTesting
7448149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        public int getResourceId() {
7458149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            return mResourceId;
7468149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        }
747c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    }
748c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
749c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    /**
750c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * Create a new IpSecTunnelInterface as a local endpoint for tunneled IPsec traffic.
751c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *
7528149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong     * <p>An application that creates tunnels is responsible for cleaning up the tunnel when the
7538149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong     * underlying network goes away, and the onLost() callback is received.
7548149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong     *
755c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @param localAddress The local addres of the tunnel
756c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @param remoteAddress The local addres of the tunnel
757c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @param underlyingNetwork the {@link Network} that will carry traffic for this tunnel.
758c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *        This network should almost certainly be a network such as WiFi with an L2 address.
759c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @return a new {@link IpSecManager#IpSecTunnelInterface} with the specified properties
760c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @throws IOException indicating that the socket could not be opened or bound
761c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @throws ResourceUnavailableException indicating that too many encapsulation sockets are open
762c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @hide
763c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     */
764c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    @SystemApi
7655a920ca377efaaaaabf3fe6c77111d8158202055Nathan Harold    @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
766c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    public IpSecTunnelInterface createIpSecTunnelInterface(@NonNull InetAddress localAddress,
767c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            @NonNull InetAddress remoteAddress, @NonNull Network underlyingNetwork)
768c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            throws ResourceUnavailableException, IOException {
769c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold        return new IpSecTunnelInterface(mService, localAddress, remoteAddress, underlyingNetwork);
770c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    }
771c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold
772c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    /**
773c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * Apply a transform to the IpSecTunnelInterface
774c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *
775c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @param tunnel The {@link IpSecManager#IpSecTunnelInterface} that will use the supplied
776c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *        transform.
777c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @param direction the direction, {@link DIRECTION_OUT} or {@link #DIRECTION_IN} in which
778c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *        the transform will be used.
779c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @param transform an {@link IpSecTransform} created in tunnel mode
780c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @throws IOException indicating that the transform could not be applied due to a lower
781c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     *         layer failure.
782c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     * @hide
783c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold     */
784c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    @SystemApi
7855a920ca377efaaaaabf3fe6c77111d8158202055Nathan Harold    @RequiresPermission(android.Manifest.permission.NETWORK_STACK)
786e0d448f31eb9f7e63d13ef45b04853d95c00670aBenedict Wong    public void applyTunnelModeTransform(IpSecTunnelInterface tunnel, int direction,
787c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold            IpSecTransform transform) throws IOException {
7888149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        try {
7898149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            mService.applyTunnelModeTransform(
7908149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong                    tunnel.getResourceId(), direction, transform.getResourceId());
7918149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        } catch (RemoteException e) {
7928149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong            throw e.rethrowFromSystemServer();
7938149f6eb6c0280078dc41d72027d1241e875ea02Benedict Wong        }
794c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    }
795c47eaccf7c09541c6dd3d3ebedcb2e224346d903Nathan Harold    /**
796c61b70d12d23da97013ee5e44f101609215d1bffJonathan Basseri     * Construct an instance of IpSecManager within an application context.
797330e1089da80cddcd68758512370d217b19f8890Nathan Harold     *
798330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @param context the application context for this manager
799330e1089da80cddcd68758512370d217b19f8890Nathan Harold     * @hide
800330e1089da80cddcd68758512370d217b19f8890Nathan Harold     */
8011afbef40c68373f3871eed087c546cfe1911ee36Nathan Harold    public IpSecManager(IIpSecService service) {
802330e1089da80cddcd68758512370d217b19f8890Nathan Harold        mService = checkNotNull(service, "missing service");
803330e1089da80cddcd68758512370d217b19f8890Nathan Harold    }
804330e1089da80cddcd68758512370d217b19f8890Nathan Harold}
805